[Analysis API] Support script declarations (KTIJ-21108)

This commit is contained in:
Yan Zhulanow
2023-02-27 19:55:36 +09:00
committed by Space Team
parent e5e0575ab0
commit 37760d1f2a
12 changed files with 196 additions and 3 deletions
@@ -37,6 +37,10 @@ internal class KtFe10SymbolProvider(
return KtFe10FileSymbol(psi, analysisContext)
}
override fun getScriptSymbol(psi: KtScript): KtScriptSymbol {
return KtFe10PsiScriptSymbol(psi, analysisContext)
}
override fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol {
return when {
psi.isFunctionTypeParameter -> error("Function type parameters are not supported in getParameterSymbol()")
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2023 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.analysis.api.descriptors.symbols.psiBased
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KtFe10AnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.pointers.KtFe10NeverRestoringSymbolPointer
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.KtFe10PsiSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.utils.cached
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.BindingContext
internal class KtFe10PsiScriptSymbol(
private val script: KtScript,
override val analysisContext: Fe10AnalysisContext
) : KtScriptSymbol(), KtFe10AnnotatedSymbol, KtFe10PsiSymbol<KtScript, ScriptDescriptor> {
override val descriptor: ScriptDescriptor? by cached {
val bindingContext = analysisContext.analyze(psi, Fe10AnalysisFacade.AnalysisMode.PARTIAL)
bindingContext[BindingContext.SCRIPT, psi]
}
override val origin: KtSymbolOrigin
get() = withValidityAssertion { if (script.containingKtFile.isCompiled) KtSymbolOrigin.LIBRARY else KtSymbolOrigin.SOURCE }
override val psi: KtScript
get() = withValidityAssertion { script }
override val name: Name
get() = withValidityAssertion { script.nameAsSafeName }
override val typeParameters: List<KtTypeParameterSymbol>
get() = withValidityAssertion { emptyList() }
context(KtAnalysisSession)
override fun createPointer(): KtSymbolPointer<KtScriptSymbol> = withValidityAssertion {
KtPsiBasedSymbolPointer.createForSymbolFromSource(this) ?: KtFe10NeverRestoringSymbolPointer()
}
}
@@ -94,6 +94,7 @@ internal class KtSymbolByFirBuilder constructor(
is FirTypeParameterSymbol -> classifierBuilder.buildTypeParameterSymbol(firSymbol)
is FirCallableSymbol<*> -> callableBuilder.buildCallableSymbol(firSymbol)
is FirFileSymbol -> buildFileSymbol(firSymbol)
is FirScriptSymbol -> buildScriptSymbol(firSymbol)
else -> throwUnexpectedElementError(firSymbol)
}
}
@@ -103,6 +104,8 @@ internal class KtSymbolByFirBuilder constructor(
fun buildFileSymbol(firSymbol: FirFileSymbol) = KtFirFileSymbol(firSymbol, analysisSession)
fun buildScriptSymbol(firSymbol: FirScriptSymbol) = KtFirScriptSymbol(firSymbol, analysisSession)
private val packageProvider = project.createPackageProvider(GlobalSearchScope.allScope(project))//todo scope
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
@@ -45,7 +45,9 @@ internal class KtFirSymbolContainingDeclarationProvider(
is KtLocalVariableSymbol -> getParentSymbolByPsi()
is KtAnonymousFunctionSymbol -> getParentSymbolByPsi()
is KtAnonymousObjectSymbol -> getParentSymbolByPsi()
is KtSamConstructorSymbol -> null // SAM constructors are always toplevel
is KtSamConstructorSymbol -> null // SAM constructors are always top-level
is KtScriptSymbol -> null // Scripts are always top-level
is KtClassInitializerSymbol -> {
val outerFirClassifier = symbol.firSymbol.getContainingClassSymbol(symbol.firSymbol.llFirSession)
@@ -69,8 +71,6 @@ internal class KtFirSymbolContainingDeclarationProvider(
val outerFirClassifier = symbol.firSymbol.llFirSession.firProvider.getFirClassifierByFqName(outerClassId) ?: return null
firSymbolBuilder.buildSymbol(outerFirClassifier) as? KtDeclarationSymbol
}
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2023 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.analysis.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForDeclaration
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.name.Name
internal class KtFirScriptSymbol(
override val firSymbol: FirScriptSymbol,
override val analysisSession: KtFirAnalysisSession
) : KtScriptSymbol(), KtFirSymbol<FirScriptSymbol> {
override val psi: PsiElement?
get() = withValidityAssertion { firSymbol.fir.psi }
override val annotationsList by cached {
KtFirAnnotationListForDeclaration.create(
firSymbol,
analysisSession.useSiteSession,
token,
)
}
override val typeParameters: List<KtTypeParameterSymbol>
get() = withValidityAssertion { emptyList() }
override val name: Name
get() = withValidityAssertion { firSymbol.fir.name }
context(KtAnalysisSession)
override fun createPointer(): KtSymbolPointer<KtScriptSymbol> = withValidityAssertion {
KtPsiBasedSymbolPointer.createForSymbolFromSource<KtScriptSymbol>(this)?.let { return it }
TODO("Creating pointers for files from library is not supported yet")
}
override fun equals(other: Any?): Boolean = symbolEquals(other)
override fun hashCode(): Int = symbolHashCode()
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.fir.symbols
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.components.KtFirAnalysisSessionComponent
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbolOfType
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
@@ -54,6 +55,10 @@ internal class KtFirSymbolProvider(
return firSymbolBuilder.buildFileSymbol(psi.getOrBuildFirFile(firResolveSession).symbol)
}
override fun getScriptSymbol(psi: KtScript): KtScriptSymbol {
return firSymbolBuilder.buildScriptSymbol(psi.resolveToFirSymbolOfType<FirScriptSymbol>(firResolveSession))
}
override fun getFunctionLikeSymbol(psi: KtNamedFunction): KtFunctionLikeSymbol {
return when (val firSymbol = psi.resolveToFirSymbolOfType<FirFunctionSymbol<*>>(firResolveSession)) {
is FirNamedFunctionSymbol -> {
@@ -81,6 +81,9 @@ public class KtDeclarationRenderer private constructor(
public val anonymousObjectRenderer: KtAnonymousObjectSymbolRenderer,
public val singleTypeParameterRenderer: KtSingleTypeParameterSymbolRenderer,
public val returnTypeFilter: KtCallableReturnTypeFilter,
public val scriptRenderer: KtScriptSymbolRenderer,
public val scriptInitializerRenderer: KtScriptInitializerRenderer
) {
context(KtAnalysisSession)
@@ -104,6 +107,7 @@ public class KtDeclarationRenderer private constructor(
is KtSyntheticJavaPropertySymbol -> syntheticJavaPropertyRenderer.renderSymbol(symbol, printer)
is KtTypeParameterSymbol -> singleTypeParameterRenderer.renderSymbol(symbol, printer)
is KtClassInitializerSymbol -> classInitializerRender.renderClassInitializer(symbol, printer)
is KtScriptSymbol -> scriptRenderer.renderSymbol(symbol, printer)
}
}
@@ -165,6 +169,9 @@ public class KtDeclarationRenderer private constructor(
this.singleTypeParameterRenderer = renderer.singleTypeParameterRenderer
this.returnTypeFilter = renderer.returnTypeFilter
this.scriptRenderer = renderer.scriptRenderer
this.scriptInitializerRenderer = renderer.scriptInitializerRenderer
action()
}
}
@@ -229,6 +236,8 @@ public class KtDeclarationRenderer private constructor(
public lateinit var anonymousObjectRenderer: KtAnonymousObjectSymbolRenderer
public lateinit var singleTypeParameterRenderer: KtSingleTypeParameterSymbolRenderer
public lateinit var scriptRenderer: KtScriptSymbolRenderer
public lateinit var scriptInitializerRenderer: KtScriptInitializerRenderer
public fun build(): KtDeclarationRenderer = KtDeclarationRenderer(
nameRenderer,
@@ -284,6 +293,9 @@ public class KtDeclarationRenderer private constructor(
anonymousObjectRenderer,
singleTypeParameterRenderer,
returnTypeFilter,
scriptRenderer,
scriptInitializerRenderer,
)
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2023 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.analysis.api.renderer.declarations.bodies
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer
import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
public interface KtScriptInitializerRenderer {
context(KtAnalysisSession, KtDeclarationRenderer)
public fun renderInitializer(symbol: KtScriptSymbol, printer: PrettyPrinter)
public object NO_INITIALIZER : KtScriptInitializerRenderer {
context(KtAnalysisSession)
override fun renderInitializer(symbol: KtScriptSymbol, printer: PrettyPrinter) {
}
}
}
@@ -82,6 +82,9 @@ public object KtDeclarationRendererForSource {
annotationRenderer = KtAnnotationRendererForSource.WITH_QUALIFIED_NAMES
declarationTypeApproximator = KtRendererTypeApproximator.TO_DENOTABLE
returnTypeFilter = KtCallableReturnTypeFilter.NO_UNIT_FOR_FUNCTIONS
scriptRenderer = KtScriptSymbolRenderer.AS_SOURCE
scriptInitializerRenderer = KtScriptInitializerRenderer.NO_INITIALIZER
}
public val WITH_SHORT_NAMES: KtDeclarationRenderer = WITH_QUALIFIED_NAMES.with {
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2023 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.analysis.api.renderer.declarations.renderers.callables
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer
import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
public interface KtScriptSymbolRenderer {
context(KtAnalysisSession, KtDeclarationRenderer)
public fun renderSymbol(symbol: KtScriptSymbol, printer: PrettyPrinter)
public object AS_SOURCE : KtScriptSymbolRenderer {
context(KtAnalysisSession, KtDeclarationRenderer)
override fun renderSymbol(symbol: KtScriptSymbol, printer: PrettyPrinter) {
scriptInitializerRenderer.renderInitializer(symbol, printer)
}
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2023 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.analysis.api.symbols
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
public abstract class KtScriptSymbol : KtDeclarationSymbol, KtAnnotatedSymbol, KtNamedSymbol {
context(KtAnalysisSession)
abstract override fun createPointer(): KtSymbolPointer<KtScriptSymbol>
}
@@ -31,11 +31,13 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
is KtPropertyAccessor -> getPropertyAccessorSymbol(psi)
is KtClassInitializer -> getClassInitializerSymbol(psi)
is KtDestructuringDeclarationEntry -> getDestructuringDeclarationEntrySymbol(psi)
is KtScript -> getScriptSymbol(psi)
else -> error("Cannot build symbol for ${psi::class}")
}
public abstract fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol
public abstract fun getFileSymbol(psi: KtFile): KtFileSymbol
public abstract fun getScriptSymbol(psi: KtScript): KtScriptSymbol
public abstract fun getFunctionLikeSymbol(psi: KtNamedFunction): KtFunctionLikeSymbol
public abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol
public abstract fun getTypeParameterSymbol(psi: KtTypeParameter): KtTypeParameterSymbol