[Analysis API] introduce KtDestructuringDeclarationSymbol to represent a destructuring declaration

Mainly needed to avoid "Cannot build symbol for KtDestructuringDeclaration" from `KtSymbolProvider.getSymbol` on `KtDestructuringDeclaration`.
This commit is contained in:
Ilya Kirillov
2023-08-07 15:02:28 +02:00
committed by Space Team
parent 1b0034b6e7
commit 8ad5a48b98
20 changed files with 338 additions and 1 deletions
@@ -74,6 +74,7 @@ public class KtDeclarationRenderer private constructor(
public val valueParameterRenderer: KtValueParameterSymbolRenderer,
public val samConstructorRenderer: KtSamConstructorSymbolRenderer,
public val propertyAccessorsRenderer: KtPropertyAccessorsRenderer,
public val destructuringDeclarationRenderer: KtDestructuringDeclarationRenderer,
public val classInitializerRender: KtClassInitializerRenderer,
public val classOrObjectRenderer: KtNamedClassOrObjectSymbolRenderer,
@@ -108,6 +109,7 @@ public class KtDeclarationRenderer private constructor(
is KtTypeParameterSymbol -> singleTypeParameterRenderer.renderSymbol(symbol, printer)
is KtClassInitializerSymbol -> classInitializerRender.renderClassInitializer(symbol, printer)
is KtScriptSymbol -> scriptRenderer.renderSymbol(symbol, printer)
is KtDestructuringDeclarationSymbol -> destructuringDeclarationRenderer.renderSymbol(symbol, printer)
}
}
@@ -161,6 +163,7 @@ public class KtDeclarationRenderer private constructor(
this.valueParameterRenderer = renderer.valueParameterRenderer
this.samConstructorRenderer = renderer.samConstructorRenderer
this.propertyAccessorsRenderer = renderer.propertyAccessorsRenderer
this.destructuringDeclarationRenderer = renderer.destructuringDeclarationRenderer
this.classInitializerRender = renderer.classInitializerRender
this.classOrObjectRenderer = renderer.classOrObjectRenderer
@@ -229,6 +232,7 @@ public class KtDeclarationRenderer private constructor(
public lateinit var valueParameterRenderer: KtValueParameterSymbolRenderer
public lateinit var samConstructorRenderer: KtSamConstructorSymbolRenderer
public lateinit var propertyAccessorsRenderer: KtPropertyAccessorsRenderer
public lateinit var destructuringDeclarationRenderer: KtDestructuringDeclarationRenderer
public lateinit var classInitializerRender: KtClassInitializerRenderer
public lateinit var classOrObjectRenderer: KtNamedClassOrObjectSymbolRenderer
@@ -286,6 +290,7 @@ public class KtDeclarationRenderer private constructor(
valueParameterRenderer,
samConstructorRenderer,
propertyAccessorsRenderer,
destructuringDeclarationRenderer,
classInitializerRender,
classOrObjectRenderer,
@@ -74,6 +74,7 @@ public object KtDeclarationRendererForSource {
anonymousObjectRenderer = KtAnonymousObjectSymbolRenderer.AS_SOURCE
singleTypeParameterRenderer = KtSingleTypeParameterSymbolRenderer.WITHOUT_BOUNDS
propertyAccessorsRenderer = KtPropertyAccessorsRenderer.NO_DEFAULT
destructuringDeclarationRenderer = KtDestructuringDeclarationRenderer.WITH_ENTRIES
callableReceiverRenderer = KtCallableReceiverRenderer.AS_TYPE_WITH_IN_APPROXIMATION
returnTypeRenderer = KtCallableReturnTypeRenderer.WITH_OUT_APPROXIMATION
@@ -0,0 +1,41 @@
/*
* 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.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter
import org.jetbrains.kotlin.analysis.api.symbols.KtDestructuringDeclarationSymbol
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
import org.jetbrains.kotlin.lexer.KtTokens
public interface KtDestructuringDeclarationRenderer {
context(KtAnalysisSession, KtDeclarationRenderer)
public fun renderSymbol(symbol: KtDestructuringDeclarationSymbol, printer: PrettyPrinter)
public object WITH_ENTRIES : KtDestructuringDeclarationRenderer {
context(KtAnalysisSession, KtDeclarationRenderer)
override fun renderSymbol(symbol: KtDestructuringDeclarationSymbol, printer: PrettyPrinter): Unit = printer {
codeStyle.getSeparatorBetweenAnnotationAndOwner(symbol).separated(
{ annotationRenderer.renderAnnotations(symbol, printer) },
{
// do not render (val a: Int, val b: Int), render `(a: Int, b: Int)` instead
val rendererWithoutValVar = with {
keywordsRenderer = keywordsRenderer.with {
keywordFilter = keywordFilter and KtRendererKeywordFilter.without(KtTokens.VAL_KEYWORD, KtTokens.VAR_KEYWORD)
}
}
printCollection(symbol.entries, prefix = "(", postfix = ")") {
with(rendererWithoutValVar) {
localVariableRenderer.renderSymbol(it, this@printCollection)
}
}
}
)
}
}
}
@@ -0,0 +1,46 @@
/*
* 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.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
/**
* A [KtSymbol] created from a [destructuring declaration][org.jetbrains.kotlin.psi.KtDestructuringDeclaration] (possibly from a lambda parameter).
*
* Examples:
* - `val (a, _) = Pair(1, 2)` leads to `KtDestructuringDeclarationSymbol(entries = [a, _])`
* - `Pair(1, _).let { (a, b) -> }` leads to `KtDestructuringDeclarationSymbol(entries = [a, _])`
*/
public abstract class KtDestructuringDeclarationSymbol : KtDeclarationSymbol, KtSymbolWithKind {
final override val symbolKind: KtSymbolKind get() = withValidityAssertion { KtSymbolKind.LOCAL }
final override val typeParameters: List<KtTypeParameterSymbol> get() = withValidityAssertion { emptyList() }
/**
* A list of [KtLocalVariableSymbol]s which were created from this destructuring declaration.
*
* E.g., for the following code:
* ```
* data class X(val y: Int, val z: String)
* fun foo() {
* val (a, _) = x // the destruction
* }
* ```
*
* the following symbols will be created (pseudocode)
* ```
* val a: Int
* val _: String
* ```
*/
public abstract val entries: List<KtLocalVariableSymbol>
context(KtAnalysisSession)
abstract override fun createPointer(): KtSymbolPointer<KtDestructuringDeclarationSymbol>
}
@@ -32,6 +32,7 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
is KtClassInitializer -> getClassInitializerSymbol(psi)
is KtDestructuringDeclarationEntry -> getDestructuringDeclarationEntrySymbol(psi)
is KtScript -> getScriptSymbol(psi)
is KtDestructuringDeclaration -> getDestructuringDeclarationSymbol(psi)
else -> error("Cannot build symbol for ${psi::class}")
}
@@ -52,6 +53,7 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
public abstract fun getPropertyAccessorSymbol(psi: KtPropertyAccessor): KtPropertyAccessorSymbol
public abstract fun getClassInitializerSymbol(psi: KtClassInitializer): KtClassInitializerSymbol
public abstract fun getDestructuringDeclarationEntrySymbol(psi: KtDestructuringDeclarationEntry): KtLocalVariableSymbol
public abstract fun getDestructuringDeclarationSymbol(psi: KtDestructuringDeclaration): KtDestructuringDeclarationSymbol
public abstract fun getPackageSymbolIfPackageExists(packageFqName: FqName): KtPackageSymbol?
@@ -0,0 +1,15 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclaration
// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE
data class X(val a: Int, val b: Int)
fun main(x: X) {
<expr>
@AAA("y")
val (@BBB("aaa") a, @BBB("bbb") b) = x
</expr>
}
annotation class AAA(val value: String)
annotation class BBB(val value: String)
@@ -0,0 +1,2 @@
@AAA(value = "y")
(@BBB(value = "aaa") a: kotlin.Int, @BBB(value = "bbb") b: kotlin.Int)
@@ -0,0 +1,14 @@
KtDestructuringDeclarationSymbol:
annotationsList: [
AAA(value = "y")
psi: KtAnnotationEntry
]
entries: [
KtLocalVariableSymbol(<local>/a)
KtLocalVariableSymbol(<local>/b)
]
origin: SOURCE
symbolKind: LOCAL
typeParameters: []
getContainingModule: KtSourceModule "Sources of main"
deprecationStatus: null
@@ -0,0 +1,12 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclaration
// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE
data class X(val a: Int, val b: Int)
fun x(action: (X) -> Unit) {}
fun main() {
x { <expr>(a, b)</expr> ->
}
}
@@ -0,0 +1 @@
(a: kotlin.Int, b: kotlin.Int)
@@ -0,0 +1,11 @@
KtDestructuringDeclarationSymbol:
annotationsList: []
entries: [
KtLocalVariableSymbol(<local>/a)
KtLocalVariableSymbol(<local>/b)
]
origin: SOURCE
symbolKind: LOCAL
typeParameters: []
getContainingModule: KtSourceModule "Sources of main"
deprecationStatus: null