[lc] KotlinAsJavaSupportBase: implement getLightClass

add more caching

^KT-50241
This commit is contained in:
Dmitry Gridin
2022-09-01 17:37:01 +02:00
committed by Space
parent 2d0e95cea0
commit 46548e5443
15 changed files with 184 additions and 140 deletions
@@ -12,12 +12,12 @@ import com.intellij.psi.scope.PsiScopeProcessor
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateSymbolLightClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class SymbolFakeFile(private val classOrObject: KtClassOrObject, ktClass: KtLightClass) : FakeFileForLightClass(
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) ktClass else getOrCreateSymbolLightClass(getOutermostClassOrObject(classOrObject))!! },
{ if (classOrObject.isTopLevel()) ktClass else getOutermostClassOrObject(classOrObject).toLightClass()!! },
) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
@@ -8,16 +8,14 @@ package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.ModificationTracker
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.decompiled.light.classes.DecompiledLightClassesFactory
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.analysis.providers.createAllLibrariesModificationTracker
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupportBase
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
@@ -25,7 +23,7 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolBasedFakeLightClass
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForFacade
import org.jetbrains.kotlin.light.classes.symbol.classes.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateSymbolLightClass
import org.jetbrains.kotlin.light.classes.symbol.classes.createSymbolLightClassNoCache
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull
@@ -89,28 +87,41 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
.getKotlinSubPackageFqNames(fqn)
.map { fqn.child(it) }
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? {
return when (classOrObject.getKtModule(project)) {
is KtSourceModule -> getOrCreateSymbolLightClass(classOrObject)
is KtLibraryModule -> DecompiledLightClassesFactory.getLightClassForDecompiledClassOrObject(classOrObject, project)
else -> null
}
}
override fun getLightClassForScript(script: KtScript): KtLightClass = error("Should not be called")
override fun KtFile.findModule(): KtModule = getKtModule(project)
override fun declarationLocation(file: KtFile, module: KtModule): DeclarationLocation? = when (module) {
is KtSourceModule -> DeclarationLocation.ProjectSources
is KtLibraryModule -> DeclarationLocation.LibraryClasses
is KtLibrarySourceModule -> DeclarationLocation.LibrarySources
else -> null
}
override fun createInstanceOfDecompiledLightClass(classOrObject: KtClassOrObject, module: KtModule): KtLightClass? {
return DecompiledLightClassesFactory.getLightClassForDecompiledClassOrObject(classOrObject, project)
}
override fun createInstanceOfLightClass(classOrObject: KtClassOrObject, module: KtModule): KtLightClass? {
return createSymbolLightClassNoCache(classOrObject)
}
override fun createInstanceOfDecompiledLightFacade(
facadeFqName: FqName,
files: List<KtFile>,
module: KtModule,
): KtLightClassForFacade? = DecompiledLightClassesFactory.createLightFacadeForDecompiledKotlinFile(project, facadeFqName, files)
override fun tracker(file: KtFile): ModificationTracker = when (val module = file.getKtModule(project)) {
is KtSourceModule -> module.createModuleWithoutDependenciesOutOfBlockModificationTracker(project)
is KtLibraryModule -> project.createAllLibrariesModificationTracker()
else -> super.tracker(file)
override fun projectWideOutOfBlockModificationTracker(): ModificationTracker {
return project.createProjectWideOutOfBlockModificationTracker()
}
override fun outOfBlockModificationTracker(element: PsiElement, module: KtModule): ModificationTracker {
return project.createProjectWideOutOfBlockModificationTracker()
}
override fun librariesTracker(element: PsiElement, module: KtModule): ModificationTracker {
return project.createAllLibrariesModificationTracker()
}
override fun createInstanceOfLightFacade(
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.asJava.classes.getParentForLocalDeclaration
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.light.classes.symbol.SymbolFakeFile
import org.jetbrains.kotlin.light.classes.symbol.SymbolLightIdentifier
import org.jetbrains.kotlin.light.classes.symbol.allowLightClassesOnEdt
@@ -160,7 +161,7 @@ internal abstract class SymbolLightClassForClassOrObject(
val kotlinOrigin = kotlinOrigin ?: return@lazyPub null
val containingClass = isTopLevel.ifFalse { getOrCreateSymbolLightClass(getOutermostClassOrObject(kotlinOrigin)) } ?: this
val containingClass = isTopLevel.ifFalse { getOutermostClassOrObject(kotlinOrigin).toLightClass() } ?: this
SymbolFakeFile(kotlinOrigin, containingClass)
}
@@ -209,7 +210,7 @@ internal abstract class SymbolLightClassForClassOrObject(
override fun getContainingClass(): PsiClass? {
val containingBody = kotlinOrigin?.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return getOrCreateSymbolLightClass(it) }
containingClass?.let { return it.toLightClass() }
return null
}
@@ -8,8 +8,6 @@ package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiReferenceList
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt
@@ -21,12 +19,12 @@ import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModuleOfTypeSafe
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.Modality
@@ -48,30 +46,8 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import java.util.*
internal fun getOrCreateSymbolLightClass(classOrObject: KtClassOrObject): KtLightClass? =
CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result
.create(
createSymbolLightClassNoCache(classOrObject),
classOrObject.project.createProjectWideOutOfBlockModificationTracker()
)
}
@OptIn(KtAllowAnalysisOnEdt::class)
internal fun createSymbolLightClassNoCache(classOrObject: KtClassOrObject): KtLightClass? = allowAnalysisOnEdt {
val containingFile = classOrObject.containingFile
if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments
return null
}
if (containingFile is KtFile && containingFile.isCompiled) return null
if (classOrObject.shouldNotBeVisibleAsLightClass()) {
return null
}
val anonymousObject = classOrObject.parent as? KtObjectLiteralExpression
if (anonymousObject != null) {
return analyzeForLightClasses(anonymousObject) {
@@ -113,14 +89,10 @@ context(KtAnalysisSession)
private fun lightClassForEnumEntry(ktEnumEntry: KtEnumEntry): KtLightClass? {
if (ktEnumEntry.body == null) return null
val symbolLightClass = ktEnumEntry
.containingClass()
?.let { getOrCreateSymbolLightClass(it) } as? SymbolLightClass
?: return null
val targetField = symbolLightClass.ownFields
.firstOrNull { it is SymbolLightFieldForEnumEntry && it.kotlinOrigin == ktEnumEntry }
?: return null
val symbolLightClass = ktEnumEntry.containingClass()?.toLightClass() as? SymbolLightClass ?: return null
val targetField = symbolLightClass.ownFields.firstOrNull {
it is SymbolLightFieldForEnumEntry && it.kotlinOrigin == ktEnumEntry
} ?: return null
return (targetField as? SymbolLightFieldForEnumEntry)?.initializingClass as? KtLightClass
}