[FIR IDE] LC Add KtFileSymbol and fix facade annotations

This commit is contained in:
Igor Yakovlev
2020-12-11 20:18:27 +03:00
parent 46071c1925
commit fb63b74b37
8 changed files with 91 additions and 13 deletions
@@ -121,6 +121,8 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
fun KtPropertyAccessor.getPropertyAccessorSymbol(): KtPropertyAccessorSymbol = symbolProvider.getPropertyAccessorSymbol(this) 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 * @return symbol with specified [this@getClassOrObjectSymbolByClassId] or `null` in case such symbol is not found
*/ */
@@ -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<KtFileSymbol>
}
@@ -30,6 +30,7 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
} }
abstract fun getParameterSymbol(psi: KtParameter): KtParameterSymbol abstract fun getParameterSymbol(psi: KtParameter): KtParameterSymbol
abstract fun getFileSymbol(psi: KtFile): KtFileSymbol
abstract fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol abstract fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol
abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol
abstract fun getTypeParameterSymbol(psi: KtTypeParameter): KtTypeParameterSymbol abstract fun getTypeParameterSymbol(psi: KtTypeParameter): KtTypeParameterSymbol
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirNamedReference 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.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.mapAnnotationParameters 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.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue 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 = internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget) hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget)
internal fun KtFileSymbol.hasJvmMultifileClassAnnotation(): Boolean =
hasAnnotation("kotlin/jvm/JvmMultifileClass", AnnotationUseSiteTarget.FILE)
internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): String? { internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): String? {
val annotation = annotations.firstOrNull { val annotation = annotations.firstOrNull {
val siteTarget = it.useSiteTarget val siteTarget = it.useSiteTarget
@@ -120,11 +124,4 @@ internal fun KtAnnotatedSymbol.computeAnnotations(
} }
return result return result
} }
internal fun KtFile.hasJvmMultifileClassAnnotation(): Boolean = this.annotationEntries
.filter {
it.useSiteTarget?.getAnnotationUseSiteTarget() == AnnotationUseSiteTarget.FILE
}.any {
it.shortName?.asString() == "JvmMultifileClass"
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod 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.KotlinLanguage
import org.jetbrains.kotlin.idea.asJava.classes.createField import org.jetbrains.kotlin.idea.asJava.classes.createField
import org.jetbrains.kotlin.idea.asJava.classes.createMethods import org.jetbrains.kotlin.idea.asJava.classes.createMethods
@@ -51,14 +52,28 @@ class FirLightClassForFacade(
override val clsDelegate: PsiClass get() = invalidAccess() override val clsDelegate: PsiClass get() = invalidAccess()
private val fileSymbols by lazyPub {
files.map { ktFile ->
analyze(ktFile) {
ktFile.getFileSymbol()
}
}
}
private val _modifierList: PsiModifierList by lazyPub { private val _modifierList: PsiModifierList by lazyPub {
if (multiFileClass) if (multiFileClass)
return@lazyPub LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL) return@lazyPub LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
val modifiers = setOf(PsiModifier.PUBLIC, PsiModifier.FINAL) val modifiers = setOf(PsiModifier.PUBLIC, PsiModifier.FINAL)
//TODO make annotations for file site val annotations = fileSymbols.flatMap {
val annotations: List<PsiAnnotation> = emptyList() it.computeAnnotations(
this@FirLightClassForFacade,
NullabilityType.Unknown,
AnnotationUseSiteTarget.FILE,
includeAnnotationsWithoutSite = false
)
}
FirLightClassModifierList(this@FirLightClassForFacade, modifiers, annotations) FirLightClassModifierList(this@FirLightClassForFacade, modifiers, annotations)
} }
@@ -95,7 +110,7 @@ class FirLightClassForFacade(
} }
private val multiFileClass: Boolean by lazyPub { private val multiFileClass: Boolean by lazyPub {
files.size > 1 || files.any { it.hasJvmMultifileClassAnnotation() } files.size > 1 || fileSymbols.any { it.hasJvmMultifileClassAnnotation() }
} }
private fun loadFieldsFromFile( private fun loadFieldsFromFile(
@@ -40,6 +40,7 @@ internal class KtSymbolByFirBuilder private constructor(
override val token: ValidityToken, override val token: ValidityToken,
val withReadOnlyCaching: Boolean, val withReadOnlyCaching: Boolean,
private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>, private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>,
private val filesCache: BuilderCache<FirFile, KtFileSymbol>,
private val typesCache: BuilderCache<ConeKotlinType, KtType> private val typesCache: BuilderCache<ConeKotlinType, KtType>
) : ValidityTokenOwner { ) : ValidityTokenOwner {
private val resolveState by weakRef(resolveState) private val resolveState by weakRef(resolveState)
@@ -56,7 +57,8 @@ internal class KtSymbolByFirBuilder private constructor(
resolveState = resolveState, resolveState = resolveState,
withReadOnlyCaching = false, withReadOnlyCaching = false,
symbolsCache = BuilderCache(), symbolsCache = BuilderCache(),
typesCache = BuilderCache() typesCache = BuilderCache(),
filesCache = BuilderCache(),
) )
@@ -68,7 +70,8 @@ internal class KtSymbolByFirBuilder private constructor(
resolveState = newResolveState, resolveState = newResolveState,
withReadOnlyCaching = true, withReadOnlyCaching = true,
symbolsCache = symbolsCache.createReadOnlyCopy(), 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) = fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) =
symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, resolveState, token, this) } 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) { fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) {
when { when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this) fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this)
@@ -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<FirFile> {
override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) }
override fun createPointer(): KtSymbolPointer<KtFileSymbol> {
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
TODO("Creating pointers for files from library is not supported yet")
}
override val annotations: List<KtAnnotationCall> by firRef.withFirAndCache(FirResolvePhase.TYPES) {
convertAnnotation(it)
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol 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.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.getOrBuildFirOfType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationOfType import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationOfType
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession 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 { override fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol = withValidityAssertion {
psi.withFirDeclarationOfType<FirSimpleFunction, KtFunctionSymbol>(resolveState) { psi.withFirDeclarationOfType<FirSimpleFunction, KtFunctionSymbol>(resolveState) {
firSymbolBuilder.buildFunctionSymbol(it) firSymbolBuilder.buildFunctionSymbol(it)