From 8f3b06ac06b20f34fa7c9fdd6338e34adc2aa87a Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 24 Sep 2021 14:02:05 -0700 Subject: [PATCH] RAW FIR: record annotations on destructuring declarations --- .../annotationOnExpression_destructuring.txt | 4 +- .../converter/DeclarationsConverter.kt | 5 ++- .../lightTree/fir/DestructuringDeclaration.kt | 12 +++++- .../kotlin/fir/builder/PsiConversionUtils.kt | 42 +++++++++++++++++++ .../kotlin/fir/builder/RawFirBuilder.kt | 5 ++- .../kotlin/fir/builder/ConversionUtils.kt | 29 +++++++++++-- .../tests/annotations/MultiDeclaration.fir.kt | 4 +- 7 files changed, 91 insertions(+), 10 deletions(-) diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/annotationOnExpression_destructuring.txt b/analysis/analysis-api/testData/analysisSession/resolveCall/annotationOnExpression_destructuring.txt index 19765bd501b..4937c6b0c0f 100644 --- a/analysis/analysis-api/testData/analysisSession/resolveCall/annotationOnExpression_destructuring.txt +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/annotationOnExpression_destructuring.txt @@ -1 +1,3 @@ -null +KtAnnotationCall: +argumentMapping = { "UNCHECKED_CAST" -> (vararg names: kotlin.String) } +targetFunction = (vararg names: kotlin.String): kotlin.Suppress diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 8985a949a7c..dee165ddc0b 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -1188,12 +1188,14 @@ class DeclarationsConverter( * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitDestructuringDeclaration */ private fun convertDestructingDeclaration(destructingDeclaration: LighterASTNode): DestructuringDeclaration { + var modifiers = Modifier() var isVar = false val entries = mutableListOf() val source = destructingDeclaration.toFirSourceElement() var firExpression: FirExpression? = null destructingDeclaration.forEachChildren { when (it.tokenType) { + MODIFIER_LIST -> modifiers = convertModifierList(it) VAR_KEYWORD -> isVar = true DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it) else -> if (it.isExpression()) firExpression = @@ -1208,7 +1210,8 @@ class DeclarationsConverter( null, ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax) ), - source + source, + modifiers ) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt index 3650e693047..90a137dc28d 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt @@ -11,15 +11,23 @@ import org.jetbrains.kotlin.fir.builder.generateTemporaryVariable import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.lightTree.converter.generateDestructuringBlock +import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier data class DestructuringDeclaration( val isVar: Boolean, val entries: List, val initializer: FirExpression, - val source: FirSourceElement + val source: FirSourceElement, + val modifier: Modifier, ) { fun toFirDestructingDeclaration(moduleData: FirModuleData): FirExpression { - val baseVariable = generateTemporaryVariable(moduleData, source, "destruct", initializer) + val baseVariable = generateTemporaryVariable( + moduleData, + source, + "destruct", + initializer, + modifier.annotations + ) return generateDestructuringBlock(moduleData, this, baseVariable, tmpVariable = true) } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index c80c10e1361..7e571b200ee 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -18,6 +18,8 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* internal fun KtWhenCondition.toFirWhenCondition( @@ -81,6 +83,46 @@ internal fun Array.toFirWhenCondition( return firCondition!! } +internal fun generateTemporaryVariable( + moduleData: FirModuleData, + source: FirSourceElement?, + name: Name, + initializer: FirExpression, + typeRef: FirTypeRef? = null, + extractAnnotationsTo: (KtAnnotated.(FirAnnotationContainerBuilder) -> Unit), +): FirVariable = + buildProperty { + this.source = source + this.moduleData = moduleData + origin = FirDeclarationOrigin.Source + returnTypeRef = typeRef ?: buildImplicitTypeRef { + this.source = source + } + this.name = name + this.initializer = initializer + symbol = FirPropertySymbol(name) + isVar = false + isLocal = true + status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) + (source.psi as? KtAnnotated)?.extractAnnotationsTo(this) + } + +internal fun generateTemporaryVariable( + moduleData: FirModuleData, + source: FirSourceElement?, + specialName: String, + initializer: FirExpression, + extractAnnotationsTo: (KtAnnotated.(FirAnnotationContainerBuilder) -> Unit), +): FirVariable = + generateTemporaryVariable( + moduleData, + source, + Name.special("<$specialName>"), + initializer, + null, + extractAnnotationsTo, + ) + internal fun generateDestructuringBlock( moduleData: FirModuleData, multiDeclaration: KtDestructuringDeclaration, diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 08decde77b4..1dc724ba851 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -2368,8 +2368,11 @@ open class RawFirBuilder( override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Unit): FirElement { val baseVariable = generateTemporaryVariable( - baseModuleData, multiDeclaration.toFirSourceElement(), "destruct", + baseModuleData, + multiDeclaration.toFirSourceElement(), + "destruct", multiDeclaration.initializer.toFirExpression("Initializer required for destructuring declaration", DiagnosticKind.Syntax), + extractAnnotationsTo = { extractAnnotationsTo(it) } ) return generateDestructuringBlock( baseModuleData, diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 73c585f728f..d239ec5d98f 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtAnnotated import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions @@ -279,7 +280,12 @@ fun generateResolvedAccessExpression(source: FirSourceElement?, variable: FirVar } fun generateTemporaryVariable( - moduleData: FirModuleData, source: FirSourceElement?, name: Name, initializer: FirExpression, typeRef: FirTypeRef? = null, + moduleData: FirModuleData, + source: FirSourceElement?, + name: Name, + initializer: FirExpression, + typeRef: FirTypeRef? = null, + extractedAnnotations: Collection? = null, ): FirVariable = buildProperty { this.source = source @@ -294,11 +300,28 @@ fun generateTemporaryVariable( isVar = false isLocal = true status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) + if (extractedAnnotations != null) { + // LT extracts annotations ahead. + // PSI extracts annotations on demand. Use a similar util in [PsiConversionUtils] + annotations.addAll(extractedAnnotations) + } } fun generateTemporaryVariable( - moduleData: FirModuleData, source: FirSourceElement?, specialName: String, initializer: FirExpression, -): FirVariable = generateTemporaryVariable(moduleData, source, Name.special("<$specialName>"), initializer) + moduleData: FirModuleData, + source: FirSourceElement?, + specialName: String, + initializer: FirExpression, + extractedAnnotations: Collection? = null, +): FirVariable = + generateTemporaryVariable( + moduleData, + source, + Name.special("<$specialName>"), + initializer, + null, + extractedAnnotations, + ) val FirClassBuilder.ownerRegularOrAnonymousObjectSymbol get() = when (this) { diff --git a/compiler/testData/diagnostics/tests/annotations/MultiDeclaration.fir.kt b/compiler/testData/diagnostics/tests/annotations/MultiDeclaration.fir.kt index 7ac8fbe9641..188b08716b7 100644 --- a/compiler/testData/diagnostics/tests/annotations/MultiDeclaration.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/MultiDeclaration.fir.kt @@ -4,6 +4,6 @@ data class Pair(val x: Int, val y: Int) fun foo(): Int { @Ann val (a, b) = Pair(12, 34) - @Err val (c, d) = Pair(56, 78) + @Err val (c, d) = Pair(56, 78) return a + b + c + d -} \ No newline at end of file +}