[RAW FIR] Refactor destructuring code

Move destructuring related code into common to reduce
differences between PSI and LT.
This commit is contained in:
Kirill Rakhman
2023-08-22 10:19:12 +02:00
committed by Space Team
parent 8de36c416e
commit 12b3fbd39a
9 changed files with 171 additions and 140 deletions
+3
View File
@@ -371,6 +371,9 @@ val projectsWithEnabledContextReceivers by extra {
":compiler:fir:resolve",
":compiler:fir:plugin-utils",
":compiler:fir:fir2ir",
":compiler:fir:raw-fir:raw-fir.common",
":compiler:fir:raw-fir:psi2fir",
":compiler:fir:raw-fir:light-tree2fir",
":kotlin-lombok-compiler-plugin.k1",
":kotlinx-serialization-compiler-plugin.k2",
":plugins:parcelize:parcelize-compiler:parcelize.k2",
@@ -6,26 +6,10 @@
package org.jetbrains.kotlin.fir.lightTree.converter
import com.intellij.lang.LighterASTNode
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.generateResolvedAccessExpression
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
import org.jetbrains.kotlin.fir.expressions.builder.buildBlock
import org.jetbrains.kotlin.fir.expressions.builder.buildComponentCall
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
@@ -76,48 +60,4 @@ inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.()
return false
}
fun generateDestructuringBlock(
moduleData: FirModuleData,
multiDeclaration: DestructuringDeclaration,
container: FirVariable,
tmpVariable: Boolean
): FirBlock {
return buildBlock {
statements.addDestructuringStatements(moduleData, multiDeclaration, container, tmpVariable)
}
}
internal fun MutableList<FirStatement>.addDestructuringStatements(
moduleData: FirModuleData,
multiDeclaration: DestructuringDeclaration,
container: FirVariable,
tmpVariable: Boolean,
) {
if (tmpVariable) {
this += container
}
val isVar = multiDeclaration.isVar
for ((index, entry) in multiDeclaration.entries.withIndex()) {
if (entry == null) continue
this += buildProperty {
this.moduleData = moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = entry.returnTypeRef
name = entry.name
initializer = buildComponentCall {
val componentCallSource = entry.source?.fakeElement(KtFakeSourceElementKind.DesugaredComponentFunctionCall)
source = componentCallSource
explicitReceiver = generateResolvedAccessExpression(componentCallSource, container)
componentIndex = index + 1
}
this.isVar = isVar
symbol = FirPropertySymbol(entry.name) // TODO?
source = entry.source
isLocal = true
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
annotations += entry.annotations
}
}
}
val FirUserTypeRef.isUnderscored get() = qualifier.lastOrNull()?.name?.asString() == "_"
@@ -1366,7 +1366,7 @@ class LightTreeRawFirDeclarationBuilder(
internal fun convertDestructingDeclaration(destructingDeclaration: LighterASTNode): DestructuringDeclaration {
var modifiers = Modifier()
var isVar = false
val entries = mutableListOf<FirVariable?>()
val entries = mutableListOf<DestructuringEntry>()
val source = destructingDeclaration.toFirSourceElement()
var firExpression: FirExpression? = null
destructingDeclaration.forEachChildren {
@@ -1387,14 +1387,14 @@ class LightTreeRawFirDeclarationBuilder(
ConeSyntaxDiagnostic("Initializer required for destructuring declaration")
),
source,
modifiers
modifiers.annotations
)
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseMultiDeclarationName
*/
private fun convertDestructingDeclarationEntry(entry: LighterASTNode): FirVariable? {
private fun convertDestructingDeclarationEntry(entry: LighterASTNode): DestructuringEntry {
var modifiers = Modifier()
var identifier: String? = null
var firType: FirTypeRef? = null
@@ -1411,18 +1411,13 @@ class LightTreeRawFirDeclarationBuilder(
} else {
identifier.nameAsSafeName()
}
return buildProperty {
source = entry.toFirSourceElement()
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
returnTypeRef = firType ?: implicitType
this.name = name
isVar = false
symbol = FirPropertySymbol(name)
isLocal = true
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
annotations += modifiers.annotations
}
return DestructuringEntry(
source = entry.toFirSourceElement(),
returnTypeRef = firType ?: implicitType,
name = name,
annotations = modifiers.annotations,
)
}
/**
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
import org.jetbrains.kotlin.fir.lightTree.fir.addDestructuringStatements
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
@@ -178,7 +179,8 @@ class LightTreeRawFirExpressionBuilder(
baseModuleData,
multiDeclaration,
multiParameter,
tmpVariable = false
tmpVariable = false,
localEntries = true
)
multiParameter
} else {
@@ -1172,13 +1174,13 @@ class LightTreeRawFirExpressionBuilder(
valueParameter.returnTypeRef
)
if (multiDeclaration != null) {
val destructuringBlock = generateDestructuringBlock(
statements.addDestructuringStatements(
baseModuleData,
multiDeclaration,
firLoopParameter,
tmpVariable = true
tmpVariable = true,
localEntries = true,
)
statements.addAll(destructuringBlock.statements)
} else {
statements.add(firLoopParameter)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -7,28 +7,76 @@ package org.jetbrains.kotlin.fir.lightTree.fir
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.DestructuringContext
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.addDestructuringStatements
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.builder.buildBlock
import org.jetbrains.kotlin.fir.generateTemporaryVariable
import org.jetbrains.kotlin.fir.lightTree.converter.generateDestructuringBlock
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
data class DestructuringDeclaration(
val isVar: Boolean,
val entries: List<FirVariable?>,
val entries: List<DestructuringEntry>,
val initializer: FirExpression,
val source: KtSourceElement,
val modifier: Modifier,
val annotations: List<FirAnnotation>,
) {
fun toFirDestructingDeclaration(moduleData: FirModuleData): FirExpression {
fun toFirDestructingDeclaration(
moduleData: FirModuleData,
tmpVariable: Boolean = true,
localEntries: Boolean = true,
): FirExpression {
val baseVariable = generateTemporaryVariable(
moduleData,
source,
SpecialNames.DESTRUCT,
initializer,
extractedAnnotations = modifier.annotations
extractedAnnotations = annotations
)
return generateDestructuringBlock(moduleData, this, baseVariable, tmpVariable = true)
return buildBlock {
statements.addDestructuringStatements(moduleData, this@DestructuringDeclaration, baseVariable, tmpVariable, localEntries)
}
}
}
class DestructuringEntry(
val source: KtSourceElement,
val returnTypeRef: FirTypeRef,
val name: Name,
val annotations: List<FirAnnotation>,
) {
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
companion object : DestructuringContext<DestructuringEntry> {
override val DestructuringEntry.returnTypeRef: FirTypeRef get() = returnTypeRef
override val DestructuringEntry.name: Name get() = name
override val DestructuringEntry.source: KtSourceElement get() = source
override fun DestructuringEntry.extractAnnotationsTo(target: FirAnnotationContainerBuilder) {
target.annotations += annotations
}
}
}
fun MutableList<FirStatement>.addDestructuringStatements(
moduleData: FirModuleData,
multiDeclaration: DestructuringDeclaration,
container: FirVariable,
tmpVariable: Boolean,
localEntries: Boolean,
) {
with(DestructuringEntry) {
addDestructuringStatements(
moduleData,
container,
multiDeclaration.entries,
multiDeclaration.isVar,
tmpVariable,
localEntries
)
}
}
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
internal fun KtWhenCondition.toFirWhenCondition(
@@ -120,14 +119,13 @@ internal fun generateTemporaryVariable(
extractAnnotationsTo,
)
context(DestructuringContext<KtDestructuringDeclarationEntry>)
internal fun generateDestructuringBlock(
moduleData: FirModuleData,
multiDeclaration: KtDestructuringDeclaration,
container: FirVariable,
tmpVariable: Boolean,
localEntries: Boolean,
extractAnnotationsTo: KtAnnotated.(FirAnnotationContainerBuilder) -> Unit,
toFirOrImplicitTypeRef: KtTypeReference?.() -> FirTypeRef,
): FirBlock {
return buildBlock {
source = multiDeclaration.toKtPsiSourceElement()
@@ -136,50 +134,18 @@ internal fun generateDestructuringBlock(
multiDeclaration,
container,
tmpVariable,
localEntries,
extractAnnotationsTo,
toFirOrImplicitTypeRef
localEntries
)
}
}
context(DestructuringContext<KtDestructuringDeclarationEntry>)
internal fun MutableList<FirStatement>.addDestructuringStatements(
moduleData: FirModuleData,
multiDeclaration: KtDestructuringDeclaration,
container: FirVariable,
tmpVariable: Boolean,
localEntries: Boolean,
extractAnnotationsTo: KtAnnotated.(FirAnnotationContainerBuilder) -> Unit,
toFirOrImplicitTypeRef: KtTypeReference?.() -> FirTypeRef,
) {
if (tmpVariable) {
this += container
}
val isVar = multiDeclaration.isVar
for ((index, entry) in multiDeclaration.entries.withIndex()) {
val name = if (entry.nameIdentifier?.text == "_") {
SpecialNames.UNDERSCORE_FOR_UNUSED_VAR
} else {
entry.nameAsSafeName
}
val entrySource = entry.toKtPsiSourceElement()
this += buildProperty {
source = entrySource
this.moduleData = moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = entry.typeReference.toFirOrImplicitTypeRef()
this.name = name
initializer = buildComponentCall {
val componentCallSource = entrySource.fakeElement(KtFakeSourceElementKind.DesugaredComponentFunctionCall)
source = componentCallSource
explicitReceiver = generateResolvedAccessExpression(componentCallSource, container)
componentIndex = index + 1
}
this.isVar = isVar
isLocal = localEntries
status = FirDeclarationStatusImpl(if (localEntries) Visibilities.Local else Visibilities.Public, Modality.FINAL)
symbol = FirPropertySymbol(name)
entry.extractAnnotationsTo(this)
}
}
addDestructuringStatements(moduleData, container, multiDeclaration.entries, multiDeclaration.isVar, tmpVariable, localEntries)
}
@@ -164,7 +164,26 @@ open class PsiRawFirBuilder(
}
}
protected open inner class Visitor : KtVisitor<FirElement, FirElement?>() {
protected open inner class Visitor : KtVisitor<FirElement, FirElement?>(), DestructuringContext<KtDestructuringDeclarationEntry> {
override val KtDestructuringDeclarationEntry.returnTypeRef: FirTypeRef
get() = typeReference.toFirOrImplicitType()
@Suppress("ConflictingExtensionProperty")
override val KtDestructuringDeclarationEntry.name: Name
get() = if (nameIdentifier?.text == "_") {
SpecialNames.UNDERSCORE_FOR_UNUSED_VAR
} else {
nameAsSafeName
}
override val KtDestructuringDeclarationEntry.source: KtSourceElement
get() = toKtPsiSourceElement()
override fun KtDestructuringDeclarationEntry.extractAnnotationsTo(target: FirAnnotationContainerBuilder) {
(this as KtAnnotated).extractAnnotationsTo(target)
}
private inline fun <reified R : FirElement> KtElement?.convertSafe(): R? =
this?.let { convertElement(it, null)} as? R
@@ -1192,10 +1211,7 @@ open class PsiRawFirBuilder(
destructuringContainerVar,
tmpVariable = false,
localEntries = false,
extractAnnotationsTo = { extractAnnotationsTo(it) },
) {
toFirOrImplicitType()
}.apply {
).apply {
statements.forEach {
(it as FirProperty).destructuringDeclarationContainerVariable = destructuringContainerVar.symbol
}
@@ -1744,8 +1760,7 @@ open class PsiRawFirBuilder(
multiParameter,
tmpVariable = false,
localEntries = true,
extractAnnotationsTo = { extractAnnotationsTo(it) },
) { toFirOrImplicitType() }
)
multiParameter
} else {
val typeRef = valueParameter.typeReference?.convertSafe() ?: FirImplicitTypeRefImplWithoutSource
@@ -2596,15 +2611,13 @@ open class PsiRawFirBuilder(
typeRef = ktParameter.typeReference.toFirOrImplicitType(),
)
if (multiDeclaration != null) {
val destructuringBlock = generateDestructuringBlock(
blockBuilder.statements.addDestructuringStatements(
baseModuleData,
multiDeclaration = multiDeclaration,
container = firLoopParameter,
tmpVariable = true,
localEntries = true,
extractAnnotationsTo = { extractAnnotationsTo(it) },
) { toFirOrImplicitType() }
blockBuilder.statements.addAll(destructuringBlock.statements)
)
} else {
blockBuilder.statements.add(firLoopParameter)
}
@@ -2968,10 +2981,7 @@ open class PsiRawFirBuilder(
baseVariable,
tmpVariable = true,
localEntries = true,
extractAnnotationsTo = { extractAnnotationsTo(it) },
) {
toFirOrImplicitType()
}
)
}
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, data: FirElement?): FirElement {
@@ -299,6 +299,18 @@ fun generateResolvedAccessExpression(source: KtSourceElement?, variable: FirVari
}
}
fun FirVariable.toComponentCall(
entrySource: KtSourceElement?,
index: Int,
): FirComponentCall {
return buildComponentCall {
val componentCallSource = entrySource?.fakeElement(KtFakeSourceElementKind.DesugaredComponentFunctionCall)
source = componentCallSource
explicitReceiver = generateResolvedAccessExpression(componentCallSource, this@toComponentCall)
componentIndex = index + 1
}
}
val FirClassBuilder.ownerRegularOrAnonymousObjectSymbol
get() = when (this) {
is FirAnonymousObjectBuilder -> symbol
@@ -0,0 +1,55 @@
/*
* 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.fir.builder
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name
interface DestructuringContext<T> {
val T.returnTypeRef: FirTypeRef
val T.name: Name
val T.source: KtSourceElement
fun T.extractAnnotationsTo(target: FirAnnotationContainerBuilder)
}
context(DestructuringContext<T>)
fun <T> MutableList<FirStatement>.addDestructuringStatements(
moduleData: FirModuleData,
container: FirVariable,
entries: List<T>,
isVar: Boolean,
tmpVariable: Boolean,
localEntries: Boolean,
) {
if (tmpVariable) {
this += container
}
for ((index, entry) in entries.withIndex()) {
this += buildProperty {
this.moduleData = moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = entry.returnTypeRef
name = entry.name
initializer = container.toComponentCall(entry.source, index)
this.isVar = isVar
symbol = FirPropertySymbol(entry.name)
source = entry.source
isLocal = localEntries
status = FirDeclarationStatusImpl(if (localEntries) Visibilities.Local else Visibilities.Public, Modality.FINAL)
entry.extractAnnotationsTo(this)
}
}
}