diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt index b5f2ac06bb7..7b5c6ee39bf 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt @@ -20,10 +20,7 @@ import com.intellij.core.CoreJavaFileManager import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassOwner -import com.intellij.psi.PsiManager -import com.intellij.psi.PsiPackage +import com.intellij.psi.* import com.intellij.psi.impl.file.PsiPackageImpl import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.cli.jvm.index.JavaRoot @@ -35,6 +32,9 @@ import org.jetbrains.kotlin.util.PerformanceCounter import java.util.* import kotlin.properties.Delegates +// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices +// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage, +// which is indirectly invoked from PsiPackage.getSubPackages class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager { private val perfCounter = PerformanceCounter.create("Find Java class") private var index: JvmDependenciesIndex by Delegates.notNull() @@ -44,13 +44,11 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ this.index = packagesCache } - override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? { - return perfCounter.time { - val classNameWithInnerClasses = classId.relativeClassName.asString() - index.findClass(classId) { dir, type -> - findClassGivenPackage(allScope, dir, classNameWithInnerClasses, type) - }?.takeIf { it.containingFile.virtualFile in searchScope } - } + override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time { + val relativeClassName = classId.relativeClassName.asString() + index.findClass(classId) { dir, type -> + findClassGivenPackage(allScope, dir, relativeClassName, type) + }?.takeIf { it.containingFile.virtualFile in searchScope } } // this method is called from IDEA to resolve dependencies in Java code @@ -62,10 +60,18 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ // Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package // "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly - var classId = qName.toSafeTopLevelClassId() ?: return super.findClass(qName, scope) + forEachClassId(qName) { classId -> + findClass(classId, scope)?.let { return it } + } + + return null + } + + private inline fun forEachClassId(fqName: String, block: (ClassId) -> Unit) { + var classId = fqName.toSafeTopLevelClassId() ?: return while (true) { - findClass(classId, scope)?.let { return it } + block(classId) val packageFqName = classId.packageFqName if (packageFqName.isRoot) break @@ -76,31 +82,26 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ false ) } - - return super.findClass(qName, scope) } - override fun findClasses(qName: String, scope: GlobalSearchScope): Array { - return perfCounter.time { - val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return@time super.findClasses(qName, scope) - - val result = ArrayList() - val classNameWithInnerClasses = classIdAsTopLevelClass.relativeClassName.asString() - index.traverseDirectoriesInPackage(classIdAsTopLevelClass.packageFqName) { dir, rootType -> - val psiClass = findClassGivenPackage(scope, dir, classNameWithInnerClasses, rootType) + override fun findClasses(qName: String, scope: GlobalSearchScope): Array = perfCounter.time { + val result = ArrayList(1) + forEachClassId(qName) { classId -> + val relativeClassName = classId.relativeClassName.asString() + index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType -> + val psiClass = findClassGivenPackage(scope, dir, relativeClassName, rootType) if (psiClass != null) { result.add(psiClass) } // traverse all true } - if (result.isEmpty()) { - super.findClasses(qName, scope) - } - else { - result.toTypedArray() + if (result.isNotEmpty()) { + return@time result.toTypedArray() } } + + PsiClass.EMPTY_ARRAY } override fun findPackage(packageName: String): PsiPackage? { @@ -157,6 +158,13 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ return result } + override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection { + // TODO + return emptySet() + } + + override fun getNonTrivialPackagePrefixes(): Collection = emptyList() + companion object { private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java) @@ -202,4 +210,4 @@ catch (e: AssertionError) { } private fun String.toSafeFqName(): FqName? = safely { FqName(this) } -private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } \ No newline at end of file +private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }