FIR: Fix label/receiver for lambda within infix calls
While this fix only changes label name, it's important for proper lambda resolution because receiver is set for a lambda only in presence of a label This commit fixes a lot of checkType calls in diagnostic tests
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
class A {
|
||||||
|
fun bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun (() -> Unit).foo(x: A.() -> Unit) {}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
{
|
||||||
|
return@foo
|
||||||
|
} foo {
|
||||||
|
bar()
|
||||||
|
return@foo
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
FILE: labelAndReceiverForInfix.kt
|
||||||
|
public final class A : R|kotlin/Any| {
|
||||||
|
public constructor(): R|A| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun bar(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final infix fun R|() -> kotlin/Unit|.foo(x: R|A.() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun main(): R|kotlin/Unit| {
|
||||||
|
foo@fun <anonymous>(): R|kotlin/Unit| {
|
||||||
|
^@foo Unit
|
||||||
|
}
|
||||||
|
.R|/foo|(foo@fun R|A|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|/A.bar|()
|
||||||
|
^@foo Unit
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
Generated
+5
@@ -228,6 +228,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelAndReceiverForInfix.kt")
|
||||||
|
public void testLabelAndReceiverForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgInScopeFunction.kt")
|
@TestMetadata("lambdaArgInScopeFunction.kt")
|
||||||
public void testLambdaArgInScopeFunction() throws Exception {
|
public void testLambdaArgInScopeFunction() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.kt");
|
||||||
|
|||||||
+5
@@ -228,6 +228,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelAndReceiverForInfix.kt")
|
||||||
|
public void testLabelAndReceiverForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgInScopeFunction.kt")
|
@TestMetadata("lambdaArgInScopeFunction.kt")
|
||||||
public void testLambdaArgInScopeFunction() throws Exception {
|
public void testLambdaArgInScopeFunction() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.kt");
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import org.jetbrains.kotlin.fir.FirFunctionTarget
|
|||||||
import org.jetbrains.kotlin.fir.FirLabel
|
import org.jetbrains.kotlin.fir.FirLabel
|
||||||
import org.jetbrains.kotlin.fir.FirLoopTarget
|
import org.jetbrains.kotlin.fir.FirLoopTarget
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.FirFunctionCallBuilder
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class Context<T> {
|
class Context<T> {
|
||||||
lateinit var packageFqName: FqName
|
lateinit var packageFqName: FqName
|
||||||
@@ -21,9 +21,9 @@ class Context<T> {
|
|||||||
val currentClassId get() = ClassId(packageFqName, className, firFunctionTargets.isNotEmpty())
|
val currentClassId get() = ClassId(packageFqName, className, firFunctionTargets.isNotEmpty())
|
||||||
|
|
||||||
val firFunctionTargets = mutableListOf<FirFunctionTarget>()
|
val firFunctionTargets = mutableListOf<FirFunctionTarget>()
|
||||||
val firFunctionCalls = mutableListOf<FirFunctionCallBuilder>()
|
val calleeNamesForLambda = mutableListOf<Name>()
|
||||||
val firLabels = mutableListOf<FirLabel>()
|
val firLabels = mutableListOf<FirLabel>()
|
||||||
val firLoopTargets = mutableListOf<FirLoopTarget>()
|
val firLoopTargets = mutableListOf<FirLoopTarget>()
|
||||||
var capturedTypeParameters = persistentListOf<FirTypeParameterSymbol>()
|
var capturedTypeParameters = persistentListOf<FirTypeParameterSymbol>()
|
||||||
val arraySetArgument = mutableMapOf<T, FirExpression>()
|
val arraySetArgument = mutableMapOf<T, FirExpression>()
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-5
@@ -137,7 +137,7 @@ class ExpressionsConverter(
|
|||||||
receiverTypeRef = implicitType
|
receiverTypeRef = implicitType
|
||||||
symbol = FirAnonymousFunctionSymbol()
|
symbol = FirAnonymousFunctionSymbol()
|
||||||
isLambda = true
|
isLambda = true
|
||||||
label = context.firLabels.pop() ?: context.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
|
label = context.firLabels.pop() ?: context.calleeNamesForLambda.lastOrNull()?.let {
|
||||||
buildLabel { name = it.asString() }
|
buildLabel { name = it.asString() }
|
||||||
}
|
}
|
||||||
target = FirFunctionTarget(labelName = label?.name, isLambda = true)
|
target = FirFunctionTarget(labelName = label?.name, isLambda = true)
|
||||||
@@ -203,7 +203,6 @@ class ExpressionsConverter(
|
|||||||
var isLeftArgument = true
|
var isLeftArgument = true
|
||||||
lateinit var operationTokenName: String
|
lateinit var operationTokenName: String
|
||||||
var leftArgNode: LighterASTNode? = null
|
var leftArgNode: LighterASTNode? = null
|
||||||
var rightArgAsFir: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No right operand", DiagnosticKind.Syntax))
|
|
||||||
var rightArg: LighterASTNode? = null
|
var rightArg: LighterASTNode? = null
|
||||||
var operationReferenceSource: FirLightSourceElement? = null
|
var operationReferenceSource: FirLightSourceElement? = null
|
||||||
binaryExpression.forEachChildren {
|
binaryExpression.forEachChildren {
|
||||||
@@ -217,7 +216,6 @@ class ExpressionsConverter(
|
|||||||
if (isLeftArgument) {
|
if (isLeftArgument) {
|
||||||
leftArgNode = it
|
leftArgNode = it
|
||||||
} else {
|
} else {
|
||||||
rightArgAsFir = getAsFirExpression(it, "No right operand")
|
|
||||||
rightArg = it
|
rightArg = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +224,23 @@ class ExpressionsConverter(
|
|||||||
|
|
||||||
val baseSource = binaryExpression.toFirSourceElement()
|
val baseSource = binaryExpression.toFirSourceElement()
|
||||||
val operationToken = operationTokenName.getOperationSymbol()
|
val operationToken = operationTokenName.getOperationSymbol()
|
||||||
|
if (operationToken == IDENTIFIER) {
|
||||||
|
context.calleeNamesForLambda += operationTokenName.nameAsSafeName()
|
||||||
|
}
|
||||||
|
|
||||||
|
val rightArgAsFir =
|
||||||
|
if (rightArg != null)
|
||||||
|
getAsFirExpression<FirExpression>(rightArg, "No right operand")
|
||||||
|
else
|
||||||
|
buildErrorExpression(null, ConeSimpleDiagnostic("No right operand", DiagnosticKind.Syntax))
|
||||||
|
|
||||||
val leftArgAsFir = getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
val leftArgAsFir = getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
||||||
|
|
||||||
|
if (operationToken == IDENTIFIER) {
|
||||||
|
// No need for the callee name since arguments are already generated
|
||||||
|
context.calleeNamesForLambda.removeLast()
|
||||||
|
}
|
||||||
|
|
||||||
when (operationToken) {
|
when (operationToken) {
|
||||||
ELVIS ->
|
ELVIS ->
|
||||||
return leftArgAsFir.generateNotNullOrOther(baseSession, rightArgAsFir, "elvis", baseSource)
|
return leftArgAsFir.generateNotNullOrOther(baseSession, rightArgAsFir, "elvis", baseSource)
|
||||||
@@ -544,9 +558,9 @@ class ExpressionsConverter(
|
|||||||
this.source = source
|
this.source = source
|
||||||
this.calleeReference = calleeReference
|
this.calleeReference = calleeReference
|
||||||
|
|
||||||
context.firFunctionCalls += this
|
context.calleeNamesForLambda += calleeReference.name
|
||||||
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
||||||
context.firFunctionCalls.removeLast()
|
context.calleeNamesForLambda.removeLast()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FirQualifiedAccessExpressionBuilder().apply {
|
FirQualifiedAccessExpressionBuilder().apply {
|
||||||
|
|||||||
+5
@@ -248,6 +248,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
|
|||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelForInfix.kt")
|
||||||
|
public void testLabelForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||||
|
|||||||
@@ -911,7 +911,7 @@ class RawFirBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val expressionSource = expression.toFirSourceElement()
|
val expressionSource = expression.toFirSourceElement()
|
||||||
label = context.firLabels.pop() ?: context.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
|
label = context.firLabels.pop() ?: context.calleeNamesForLambda.lastOrNull()?.let {
|
||||||
buildLabel {
|
buildLabel {
|
||||||
source = expressionSource
|
source = expressionSource
|
||||||
name = it.asString()
|
name = it.asString()
|
||||||
@@ -1472,9 +1472,21 @@ class RawFirBuilder(
|
|||||||
|
|
||||||
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): FirElement {
|
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): FirElement {
|
||||||
val operationToken = expression.operationToken
|
val operationToken = expression.operationToken
|
||||||
|
|
||||||
|
if (operationToken == IDENTIFIER) {
|
||||||
|
context.calleeNamesForLambda += expression.operationReference.getReferencedNameAsName()
|
||||||
|
}
|
||||||
|
|
||||||
val leftArgument = expression.left.toFirExpression("No left operand")
|
val leftArgument = expression.left.toFirExpression("No left operand")
|
||||||
val rightArgument = expression.right.toFirExpression("No right operand")
|
val rightArgument = expression.right.toFirExpression("No right operand")
|
||||||
|
|
||||||
|
if (operationToken == IDENTIFIER) {
|
||||||
|
// No need for the callee name since arguments are already generated
|
||||||
|
context.calleeNamesForLambda.removeLast()
|
||||||
|
}
|
||||||
|
|
||||||
val source = expression.toFirSourceElement()
|
val source = expression.toFirSourceElement()
|
||||||
|
|
||||||
when (operationToken) {
|
when (operationToken) {
|
||||||
ELVIS ->
|
ELVIS ->
|
||||||
return leftArgument.generateNotNullOrOther(baseSession, rightArgument, "elvis", source)
|
return leftArgument.generateNotNullOrOther(baseSession, rightArgument, "elvis", source)
|
||||||
@@ -1617,9 +1629,9 @@ class RawFirBuilder(
|
|||||||
FirFunctionCallBuilder().apply {
|
FirFunctionCallBuilder().apply {
|
||||||
this.source = source
|
this.source = source
|
||||||
this.calleeReference = calleeReference
|
this.calleeReference = calleeReference
|
||||||
context.firFunctionCalls += this
|
context.calleeNamesForLambda += calleeReference.name
|
||||||
expression.extractArgumentsTo(this)
|
expression.extractArgumentsTo(this)
|
||||||
context.firFunctionCalls.removeLast()
|
context.calleeNamesForLambda.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
{ length } foo { bar() }
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
FILE: labelForInfix.kt
|
||||||
|
public? final? fun main(): R|kotlin/Unit| {
|
||||||
|
foo@fun <implicit>.<anonymous>(): <implicit> {
|
||||||
|
length#
|
||||||
|
}
|
||||||
|
.foo#(foo@fun <implicit>.<anonymous>(): <implicit> {
|
||||||
|
bar#()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
+5
@@ -248,6 +248,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
|||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelForInfix.kt")
|
||||||
|
public void testLabelForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun test(x: Int): Int {
|
fun test(x: Int): Int {
|
||||||
x myMap {
|
x myMap {
|
||||||
return@myMap
|
return@myMap
|
||||||
@@ -22,4 +21,4 @@ fun box(): String {
|
|||||||
myMap(0)
|
myMap(0)
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -248,6 +248,11 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizer {
|
|||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelForInfix.kt")
|
||||||
|
public void testLabelForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||||
|
|||||||
+5
@@ -248,6 +248,11 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizer {
|
|||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("labelForInfix.kt")
|
||||||
|
public void testLabelForInfix() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user