Do not search for Kotlin classes, when looking for Java classes

This commit is contained in:
Alexander Podkhalyuzin
2019-05-27 18:33:35 +02:00
committed by Vladimir Dolzhenko
parent 91ac38aaf4
commit 661d50de18
2 changed files with 48 additions and 14 deletions
@@ -52,14 +52,21 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
private val LOG = Logger.getInstance(KotlinShortNamesCache::class.java) private val LOG = Logger.getInstance(KotlinShortNamesCache::class.java)
} }
//hacky way to avoid searches for Kotlin classes, when looking for Java (from Kotlin)
val disableSearch: ThreadLocal<Boolean> = object : ThreadLocal<Boolean>() {
override fun initialValue(): Boolean = false
}
//region Classes //region Classes
override fun processAllClassNames(processor: Processor<String>): Boolean { override fun processAllClassNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
return KotlinClassShortNameIndex.getInstance().processAllKeys(project, processor) && return KotlinClassShortNameIndex.getInstance().processAllKeys(project, processor) &&
KotlinFileFacadeShortNameIndex.INSTANCE.processAllKeys(project, processor) KotlinFileFacadeShortNameIndex.INSTANCE.processAllKeys(project, processor)
} }
override fun processAllClassNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean { override fun processAllClassNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
return processAllClassNames(processor) return processAllClassNames(processor)
} }
@@ -67,6 +74,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
* Return kotlin class names from project sources which should be visible from java. * Return kotlin class names from project sources which should be visible from java.
*/ */
override fun getAllClassNames(): Array<String> { override fun getAllClassNames(): Array<String> {
if (disableSearch.get()) return ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor -> return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllClassNames(processor) processAllClassNames(processor)
} }
@@ -78,6 +86,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope, scope: GlobalSearchScope,
filter: IdFilter? filter: IdFilter?
): Boolean { ): Boolean {
if (disableSearch.get()) return true
val effectiveScope = kotlinDeclarationsVisibleFromJavaScope(scope) val effectiveScope = kotlinDeclarationsVisibleFromJavaScope(scope)
val fqNameProcessor = Processor<FqName> { fqName: FqName? -> val fqNameProcessor = Processor<FqName> { fqName: FqName? ->
if (fqName == null) return@Processor true if (fqName == null) return@Processor true
@@ -131,6 +140,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
* Return class names form kotlin sources in given scope which should be visible as Java classes. * Return class names form kotlin sources in given scope which should be visible as Java classes.
*/ */
override fun getClassesByName(name: String, scope: GlobalSearchScope): Array<PsiClass> { override fun getClassesByName(name: String, scope: GlobalSearchScope): Array<PsiClass> {
if (disableSearch.get()) return PsiClass.EMPTY_ARRAY
return withArrayProcessor(PsiClass.EMPTY_ARRAY) { processor -> return withArrayProcessor(PsiClass.EMPTY_ARRAY) { processor ->
processClassesWithName(name, processor, scope, null) processClassesWithName(name, processor, scope, null)
} }
@@ -150,16 +160,19 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
//region Methods //region Methods
override fun processAllMethodNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean { override fun processAllMethodNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
return processAllMethodNames(processor) return processAllMethodNames(processor)
} }
override fun getAllMethodNames(): Array<String> { override fun getAllMethodNames(): Array<String> {
if (disableSearch.get()) ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor -> return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllMethodNames(processor) processAllMethodNames(processor)
} }
} }
private fun processAllMethodNames(processor: Processor<String>): Boolean { private fun processAllMethodNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
if (!KotlinFunctionShortNameIndex.getInstance().processAllKeys(project, processor)) { if (!KotlinFunctionShortNameIndex.getInstance().processAllKeys(project, processor)) {
return false return false
} }
@@ -175,6 +188,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope, scope: GlobalSearchScope,
filter: IdFilter? filter: IdFilter?
): Boolean { ): Boolean {
if (disableSearch.get()) return true
val allFunctionsProcessed = StubIndex.getInstance().processElements( val allFunctionsProcessed = StubIndex.getInstance().processElements(
KotlinFunctionShortNameIndex.getInstance().key, KotlinFunctionShortNameIndex.getInstance().key,
name, name,
@@ -220,12 +234,14 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
} }
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod> { override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod> {
if (disableSearch.get()) return PsiMethod.EMPTY_ARRAY
return withArrayProcessor(PsiMethod.EMPTY_ARRAY) { processor -> return withArrayProcessor(PsiMethod.EMPTY_ARRAY) { processor ->
processMethodsWithName(name, processor, scope, null) processMethodsWithName(name, processor, scope, null)
} }
} }
override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiMethod> { override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiMethod> {
if (disableSearch.get()) return PsiMethod.EMPTY_ARRAY
require(maxCount >= 0) require(maxCount >= 0)
return withArrayProcessor(PsiMethod.EMPTY_ARRAY) { processor -> return withArrayProcessor(PsiMethod.EMPTY_ARRAY) { processor ->
@@ -240,23 +256,28 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
} }
} }
override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean = override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean {
ContainerUtil.process(getMethodsByName(name, scope), processor) if (disableSearch.get()) return true
return ContainerUtil.process(getMethodsByName(name, scope), processor)
}
//endregion //endregion
//region Fields //region Fields
override fun processAllFieldNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean { override fun processAllFieldNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
return processAllFieldNames(processor) return processAllFieldNames(processor)
} }
override fun getAllFieldNames(): Array<String> { override fun getAllFieldNames(): Array<String> {
if (disableSearch.get()) return ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor -> return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllFieldNames(processor) processAllFieldNames(processor)
} }
} }
private fun processAllFieldNames(processor: Processor<String>): Boolean { private fun processAllFieldNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
return KotlinPropertyShortNameIndex.getInstance().processAllKeys(project, processor) return KotlinPropertyShortNameIndex.getInstance().processAllKeys(project, processor)
} }
@@ -266,6 +287,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope, scope: GlobalSearchScope,
filter: IdFilter? filter: IdFilter?
): Boolean { ): Boolean {
if (disableSearch.get()) return true
return StubIndex.getInstance().processElements( return StubIndex.getInstance().processElements(
KotlinPropertyShortNameIndex.getInstance().key, KotlinPropertyShortNameIndex.getInstance().key,
name, name,
@@ -282,12 +304,14 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
} }
override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField> { override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField> {
if (disableSearch.get()) return PsiField.EMPTY_ARRAY
return withArrayProcessor(PsiField.EMPTY_ARRAY) { processor -> return withArrayProcessor(PsiField.EMPTY_ARRAY) { processor ->
processFieldsWithName(name, processor, scope, null) processFieldsWithName(name, processor, scope, null)
} }
} }
override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiField> { override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiField> {
if (disableSearch.get()) return PsiField.EMPTY_ARRAY
require(maxCount >= 0) require(maxCount >= 0)
return withArrayProcessor(PsiField.EMPTY_ARRAY) { processor -> return withArrayProcessor(PsiField.EMPTY_ARRAY) { processor ->
@@ -21,10 +21,12 @@ import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.PrefixMatcher import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.PsiLiteral import com.intellij.psi.PsiLiteral
import com.intellij.psi.search.PsiShortNamesCache
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.idea.caches.KotlinShortNamesCache
import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper
import org.jetbrains.kotlin.idea.core.isJavaClassNotToBeUsedInKotlin import org.jetbrains.kotlin.idea.core.isJavaClassNotToBeUsedInKotlin
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
@@ -86,21 +88,29 @@ class AllClassesCompletion(private val parameters: CompletionParameters,
} }
private fun addAdaptedJavaCompletion(collector: (PsiClass) -> Unit) { private fun addAdaptedJavaCompletion(collector: (PsiClass) -> Unit) {
AllClassesGetter.processJavaClasses(parameters, prefixMatcher, true, { psiClass -> val shortNamesCache = PsiShortNamesCache.EP_NAME.getExtensions(parameters.editor.project).firstOrNull {
if (psiClass!! !is KtLightClass) { // Kotlin class should have already been added as kotlin element before it is KotlinShortNamesCache
if (psiClass.isSyntheticKotlinClass()) return@processJavaClasses // filter out synthetic classes produced by Kotlin compiler } as KotlinShortNamesCache?
shortNamesCache?.disableSearch?.set(true)
try {
AllClassesGetter.processJavaClasses(parameters, prefixMatcher, true) { psiClass ->
if (psiClass!! !is KtLightClass) { // Kotlin class should have already been added as kotlin element before
if (psiClass.isSyntheticKotlinClass()) return@processJavaClasses // filter out synthetic classes produced by Kotlin compiler
val kind = when { val kind = when {
psiClass.isAnnotationType -> ClassKind.ANNOTATION_CLASS psiClass.isAnnotationType -> ClassKind.ANNOTATION_CLASS
psiClass.isInterface -> ClassKind.INTERFACE psiClass.isInterface -> ClassKind.INTERFACE
psiClass.isEnum -> ClassKind.ENUM_CLASS psiClass.isEnum -> ClassKind.ENUM_CLASS
else -> ClassKind.CLASS else -> ClassKind.CLASS
} }
if (kindFilter(kind) && !isNotToBeUsed(psiClass)) { if (kindFilter(kind) && !isNotToBeUsed(psiClass)) {
collector(psiClass) collector(psiClass)
}
} }
} }
}) } finally {
shortNamesCache?.disableSearch?.set(false)
}
} }
private fun PsiClass.isSyntheticKotlinClass(): Boolean { private fun PsiClass.isSyntheticKotlinClass(): Boolean {