Do not use CoreJavaFileManager in KotlinCliJavaFileManagerImpl
The inheritance is still needed because of the code in intellij-core, specifically in JavaCoreProjectEnvironment.addSourcesToClasspath and CoreJavaDirectoryService.getPackage, which assumes that the JavaFileManager instance in the project is a CoreJavaFileManager
This commit is contained in:
+37
-29
@@ -20,10 +20,7 @@ import com.intellij.core.CoreJavaFileManager
|
|||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiClassOwner
|
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import com.intellij.psi.PsiPackage
|
|
||||||
import com.intellij.psi.impl.file.PsiPackageImpl
|
import com.intellij.psi.impl.file.PsiPackageImpl
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||||
@@ -35,6 +32,9 @@ import org.jetbrains.kotlin.util.PerformanceCounter
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.properties.Delegates
|
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 {
|
class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
|
||||||
private val perfCounter = PerformanceCounter.create("Find Java class")
|
private val perfCounter = PerformanceCounter.create("Find Java class")
|
||||||
private var index: JvmDependenciesIndex by Delegates.notNull()
|
private var index: JvmDependenciesIndex by Delegates.notNull()
|
||||||
@@ -44,13 +44,11 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
|||||||
this.index = packagesCache
|
this.index = packagesCache
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? {
|
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time {
|
||||||
return perfCounter.time {
|
val relativeClassName = classId.relativeClassName.asString()
|
||||||
val classNameWithInnerClasses = classId.relativeClassName.asString()
|
index.findClass(classId) { dir, type ->
|
||||||
index.findClass(classId) { dir, type ->
|
findClassGivenPackage(allScope, dir, relativeClassName, type)
|
||||||
findClassGivenPackage(allScope, dir, classNameWithInnerClasses, type)
|
}?.takeIf { it.containingFile.virtualFile in searchScope }
|
||||||
}?.takeIf { it.containingFile.virtualFile in searchScope }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is called from IDEA to resolve dependencies in Java code
|
// 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
|
// 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
|
// "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) {
|
while (true) {
|
||||||
findClass(classId, scope)?.let { return it }
|
block(classId)
|
||||||
|
|
||||||
val packageFqName = classId.packageFqName
|
val packageFqName = classId.packageFqName
|
||||||
if (packageFqName.isRoot) break
|
if (packageFqName.isRoot) break
|
||||||
@@ -76,31 +82,26 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.findClass(qName, scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> = perfCounter.time {
|
||||||
return perfCounter.time {
|
val result = ArrayList<PsiClass>(1)
|
||||||
val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return@time super.findClasses(qName, scope)
|
forEachClassId(qName) { classId ->
|
||||||
|
val relativeClassName = classId.relativeClassName.asString()
|
||||||
val result = ArrayList<PsiClass>()
|
index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
|
||||||
val classNameWithInnerClasses = classIdAsTopLevelClass.relativeClassName.asString()
|
val psiClass = findClassGivenPackage(scope, dir, relativeClassName, rootType)
|
||||||
index.traverseDirectoriesInPackage(classIdAsTopLevelClass.packageFqName) { dir, rootType ->
|
|
||||||
val psiClass = findClassGivenPackage(scope, dir, classNameWithInnerClasses, rootType)
|
|
||||||
if (psiClass != null) {
|
if (psiClass != null) {
|
||||||
result.add(psiClass)
|
result.add(psiClass)
|
||||||
}
|
}
|
||||||
// traverse all
|
// traverse all
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
if (result.isEmpty()) {
|
if (result.isNotEmpty()) {
|
||||||
super.findClasses(qName, scope)
|
return@time result.toTypedArray()
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.toTypedArray()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PsiClass.EMPTY_ARRAY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findPackage(packageName: String): PsiPackage? {
|
override fun findPackage(packageName: String): PsiPackage? {
|
||||||
@@ -157,6 +158,13 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection<PsiJavaModule> {
|
||||||
|
// TODO
|
||||||
|
return emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getNonTrivialPackagePrefixes(): Collection<String> = emptyList()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java)
|
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.toSafeFqName(): FqName? = safely { FqName(this) }
|
||||||
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
|
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
|
||||||
|
|||||||
Reference in New Issue
Block a user