[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
@@ -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<TModule>(protected val project: Project) : KotlinAsJavaSupport() {
fun createLightFacade(file: KtFile): KtLightClassForFacade? {
fun createLightFacade(file: KtFile): Pair<KtLightClassForFacade?, ModificationTracker>? {
if (file.isScript()) return null
if (file.isCompiled && !file.name.endsWith(".class")) return null
@@ -30,36 +37,54 @@ abstract class KotlinAsJavaSupportBase<TModule>(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<KtFile>, module: TModule): KtLightClassForFacade
abstract fun createInstanceOfDecompiledLightFacade(facadeFqName: FqName, files: List<KtFile>, module: TModule): KtLightClassForFacade?
protected abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>, module: TModule): KtLightClassForFacade
protected abstract fun createInstanceOfDecompiledLightFacade(
facadeFqName: FqName,
files: List<KtFile>,
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<KtLightClassForFacade> {
return findFilesForFacadeByPackage(packageFqName, scope).toFacadeClasses()
}
@@ -81,5 +106,71 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
}
private data class FacadeKey<TModule>(val fqName: FqName, val isMultifile: Boolean, val module: TModule)
private val recursiveGuard = ThreadLocal<Boolean>()
private inline fun <T> 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<KtLightClass?, ModificationTracker>? {
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 <T : PsiElement, V> ifValid(element: T, action: () -> V?): V? {
if (!element.isValid) return null
return action()
}
@@ -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)
}
}
}
@@ -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
@@ -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
}
@@ -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<KtClassOrObject> {
@@ -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)
}
}
@@ -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)
}
}
@@ -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)
}
}
}
@@ -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 {
@@ -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<PsiClass>()
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
@@ -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<PsiTypeParameter> = emptyArray()
override fun getContainingClass(): KtLightClassForSourceDeclaration? = KotlinLightClassFactory.createClass(classOrObject)
override fun getContainingClass(): KtLightClass? = classOrObject.toLightClass()
override fun getScope(): PsiElement? = containingClass
override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnFields(): List<KtLightField> = emptyList()
@@ -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
@@ -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)
}
}