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 9905a8aa37f..2f3b3854b1d 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 @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClass 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.createSymbolLightClassNoCache import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -123,12 +122,7 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase, - ): KtLightClassForFacade { - val firstFile = files.first() - return analyzeForLightClasses(firstFile) { - SymbolLightClassForFacade(facadeFqName, files, firstFile.getKtModule(project)) - } - } + ): KtLightClassForFacade = SymbolLightClassForFacade(facadeFqName, files, files.first().getKtModule(project)) override val KtModule.contentSearchScope: GlobalSearchScope get() = this.contentScope diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForFacade.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForFacade.kt index a1e6edfd57e..d9a63467a2b 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForFacade.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForFacade.kt @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.scopes.KtScope import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol @@ -24,13 +25,13 @@ import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.light.classes.symbol.NullabilityType import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations import org.jetbrains.kotlin.light.classes.symbol.annotations.hasInlineOnlyAnnotation import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation -import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmMultifileClassAnnotation import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForMember @@ -39,7 +40,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile -context(KtAnalysisSession) class SymbolLightClassForFacade( override val facadeClassFqName: FqName, override val files: Collection, @@ -56,13 +56,12 @@ class SymbolLightClassForFacade( require(files.none { it.isCompiled }) } - private val firstFileInFacade by lazyPub { files.first() } - - private val fileSymbols by lazyPub { - files.map { ktFile -> - ktFile.getFileSymbol() + private fun withFileSymbols(action: KtAnalysisSession.(List) -> T): T = + analyzeForLightClasses(ktModule) { + action(files.map { it.getFileSymbol() }) } - } + + private val firstFileInFacade by lazyPub { files.first() } private val _modifierList: PsiModifierList by lazyPub { if (multiFileClass) @@ -70,18 +69,20 @@ class SymbolLightClassForFacade( val lazyModifiers = lazyOf(setOf(PsiModifier.PUBLIC, PsiModifier.FINAL)) - val lazyAnnotations = lazyPub { - fileSymbols.flatMap { - it.computeAnnotations( - this@SymbolLightClassForFacade, - NullabilityType.Unknown, - AnnotationUseSiteTarget.FILE, - includeAnnotationsWithoutSite = false - ) + withFileSymbols { fileSymbols -> + val lazyAnnotations = lazyPub { + fileSymbols.flatMap { + it.computeAnnotations( + this@SymbolLightClassForFacade, + NullabilityType.Unknown, + AnnotationUseSiteTarget.FILE, + includeAnnotationsWithoutSite = false + ) + } } - } - SymbolLightClassModifierList(this@SymbolLightClassForFacade, lazyModifiers, lazyAnnotations) + SymbolLightClassModifierList(this@SymbolLightClassForFacade, lazyModifiers, lazyAnnotations) + } } override fun getModifierList(): PsiModifierList = _modifierList @@ -89,29 +90,31 @@ class SymbolLightClassForFacade( override fun getScope(): PsiElement = parent private val _ownMethods: List by lazyPub { - val result = mutableListOf() - - val methodsAndProperties = sequence { - for (fileSymbol in fileSymbols) { - for (callableSymbol in fileSymbol.getFileScope().getCallableSymbols()) { - if (callableSymbol !is KtFunctionSymbol && callableSymbol !is KtKotlinPropertySymbol) continue - if (callableSymbol !is KtSymbolWithVisibility) continue - if ((callableSymbol as? KtAnnotatedSymbol)?.hasInlineOnlyAnnotation() == true) continue - val isPrivate = callableSymbol.toPsiVisibilityForMember() == PsiModifier.PRIVATE - if (isPrivate && multiFileClass) continue - yield(callableSymbol) + withFileSymbols { fileSymbols -> + val result = mutableListOf() + val methodsAndProperties = sequence { + for (fileSymbol in fileSymbols) { + for (callableSymbol in fileSymbol.getFileScope().getCallableSymbols()) { + if (callableSymbol !is KtFunctionSymbol && callableSymbol !is KtKotlinPropertySymbol) continue + if (callableSymbol !is KtSymbolWithVisibility) continue + if ((callableSymbol as? KtAnnotatedSymbol)?.hasInlineOnlyAnnotation() == true) continue + val isPrivate = callableSymbol.toPsiVisibilityForMember() == PsiModifier.PRIVATE + if (isPrivate && multiFileClass) continue + yield(callableSymbol) + } } } - } - createMethods(methodsAndProperties, result, isTopLevel = true) - result + createMethods(methodsAndProperties, result, isTopLevel = true) + result + } } private val multiFileClass: Boolean by lazyPub { - files.size > 1 || fileSymbols.any { it.hasJvmMultifileClassAnnotation() } + files.size > 1 || firstFileInFacade.isJvmMultifileClassFile } + context(KtAnalysisSession) private fun loadFieldsFromFile( fileScope: KtScope, nameGenerator: SymbolLightField.FieldNameGenerator, @@ -151,9 +154,12 @@ class SymbolLightClassForFacade( private val _ownFields: List by lazyPub { val result = mutableListOf() val nameGenerator = SymbolLightField.FieldNameGenerator() - for (fileSymbol in fileSymbols) { - loadFieldsFromFile(fileSymbol.getFileScope(), nameGenerator, result) + withFileSymbols { fileSymbols -> + for (fileSymbol in fileSymbols) { + loadFieldsFromFile(fileSymbol.getFileScope(), nameGenerator, result) + } } + result } @@ -179,8 +185,7 @@ class SymbolLightClassForFacade( override val kotlinOrigin: KtClassOrObject? get() = null - val fqName: FqName - get() = facadeClassFqName + val fqName: FqName get() = facadeClassFqName override fun hasModifierProperty(@NonNls name: String) = modifierList.hasModifierProperty(name) @@ -224,7 +229,11 @@ class SymbolLightClassForFacade( override fun getNameIdentifier(): PsiIdentifier? = null - override fun isValid() = files.all { it.isValid && it.hasTopLevelCallables() && facadeClassFqName == it.javaFileFacadeFqName } + override fun isValid() = files.all { + it.isValid && facadeClassFqName == it.javaFileFacadeFqName + } && files.any { + it.hasTopLevelCallables() + } override fun getNavigationElement() = firstFileInFacade @@ -246,23 +255,16 @@ class SymbolLightClassForFacade( arrayOf(PsiType.getJavaLangObject(manager, resolveScope)) override fun equals(other: Any?): Boolean { - if (other !is SymbolLightClassForFacade) return false - if (this === other) return true - - if (this.hashCode() != other.hashCode()) return false - if (manager != other.manager) return false - if (facadeClassFqName != other.facadeClassFqName) return false - if (!fileSymbols.containsAll(other.fileSymbols)) return false - if (!other.fileSymbols.containsAll(fileSymbols)) return false - return true + return this === other || other is SymbolLightClassForFacade && + facadeClassFqName == other.facadeClassFqName && + files == other.files } override fun hashCode() = facadeClassFqName.hashCode() override fun toString() = "${SymbolLightClassForFacade::class.java.simpleName}:$facadeClassFqName" - override val originKind: LightClassOriginKind - get() = LightClassOriginKind.SOURCE + override val originKind: LightClassOriginKind get() = LightClassOriginKind.SOURCE override fun getText() = firstFileInFacade.text ?: ""