Raw FIR: generate data-class component1, component2, ... functions
This commit is contained in:
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -551,6 +552,48 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
)
|
||||
}
|
||||
|
||||
if (classOrObject.hasModifier(KtTokens.DATA_KEYWORD) && firPrimaryConstructor != null) {
|
||||
var componentIndex = 1
|
||||
val zippedParameters =
|
||||
classOrObject.primaryConstructorParameters.zip(firClass.declarations.filterIsInstance<FirProperty>())
|
||||
for ((ktParameter, firProperty) in zippedParameters) {
|
||||
if (!ktParameter.hasValOrVar()) continue
|
||||
val name = Name.identifier("component$componentIndex")
|
||||
componentIndex++
|
||||
val symbol = FirFunctionSymbol(callableIdForName(name))
|
||||
firClass.addDeclaration(
|
||||
FirMemberFunctionImpl(
|
||||
session, ktParameter, symbol, name,
|
||||
Visibilities.PUBLIC, Modality.FINAL,
|
||||
isExpect = false, isActual = false,
|
||||
isOverride = false, isOperator = false,
|
||||
isInfix = false, isInline = false,
|
||||
isTailRec = false, isExternal = false,
|
||||
isSuspend = false, receiverTypeRef = null,
|
||||
returnTypeRef = FirImplicitTypeRefImpl(session, ktParameter)
|
||||
).apply {
|
||||
val componentFunction = this
|
||||
body = FirSingleExpressionBlock(
|
||||
this@RawFirBuilder.session,
|
||||
FirReturnExpressionImpl(
|
||||
this@RawFirBuilder.session, ktParameter,
|
||||
FirQualifiedAccessExpressionImpl(this@RawFirBuilder.session, ktParameter).apply {
|
||||
val parameterName = ktParameter.nameAsSafeName
|
||||
calleeReference = FirResolvedCallableReferenceImpl(
|
||||
this@RawFirBuilder.session, ktParameter,
|
||||
parameterName, firProperty.symbol
|
||||
)
|
||||
}
|
||||
).apply {
|
||||
target = FirFunctionTarget(null)
|
||||
target.bind(componentFunction)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
firClass
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,18 @@ FILE: destructuring.kt
|
||||
public? final? val third: String = R|<local>/third|
|
||||
public? get(): String
|
||||
|
||||
public final fun component1(): <implicit> {
|
||||
^component1 R|/Some.first|
|
||||
}
|
||||
|
||||
public final fun component2(): <implicit> {
|
||||
^component2 R|/Some.second|
|
||||
}
|
||||
|
||||
public final fun component3(): <implicit> {
|
||||
^component3 R|/Some.third|
|
||||
}
|
||||
|
||||
}
|
||||
public? final? fun foo(some: Some): kotlin/Unit {
|
||||
lval <destruct>: <implicit> = some#
|
||||
|
||||
@@ -35,6 +35,14 @@ FILE: for.kt
|
||||
public? final? val y: Int = R|<local>/y|
|
||||
public? get(): Int
|
||||
|
||||
public final fun component1(): <implicit> {
|
||||
^component1 R|/Some.x|
|
||||
}
|
||||
|
||||
public final fun component2(): <implicit> {
|
||||
^component2 R|/Some.y|
|
||||
}
|
||||
|
||||
}
|
||||
public? final? fun baz(set: Set<Some>): kotlin/Unit {
|
||||
lval <range>: <implicit> = set#
|
||||
|
||||
@@ -10,6 +10,14 @@ FILE: lambda.kt
|
||||
public? final? val y: Int = R|<local>/y|
|
||||
public? get(): Int
|
||||
|
||||
public final fun component1(): <implicit> {
|
||||
^component1 R|/Tuple.x|
|
||||
}
|
||||
|
||||
public final fun component2(): <implicit> {
|
||||
^component2 R|/Tuple.y|
|
||||
}
|
||||
|
||||
}
|
||||
public? final? inline fun use(f: ( (Tuple) -> Int )): <implicit> {
|
||||
^use f#(Tuple#(Int(1), Int(2)))
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
data class D(val x: Int, val y: String)
|
||||
|
||||
fun foo(list: List<D>) {
|
||||
for ((x, y) in list) {
|
||||
}
|
||||
val (x, y) = list.first()
|
||||
list.forEach { (x, y) ->
|
||||
println(x)
|
||||
println(y)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
FILE: components.kt
|
||||
public final data class D : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|, y: R|kotlin/String|): R|D| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|kotlin/Int| = R|<local>/x|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val y: R|kotlin/String| = R|<local>/y|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final fun component1(): R|kotlin/Int| {
|
||||
^component1 R|/D.x|
|
||||
}
|
||||
|
||||
public final fun component2(): R|kotlin/String| {
|
||||
^component2 R|/D.y|
|
||||
}
|
||||
|
||||
}
|
||||
public final fun foo(list: R|kotlin/collections/List<D>|): R|kotlin/Unit| {
|
||||
lval <range>: R|kotlin/collections/List<D>| = R|<local>/list|
|
||||
lval <iterator>: R|kotlin/collections/Iterator<D>| = R|<local>/<range>|.R|FakeOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<D>|>|()
|
||||
while(R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.hasNext: R|kotlin/Boolean|>|()) {
|
||||
lval <destruct>: R|D| = R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|D|>|()
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/D.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/D.component2|()
|
||||
}
|
||||
|
||||
lval <destruct>: <ERROR TYPE REF: Ambiguity: first, [kotlin/collections/first, kotlin/collections/first]> = R|<local>/list|.<Ambiguity: first, [kotlin/collections/first, kotlin/collections/first]>#()
|
||||
lval x: <ERROR TYPE REF: Ambiguity: component1, [kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1, kotlin/collections/component1]> = R|<local>/<destruct>|.component1()
|
||||
lval y: <ERROR TYPE REF: Ambiguity: component2, [kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2, kotlin/collections/component2]> = R|<local>/<destruct>|.component2()
|
||||
R|<local>/list|.R|kotlin/collections/forEach|<R|D|>(<L> = forEach@fun <anonymous>(<destruct>: R|D|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/D.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/D.component2|()
|
||||
R|kotlin/io/println|(R|<local>/x|)
|
||||
R|kotlin/io/println|(R|<local>/y|)
|
||||
}
|
||||
)
|
||||
}
|
||||
Generated
+5
@@ -34,6 +34,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/arrayFirstOrNull.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("components.kt")
|
||||
public void testComponents() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/components.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("concurrent.kt")
|
||||
public void testConcurrent() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/concurrent.kt");
|
||||
|
||||
Reference in New Issue
Block a user