diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index 87d92fa5959..cd6d5c9d1e7 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -121,6 +121,8 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali fun KtPropertyAccessor.getPropertyAccessorSymbol(): KtPropertyAccessorSymbol = symbolProvider.getPropertyAccessorSymbol(this) + fun KtFile.getFileSymbol(): KtFileSymbol = symbolProvider.getFileSymbol(this) + /** * @return symbol with specified [this@getClassOrObjectSymbolByClassId] or `null` in case such symbol is not found */ diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFileSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFileSymbol.kt new file mode 100644 index 00000000000..ecc70c37c8b --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFileSymbol.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.frontend.api.symbols + +import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer + +abstract class KtFileSymbol : KtAnnotatedSymbol { + abstract override fun createPointer(): KtSymbolPointer +} \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt index cbb9955aeb7..c4381a90d6e 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt @@ -30,6 +30,7 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() { } abstract fun getParameterSymbol(psi: KtParameter): KtParameterSymbol + abstract fun getFileSymbol(psi: KtFile): KtFileSymbol abstract fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol abstract fun getTypeParameterSymbol(psi: KtTypeParameter): KtTypeParameterSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt index 1042171a89e..6731923c6c5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol import org.jetbrains.kotlin.idea.frontend.api.fir.utils.mapAnnotationParameters +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue @@ -24,6 +25,9 @@ import org.jetbrains.kotlin.psi.KtFile internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean = hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget) +internal fun KtFileSymbol.hasJvmMultifileClassAnnotation(): Boolean = + hasAnnotation("kotlin/jvm/JvmMultifileClass", AnnotationUseSiteTarget.FILE) + internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): String? { val annotation = annotations.firstOrNull { val siteTarget = it.useSiteTarget @@ -120,11 +124,4 @@ internal fun KtAnnotatedSymbol.computeAnnotations( } return result -} - -internal fun KtFile.hasJvmMultifileClassAnnotation(): Boolean = this.annotationEntries - .filter { - it.useSiteTarget?.getAnnotationUseSiteTarget() == AnnotationUseSiteTarget.FILE - }.any { - it.shortName?.asString() == "JvmMultifileClass" - } \ No newline at end of file +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt index df736dafef1..d7e809829e4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub 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.idea.KotlinLanguage import org.jetbrains.kotlin.idea.asJava.classes.createField import org.jetbrains.kotlin.idea.asJava.classes.createMethods @@ -51,14 +52,28 @@ class FirLightClassForFacade( override val clsDelegate: PsiClass get() = invalidAccess() + private val fileSymbols by lazyPub { + files.map { ktFile -> + analyze(ktFile) { + ktFile.getFileSymbol() + } + } + } + private val _modifierList: PsiModifierList by lazyPub { if (multiFileClass) return@lazyPub LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL) val modifiers = setOf(PsiModifier.PUBLIC, PsiModifier.FINAL) - //TODO make annotations for file site - val annotations: List = emptyList() + val annotations = fileSymbols.flatMap { + it.computeAnnotations( + this@FirLightClassForFacade, + NullabilityType.Unknown, + AnnotationUseSiteTarget.FILE, + includeAnnotationsWithoutSite = false + ) + } FirLightClassModifierList(this@FirLightClassForFacade, modifiers, annotations) } @@ -95,7 +110,7 @@ class FirLightClassForFacade( } private val multiFileClass: Boolean by lazyPub { - files.size > 1 || files.any { it.hasJvmMultifileClassAnnotation() } + files.size > 1 || fileSymbols.any { it.hasJvmMultifileClassAnnotation() } } private fun loadFieldsFromFile( diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt index edec83d27c8..bf887c7db11 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt @@ -40,6 +40,7 @@ internal class KtSymbolByFirBuilder private constructor( override val token: ValidityToken, val withReadOnlyCaching: Boolean, private val symbolsCache: BuilderCache, + private val filesCache: BuilderCache, private val typesCache: BuilderCache ) : ValidityTokenOwner { private val resolveState by weakRef(resolveState) @@ -56,7 +57,8 @@ internal class KtSymbolByFirBuilder private constructor( resolveState = resolveState, withReadOnlyCaching = false, symbolsCache = BuilderCache(), - typesCache = BuilderCache() + typesCache = BuilderCache(), + filesCache = BuilderCache(), ) @@ -68,7 +70,8 @@ internal class KtSymbolByFirBuilder private constructor( resolveState = newResolveState, withReadOnlyCaching = true, symbolsCache = symbolsCache.createReadOnlyCopy(), - typesCache = typesCache.createReadOnlyCopy() + typesCache = typesCache.createReadOnlyCopy(), + filesCache = filesCache.createReadOnlyCopy(), ) } @@ -139,6 +142,8 @@ internal class KtSymbolByFirBuilder private constructor( fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) = symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, resolveState, token, this) } + fun buildFileSymbol(fir: FirFile) = filesCache.cache(fir) { KtFirFileSymbol(fir, resolveState, token, this) } + fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) { when { fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFileSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFileSymbol.kt new file mode 100644 index 00000000000..bc810e90b06 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFileSymbol.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.frontend.api.fir.symbols + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState +import org.jetbrains.kotlin.idea.frontend.api.ValidityToken +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer + +internal class KtFirFileSymbol( + fir: FirFile, + resolveState: FirModuleResolveState, + override val token: ValidityToken, + private val builder: KtSymbolByFirBuilder +) : KtFileSymbol(), KtFirSymbol { + + override val firRef = firRef(fir, resolveState) + override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + TODO("Creating pointers for files from library is not supported yet") + } + + override val annotations: List by firRef.withFirAndCache(FirResolvePhase.TYPES) { + convertAnnotation(it) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt index 027dbc18cd9..6ea38bc1d3a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState +import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationOfType import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession @@ -38,6 +39,10 @@ internal class KtFirSymbolProvider( } } + override fun getFileSymbol(psi: KtFile): KtFileSymbol = withValidityAssertion { + firSymbolBuilder.buildFileSymbol(psi.getFirFile(resolveState)) + } + override fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol = withValidityAssertion { psi.withFirDeclarationOfType(resolveState) { firSymbolBuilder.buildFunctionSymbol(it)