From 46548e54430c44bf9815d7e00921a382a96270f3 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Thu, 1 Sep 2022 17:37:01 +0200 Subject: [PATCH] [lc] KotlinAsJavaSupportBase: implement getLightClass add more caching ^KT-50241 --- .../kotlin/asJava/KotlinAsJavaSupportBase.kt | 131 +++++++++++++++--- .../asJava/classes/KotlinLightClassFactory.kt | 11 +- .../KtLightClassForSourceDeclaration.kt | 1 - .../light/classes/symbol/SymbolFakeFile.kt | 4 +- .../symbol/SymbolKotlinAsJavaSupport.kt | 47 ++++--- .../SymbolLightClassForClassOrObject.kt | 5 +- .../symbol/classes/symbolLightClassUtils.kt | 38 +---- .../jvm/compiler/CliKotlinAsJavaSupport.kt | 10 +- .../asJava/LightClassGenerationSupport.kt | 30 ++-- .../classes/KotlinK1LightClassFactory.kt | 23 --- .../kotlin/asJava/classes/KtLightClassImpl.kt | 12 +- ...UltraLightClassForInterfaceDefaultImpls.kt | 3 +- ...htClassForRepeatableAnnotationContainer.kt | 3 +- .../kotlin/asJava/classes/ultraLightClass.kt | 3 +- .../classes/ultraLightClassForScript.kt | 3 +- 15 files changed, 184 insertions(+), 140 deletions(-) diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt index f0ae9db9565..404f2bf22a7 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt @@ -5,20 +5,27 @@ package org.jetbrains.kotlin.asJava +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker +import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService +import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy +import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.analysisContext abstract class KotlinAsJavaSupportBase(protected val project: Project) : KotlinAsJavaSupport() { - fun createLightFacade(file: KtFile): KtLightClassForFacade? { + fun createLightFacade(file: KtFile): Pair? { if (file.isScript()) return null if (file.isCompiled && !file.name.endsWith(".class")) return null @@ -30,36 +37,54 @@ abstract class KotlinAsJavaSupportBase(protected val project: Project) listOf(file) } - if (facadeFiles.none(KtFile::hasTopLevelCallables)) return null return when { - facadeFiles.none(KtFile::isCompiled) -> createInstanceOfLightFacade(facadeFqName, facadeFiles, module) - facadeFiles.all(KtFile::isCompiled) -> createInstanceOfDecompiledLightFacade(facadeFqName, facadeFiles, module) + facadeFiles.none(KtFile::hasTopLevelCallables) -> null + facadeFiles.none(KtFile::isCompiled) -> { + createInstanceOfLightFacade(facadeFqName, facadeFiles, module) to outOfBlockModificationTracker(file, module) + } + + facadeFiles.all(KtFile::isCompiled) -> { + createInstanceOfDecompiledLightFacade(facadeFqName, facadeFiles, module) to librariesTracker(file, module) + } + else -> error("Source and compiled files are mixed: $facadeFiles") } } - abstract fun KtFile.findModule(): TModule - abstract fun facadeIsApplicable(module: TModule, file: KtFile): Boolean - abstract val TModule.contentSearchScope: GlobalSearchScope + protected abstract fun KtFile.findModule(): TModule + protected abstract fun facadeIsApplicable(module: TModule, file: KtFile): Boolean + protected abstract val TModule.contentSearchScope: GlobalSearchScope - abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List, module: TModule): KtLightClassForFacade - abstract fun createInstanceOfDecompiledLightFacade(facadeFqName: FqName, files: List, module: TModule): KtLightClassForFacade? + protected abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List, module: TModule): KtLightClassForFacade + protected abstract fun createInstanceOfDecompiledLightFacade( + facadeFqName: FqName, + files: List, + module: TModule, + ): KtLightClassForFacade? + + protected open fun outOfBlockModificationTracker(element: PsiElement, module: TModule): ModificationTracker { + return projectWideOutOfBlockModificationTracker() + } + + protected open fun librariesTracker(element: PsiElement, module: TModule): ModificationTracker { + return projectWideOutOfBlockModificationTracker() + } + + protected open fun projectWideOutOfBlockModificationTracker(): ModificationTracker { + return KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker + } + + override fun getLightFacade(file: KtFile): KtLightClassForFacade? = ifValid(file) { + CachedValuesManager.getCachedValue(file) { + val (facade, tracker) = createLightFacade(file) ?: (null to projectWideOutOfBlockModificationTracker()) + CachedValueProvider.Result.createSingleDependency(facade, tracker) + } + } override fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade { return createInstanceOfLightFacade(file.javaFileFacadeFqName, listOf(file), file.findModule()) } - override fun getLightFacade(file: KtFile): KtLightClassForFacade? = CachedValuesManager.getCachedValue(file) { - CachedValueProvider.Result.create( - createLightFacade(file), - tracker(file), - ) - } - - open fun tracker(file: KtFile): ModificationTracker { - return KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker - } - override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection { return findFilesForFacadeByPackage(packageFqName, scope).toFacadeClasses() } @@ -81,5 +106,71 @@ abstract class KotlinAsJavaSupportBase(protected val project: Project) } private data class FacadeKey(val fqName: FqName, val isMultifile: Boolean, val module: TModule) + + private val recursiveGuard = ThreadLocal() + private inline fun guardedRun(body: () -> T): T? { + if (recursiveGuard.get() == true) return null + return try { + recursiveGuard.set(true) + body() + } finally { + recursiveGuard.set(false) + } + } + + fun createLightClass(classOrObject: KtClassOrObject): Pair? { + if (classOrObject.shouldNotBeVisibleAsLightClass()) return null + + val containingFile = classOrObject.containingKtFile + val module = containingFile.findModule() + when (declarationLocation(containingFile, module)) { + DeclarationLocation.ProjectSources -> { + return createInstanceOfLightClass(classOrObject, module) to outOfBlockModificationTracker(classOrObject, module) + } + + DeclarationLocation.LibraryClasses -> { + return createInstanceOfDecompiledLightClass(classOrObject, module) to librariesTracker(classOrObject, module) + } + + DeclarationLocation.LibrarySources -> { + val originalClassOrObject = ApplicationManager.getApplication() + .getService(KotlinDeclarationNavigationPolicy::class.java) + ?.getOriginalElement(classOrObject) as? KtClassOrObject + + val value = originalClassOrObject?.takeUnless(classOrObject::equals)?.let { + guardedRun { getLightClass(it) } + } + + return value to librariesTracker(classOrObject, module) + } + + null -> Unit + } + + if (containingFile.analysisContext != null || containingFile.originalFile.virtualFile != null) { + return createInstanceOfLightClass(classOrObject, module) to outOfBlockModificationTracker(classOrObject, module) + } + + return null + } + + protected abstract fun createInstanceOfLightClass(classOrObject: KtClassOrObject, module: TModule): KtLightClass? + protected abstract fun createInstanceOfDecompiledLightClass(classOrObject: KtClassOrObject, module: TModule): KtLightClass? + protected abstract fun declarationLocation(file: KtFile, module: TModule): DeclarationLocation? + + protected enum class DeclarationLocation { + ProjectSources, LibraryClasses, LibrarySources, + } + + override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = ifValid(classOrObject) { + CachedValuesManager.getCachedValue(classOrObject) { + val (clazz, tracker) = createLightClass(classOrObject) ?: (null to projectWideOutOfBlockModificationTracker()) + CachedValueProvider.Result.createSingleDependency(clazz, tracker) + } + } } +private fun ifValid(element: T, action: () -> V?): V? { + if (!element.isValid) return null + return action() +} \ No newline at end of file diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinLightClassFactory.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinLightClassFactory.kt index b7cfae48deb..1619d460eb4 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinLightClassFactory.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinLightClassFactory.kt @@ -8,23 +8,14 @@ package org.jetbrains.kotlin.asJava.classes import com.intellij.openapi.components.ServiceManager -import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtScript interface KotlinLightClassFactory { - fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? fun createScript(script: KtScript): KtLightClassForScript? companion object { - private val instance: KotlinLightClassFactory - get() = ServiceManager.getService(KotlinLightClassFactory::class.java) - - fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { - return instance.createClass(classOrObject) - } - fun createScript(script: KtScript): KtLightClassForScript? { - return instance.createScript(script) + return ServiceManager.getService(KotlinLightClassFactory::class.java).createScript(script) } } } \ No newline at end of file diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index ce7a7592029..cd8d67403a2 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -211,7 +211,6 @@ fun KtClassOrObject.defaultJavaAncestorQualifiedName(): String? { } fun KtClassOrObject.shouldNotBeVisibleAsLightClass(): Boolean { - if (containingFile is KtCodeFragment) { // Avoid building light classes for code fragments return true diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolFakeFile.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolFakeFile.kt index 982d43ac795..170a24ca2fc 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolFakeFile.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolFakeFile.kt @@ -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) diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt index 6fb6605710c..3ee3a54674d 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt @@ -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 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, 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( diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt index c74cf4e80ab..c3820a817ae 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt @@ -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 } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt index 73a379cd355..92088c88dcf 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt @@ -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 } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt index 00189081353..28b9eca9fe4 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt @@ -94,8 +94,6 @@ class CliKotlinAsJavaSupport(project: Project, private val traceHolder: CliTrace ).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName } } - override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = KotlinLightClassFactory.createClass(classOrObject) - override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KotlinLightClassFactory.createScript(script) override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { @@ -114,4 +112,12 @@ class CliKotlinAsJavaSupport(project: Project, private val traceHolder: CliTrace } override fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade = error("Should not be called") + override fun declarationLocation(file: KtFile, module: KtFile): DeclarationLocation = DeclarationLocation.ProjectSources + override fun createInstanceOfDecompiledLightClass(classOrObject: KtClassOrObject, module: KtFile): KtLightClass? { + error("Should not be called") + } + + override fun createInstanceOfLightClass(classOrObject: KtClassOrObject, module: KtFile): KtLightClass? { + return LightClassGenerationSupport.getInstance(classOrObject.project).createUltraLightClass(classOrObject) + } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt index f442d0039f8..3e2b5361d42 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt @@ -45,29 +45,23 @@ abstract class LightClassGenerationSupport { ) } - fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? { - if (element.shouldNotBeVisibleAsLightClass()) { - return null + fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass = getUltraLightClassSupport(element).let { support -> + if (support.languageVersionSettings.getFlag(AnalysisFlags.eagerResolveOfLightClasses)) { + val descriptor = resolveToDescriptor(element) + (descriptor as? LazyClassDescriptor)?.forceResolveAllContents() } - return getUltraLightClassSupport(element).let { support -> - if (support.languageVersionSettings.getFlag(AnalysisFlags.eagerResolveOfLightClasses)) { - val descriptor = resolveToDescriptor(element) - (descriptor as? LazyClassDescriptor)?.forceResolveAllContents() - } + when { + element is KtObjectDeclaration && element.isObjectLiteral() -> + KtUltraLightClassForAnonymousDeclaration(element, support) - when { - element is KtObjectDeclaration && element.isObjectLiteral() -> - KtUltraLightClassForAnonymousDeclaration(element, support) + element.safeIsLocal() -> + KtUltraLightClassForLocalDeclaration(element, support) - element.safeIsLocal() -> - KtUltraLightClassForLocalDeclaration(element, support) + (element.hasModifier(KtTokens.INLINE_KEYWORD)) -> + KtUltraLightInlineClass(element, support) - (element.hasModifier(KtTokens.INLINE_KEYWORD)) -> - KtUltraLightInlineClass(element, support) - - else -> KtUltraLightClass(element, support) - } + else -> KtUltraLightClass(element, support) } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinK1LightClassFactory.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinK1LightClassFactory.kt index 76529cfae6e..bc0eada4821 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinK1LightClassFactory.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinK1LightClassFactory.kt @@ -9,19 +9,10 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.asJava.LightClassGenerationSupport -import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtScript class KotlinK1LightClassFactory : KotlinLightClassFactory { - override fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? = - CachedValuesManager.getCachedValue(classOrObject) { - CachedValueProvider.Result.create( - createClassNoCache(classOrObject), - KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker, - ) - } - override fun createScript(script: KtScript): KtLightClassForScript? = CachedValuesManager.getCachedValue(script) { CachedValueProvider.Result.create( createScriptNoCache(script), @@ -39,19 +30,5 @@ class KotlinK1LightClassFactory : KotlinLightClassFactory { return LightClassGenerationSupport.getInstance(script.project).createUltraLightClassForScript(script) } - - fun createClassNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { - val containingFile = classOrObject.containingFile - if (containingFile is KtCodeFragment) { - // Avoid building light classes for code fragments - return null - } - - if (classOrObject.shouldNotBeVisibleAsLightClass()) { - return null - } - - return LightClassGenerationSupport.getInstance(classOrObject.project).createUltraLightClass(classOrObject) - } } } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt index e0dfaa8de94..87048bbe829 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.KtLightModifierListDescriptorBased import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -133,7 +134,7 @@ abstract class KtLightClassImpl constructor( private val _containingFile: PsiFile by lazyPub { object : FakeFileForLightClass( classOrObject.containingKtFile, - { if (classOrObject.isTopLevel()) this else KotlinLightClassFactory.createClass(getOutermostClassOrObject(classOrObject))!! }, + { if (classOrObject.isTopLevel()) this else getOutermostClassOrObject(classOrObject).toLightClass()!! }, ) { override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset) @@ -167,9 +168,7 @@ abstract class KtLightClassImpl constructor( // inner classes with null names can't be searched for and can't be used from java anyway // we can't prohibit creating light classes with null names either since they can contain members .filter { it.name != null } - .mapNotNullTo(result) { - KotlinLightClassFactory.createClass(it) - } + .mapNotNullTo(result, KtClassOrObject::toLightClass) if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) { result.add(createClassForInterfaceDefaultImpls()) @@ -185,11 +184,10 @@ abstract class KtLightClassImpl constructor( val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject if (containingClassOrObject != null) { - return KotlinLightClassFactory.createClass(containingClassOrObject) + return containingClassOrObject.toLightClass() } - // TODO: should return null - return super.getContainingClass() + return null } companion object { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt index e61231999fd..77128b97bce 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt @@ -14,6 +14,7 @@ import com.intellij.util.IncorrectOperationException import org.jetbrains.annotations.NotNull import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.JvmAbi @@ -59,7 +60,7 @@ class KtUltraLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject, override fun setName(name: String): PsiElement = throw IncorrectOperationException("Impossible to rename ${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}") - override fun getContainingClass(): KtLightClassForSourceDeclaration? = KotlinLightClassFactory.createClass(classOrObject) + override fun getContainingClass(): KtLightClass? = classOrObject.toLightClass() override fun getOwnInnerClasses() = emptyList() override fun getOwnMethods(): List = _ownMethods.value diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt index c5de095ddbf..5027ff5a27c 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt @@ -11,6 +11,7 @@ import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightParameterListBuilder import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.asJava.elements.* +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.KtClassOrObject @@ -22,7 +23,7 @@ class KtUltraLightClassForRepeatableAnnotationContainer(classOrObject: KtClassOr override fun getParent() = containingClass override fun getTypeParameterList(): PsiTypeParameterList? = null override fun getTypeParameters(): Array = emptyArray() - override fun getContainingClass(): KtLightClassForSourceDeclaration? = KotlinLightClassFactory.createClass(classOrObject) + override fun getContainingClass(): KtLightClass? = classOrObject.toLightClass() override fun getScope(): PsiElement? = containingClass override fun getOwnInnerClasses() = emptyList() override fun getOwnFields(): List = emptyList() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index 9898b6d3069..e048bd3da64 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -18,6 +18,7 @@ import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -484,7 +485,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor val containingBody = classOrObject.parent as? KtClassBody val containingClass = containingBody?.parent as? KtClassOrObject - containingClass?.let { return KotlinLightClassFactory.createClass(it) } + containingClass?.let { return it.toLightClass() } val containingBlock = classOrObject.parent as? KtBlockExpression val containingScript = containingBlock?.parent as? KtScript diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt index b749ba496bb..f7e78ab58c5 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt @@ -15,6 +15,7 @@ import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtProperty @@ -136,6 +137,6 @@ class KtUltraLightClassForScript( // inner classes with null names can't be searched for and can't be used from java anyway // we can't prohibit creating light classes with null names either since they can contain members .filter { it.name != null } - .mapNotNull { KotlinLightClassFactory.createClass(it) } + .mapNotNull(KtClassOrObject::toLightClass) } } \ No newline at end of file