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.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||||
import org.jetbrains.kotlin.fir.types.impl.*
|
import org.jetbrains.kotlin.fir.types.impl.*
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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
|
firClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,18 @@ FILE: destructuring.kt
|
|||||||
public? final? val third: String = R|<local>/third|
|
public? final? val third: String = R|<local>/third|
|
||||||
public? get(): String
|
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 {
|
public? final? fun foo(some: Some): kotlin/Unit {
|
||||||
lval <destruct>: <implicit> = some#
|
lval <destruct>: <implicit> = some#
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ FILE: for.kt
|
|||||||
public? final? val y: Int = R|<local>/y|
|
public? final? val y: Int = R|<local>/y|
|
||||||
public? get(): Int
|
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 {
|
public? final? fun baz(set: Set<Some>): kotlin/Unit {
|
||||||
lval <range>: <implicit> = set#
|
lval <range>: <implicit> = set#
|
||||||
|
|||||||
@@ -10,6 +10,14 @@ FILE: lambda.kt
|
|||||||
public? final? val y: Int = R|<local>/y|
|
public? final? val y: Int = R|<local>/y|
|
||||||
public? get(): Int
|
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> {
|
public? final? inline fun use(f: ( (Tuple) -> Int )): <implicit> {
|
||||||
^use f#(Tuple#(Int(1), Int(2)))
|
^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");
|
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")
|
@TestMetadata("concurrent.kt")
|
||||||
public void testConcurrent() throws Exception {
|
public void testConcurrent() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/concurrent.kt");
|
runTest("compiler/fir/resolve/testData/resolve/stdlib/concurrent.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user