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)
}
//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
override fun processAllClassNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
return KotlinClassShortNameIndex.getInstance().processAllKeys(project, processor) &&
KotlinFileFacadeShortNameIndex.INSTANCE.processAllKeys(project, processor)
}
override fun processAllClassNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
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.
*/
override fun getAllClassNames(): Array<String> {
if (disableSearch.get()) return ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllClassNames(processor)
}
@@ -78,6 +86,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope,
filter: IdFilter?
): Boolean {
if (disableSearch.get()) return true
val effectiveScope = kotlinDeclarationsVisibleFromJavaScope(scope)
val fqNameProcessor = Processor<FqName> { fqName: FqName? ->
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.
*/
override fun getClassesByName(name: String, scope: GlobalSearchScope): Array<PsiClass> {
if (disableSearch.get()) return PsiClass.EMPTY_ARRAY
return withArrayProcessor(PsiClass.EMPTY_ARRAY) { processor ->
processClassesWithName(name, processor, scope, null)
}
@@ -150,16 +160,19 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
//region Methods
override fun processAllMethodNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
return processAllMethodNames(processor)
}
override fun getAllMethodNames(): Array<String> {
if (disableSearch.get()) ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllMethodNames(processor)
}
}
private fun processAllMethodNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
if (!KotlinFunctionShortNameIndex.getInstance().processAllKeys(project, processor)) {
return false
}
@@ -175,6 +188,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope,
filter: IdFilter?
): Boolean {
if (disableSearch.get()) return true
val allFunctionsProcessed = StubIndex.getInstance().processElements(
KotlinFunctionShortNameIndex.getInstance().key,
name,
@@ -220,12 +234,14 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
}
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod> {
if (disableSearch.get()) return PsiMethod.EMPTY_ARRAY
return withArrayProcessor(PsiMethod.EMPTY_ARRAY) { processor ->
processMethodsWithName(name, processor, scope, null)
}
}
override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiMethod> {
if (disableSearch.get()) return PsiMethod.EMPTY_ARRAY
require(maxCount >= 0)
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 =
ContainerUtil.process(getMethodsByName(name, scope), processor)
override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean {
if (disableSearch.get()) return true
return ContainerUtil.process(getMethodsByName(name, scope), processor)
}
//endregion
//region Fields
override fun processAllFieldNames(processor: Processor<String>, scope: GlobalSearchScope, filter: IdFilter?): Boolean {
if (disableSearch.get()) return true
return processAllFieldNames(processor)
}
override fun getAllFieldNames(): Array<String> {
if (disableSearch.get()) return ArrayUtil.EMPTY_STRING_ARRAY
return withArrayProcessor(ArrayUtil.EMPTY_STRING_ARRAY) { processor ->
processAllFieldNames(processor)
}
}
private fun processAllFieldNames(processor: Processor<String>): Boolean {
if (disableSearch.get()) return true
return KotlinPropertyShortNameIndex.getInstance().processAllKeys(project, processor)
}
@@ -266,6 +287,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
scope: GlobalSearchScope,
filter: IdFilter?
): Boolean {
if (disableSearch.get()) return true
return StubIndex.getInstance().processElements(
KotlinPropertyShortNameIndex.getInstance().key,
name,
@@ -282,12 +304,14 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
}
override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField> {
if (disableSearch.get()) return PsiField.EMPTY_ARRAY
return withArrayProcessor(PsiField.EMPTY_ARRAY) { processor ->
processFieldsWithName(name, processor, scope, null)
}
}
override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiField> {
if (disableSearch.get()) return PsiField.EMPTY_ARRAY
require(maxCount >= 0)
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.psi.PsiClass
import com.intellij.psi.PsiLiteral
import com.intellij.psi.search.PsiShortNamesCache
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
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.isJavaClassNotToBeUsedInKotlin
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
@@ -86,21 +88,29 @@ class AllClassesCompletion(private val parameters: CompletionParameters,
}
private fun addAdaptedJavaCompletion(collector: (PsiClass) -> Unit) {
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 shortNamesCache = PsiShortNamesCache.EP_NAME.getExtensions(parameters.editor.project).firstOrNull {
it is KotlinShortNamesCache
} 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 {
psiClass.isAnnotationType -> ClassKind.ANNOTATION_CLASS
psiClass.isInterface -> ClassKind.INTERFACE
psiClass.isEnum -> ClassKind.ENUM_CLASS
else -> ClassKind.CLASS
}
if (kindFilter(kind) && !isNotToBeUsed(psiClass)) {
collector(psiClass)
val kind = when {
psiClass.isAnnotationType -> ClassKind.ANNOTATION_CLASS
psiClass.isInterface -> ClassKind.INTERFACE
psiClass.isEnum -> ClassKind.ENUM_CLASS
else -> ClassKind.CLASS
}
if (kindFilter(kind) && !isNotToBeUsed(psiClass)) {
collector(psiClass)
}
}
}
})
} finally {
shortNamesCache?.disableSearch?.set(false)
}
}
private fun PsiClass.isSyntheticKotlinClass(): Boolean {