Fix raw FIR building with parenthesized expression as selector

This commit is contained in:
Mikhail Glukhikh
2019-12-24 13:30:04 +03:00
parent a18fecb05f
commit a8a50fa657
21 changed files with 115 additions and 34 deletions
@@ -440,17 +440,29 @@ class ExpressionsConverter(
val valueArguments = mutableListOf<LighterASTNode>() val valueArguments = mutableListOf<LighterASTNode>()
var additionalArgument: FirExpression? = null var additionalArgument: FirExpression? = null
var hasArguments = false var hasArguments = false
callSuffix.forEachChildren { callSuffix.forEachChildren { child ->
when (it.tokenType) { fun process(node: LighterASTNode) {
REFERENCE_EXPRESSION -> name = it.asText when (node.tokenType) {
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it) REFERENCE_EXPRESSION -> {
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> { name = node.asText
hasArguments = true }
valueArguments += it PARENTHESIZED -> node.getExpressionInParentheses()?.let { process(it) } ?: run {
additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver")
}
TYPE_ARGUMENT_LIST -> {
firTypeArguments += declarationsConverter.convertTypeArguments(node)
}
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> {
hasArguments = true
valueArguments += node
}
else -> if (node.tokenType != TokenType.ERROR_ELEMENT) {
additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver")
}
} }
else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument =
getAsFirExpression(it, "Incorrect invoke receiver")
} }
process(child)
} }
val (calleeReference, explicitReceiver) = when { val (calleeReference, explicitReceiver) = when {
@@ -213,6 +213,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt");
}
@TestMetadata("init.kt") @TestMetadata("init.kt")
public void testInit() throws Exception { public void testInit() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement
import org.jetbrains.kotlin.fir.impl.FirLabelImpl import org.jetbrains.kotlin.fir.impl.FirLabelImpl
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.impl.* import org.jetbrains.kotlin.fir.references.impl.*
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -1253,23 +1254,29 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
} }
} }
override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement { private fun splitToCalleeAndReceiver(
val calleeExpression = expression.calleeExpression calleeExpression: KtExpression?,
val source = expression.toFirSourceElement() defaultSource: FirPsiSourceElement
): Pair<FirNamedReference, FirExpression?> {
val (calleeReference, explicitReceiver) = when (calleeExpression) { return when (calleeExpression) {
is KtSimpleNameExpression -> FirSimpleNamedReference( is KtSimpleNameExpression -> FirSimpleNamedReference(
calleeExpression.toFirSourceElement(), calleeExpression.getReferencedNameAsName(), null calleeExpression.toFirSourceElement(), calleeExpression.getReferencedNameAsName(), null
) to null ) to null
is KtParenthesizedExpression -> splitToCalleeAndReceiver(calleeExpression.expression, defaultSource)
null -> FirErrorNamedReferenceImpl( null -> FirErrorNamedReferenceImpl(
null, FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) null, FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax)
) to null ) to null
else -> { else -> {
FirSimpleNamedReference( FirSimpleNamedReference(
source, OperatorNameConventions.INVOKE, null defaultSource, OperatorNameConventions.INVOKE, null
) to calleeExpression.toFirExpression("Incorrect invoke receiver") ) to calleeExpression.toFirExpression("Incorrect invoke receiver")
} }
} }
}
override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement {
val source = expression.toFirSourceElement()
val (calleeReference, explicitReceiver) = splitToCalleeAndReceiver(expression.calleeExpression, source)
val result = if (expression.valueArgumentList == null && expression.lambdaArguments.isEmpty()) { val result = if (expression.valueArgumentList == null && expression.lambdaArguments.isEmpty()) {
FirQualifiedAccessExpressionImpl(source).apply { FirQualifiedAccessExpressionImpl(source).apply {
@@ -0,0 +1,4 @@
fun test(e: Int.() -> String) {
val s = 3.e()
val ss = 3.(e)()
}
@@ -0,0 +1,5 @@
FILE: inBrackets.kt
public? final? fun test(e: ( Int.() -> String )): R|kotlin/Unit| {
lval s: <implicit> = IntegerLiteral(3).e#()
lval ss: <implicit> = IntegerLiteral(3).e#()
}
@@ -213,6 +213,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt");
}
@TestMetadata("init.kt") @TestMetadata("init.kt")
public void testInit() throws Exception { public void testInit() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");
@@ -0,0 +1,4 @@
fun test(e: Int.() -> String) {
val s = 3.<!UNRESOLVED_REFERENCE!>e<!>()
val ss = 3.(<!UNRESOLVED_REFERENCE!>e<!>)()
}
@@ -0,0 +1,5 @@
FILE: inBrackets.kt
public final fun test(e: R|kotlin/Int.() -> kotlin/String|): R|kotlin/Unit| {
lval s: <ERROR TYPE REF: Unresolved name: e> = Int(3).<Unresolved name: e>#()
lval ss: <ERROR TYPE REF: Unresolved name: e> = Int(3).<Unresolved name: e>#()
}
@@ -679,6 +679,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt"); runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt");
}
@TestMetadata("propertyFromParameter.kt") @TestMetadata("propertyFromParameter.kt")
public void testPropertyFromParameter() throws Exception { public void testPropertyFromParameter() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt"); runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt");
@@ -679,6 +679,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt"); runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt");
}
@TestMetadata("propertyFromParameter.kt") @TestMetadata("propertyFromParameter.kt")
public void testPropertyFromParameter() throws Exception { public void testPropertyFromParameter() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt"); runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt");
@@ -45,7 +45,7 @@ fun test() {
x4 checkType { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Unit>>() } x4 checkType { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Unit>>() }
{ y: Int -> fun named14(): Int {return 1} } { y: Int -> fun named14(): Int {return 1} }
val b = <!UNRESOLVED_REFERENCE!><!INFERENCE_ERROR!>(fun named15(): Boolean { return true })<!>()<!> val b = <!UNRESOLVED_REFERENCE!>(<!INFERENCE_ERROR!>fun named15(): Boolean { return true }<!>)()<!>
baz(<!INFERENCE_ERROR!>fun named16(){}<!>) baz(<!INFERENCE_ERROR!>fun named16(){}<!>)
} }
@@ -10,7 +10,7 @@ enum class E {
val foo: Any.() -> Unit = {} val foo: Any.() -> Unit = {}
fun f1() = E.FIRST.<!UNRESOLVED_REFERENCE!>foo<!>() fun f1() = E.FIRST.<!UNRESOLVED_REFERENCE!>foo<!>()
fun f2() = E.FIRST.<!UNRESOLVED_REFERENCE!>(foo)()<!> fun f2() = E.FIRST.(<!UNRESOLVED_REFERENCE!>foo<!>)()
fun f3() = E.SECOND.<!UNRESOLVED_REFERENCE!>foo<!>() fun f3() = E.SECOND.<!UNRESOLVED_REFERENCE!>foo<!>()
fun f4() = E.SECOND.<!UNRESOLVED_REFERENCE!>(foo)()<!> fun f4() = E.SECOND.(<!UNRESOLVED_REFERENCE!>foo<!>)()
fun f5() = E.SECOND.A() fun f5() = E.SECOND.A()
@@ -10,7 +10,7 @@ enum class E {
val foo: Any.() -> Unit = {} val foo: Any.() -> Unit = {}
fun f1() = E.FIRST.<!UNRESOLVED_REFERENCE!>foo<!>() fun f1() = E.FIRST.<!UNRESOLVED_REFERENCE!>foo<!>()
fun f2() = E.FIRST.<!UNRESOLVED_REFERENCE!>(foo)()<!> fun f2() = E.FIRST.(<!UNRESOLVED_REFERENCE!>foo<!>)()
fun f3() = E.SECOND.<!UNRESOLVED_REFERENCE!>foo<!>() fun f3() = E.SECOND.<!UNRESOLVED_REFERENCE!>foo<!>()
fun f4() = E.SECOND.<!UNRESOLVED_REFERENCE!>(foo)()<!> fun f4() = E.SECOND.(<!UNRESOLVED_REFERENCE!>foo<!>)()
fun f5() = E.SECOND.A() fun f5() = E.SECOND.A()
@@ -1,5 +1,5 @@
fun test1(f: String.() -> Unit) { fun test1(f: String.() -> Unit) {
<!INAPPLICABLE_CANDIDATE!>(f)()<!> (<!INAPPLICABLE_CANDIDATE!>f<!>)()
<!INAPPLICABLE_CANDIDATE!>f<!>() <!INAPPLICABLE_CANDIDATE!>f<!>()
} }
@@ -7,5 +7,5 @@ fun test1(f: String.() -> Unit) {
fun test2(f: (Int) -> Int) { fun test2(f: (Int) -> Int) {
1.<!UNRESOLVED_REFERENCE!>f<!>(2) 1.<!UNRESOLVED_REFERENCE!>f<!>(2)
2.<!UNRESOLVED_REFERENCE!>(f)(2)<!> 2.(<!UNRESOLVED_REFERENCE!>f<!>)(2)
} }
@@ -6,8 +6,8 @@ fun test1() {
} }
fun test2(f: String.(Int) -> Unit) { fun test2(f: String.(Int) -> Unit) {
11.<!UNRESOLVED_REFERENCE!>(f)(1)<!> 11.(<!UNRESOLVED_REFERENCE!>f<!>)(1)
11.<!UNRESOLVED_REFERENCE!>(f)()<!> 11.(<!UNRESOLVED_REFERENCE!>f<!>)()
} }
fun test3() { fun test3() {
@@ -25,9 +25,9 @@ fun test(c: () -> String, e: Int.() -> String) {
(c)() (c)()
3.<!UNRESOLVED_REFERENCE!>e<!>() 3.<!UNRESOLVED_REFERENCE!>e<!>()
3.<!UNRESOLVED_REFERENCE!>(e)()<!> 3.(<!UNRESOLVED_REFERENCE!>e<!>)()
with(3) { with(3) {
<!INAPPLICABLE_CANDIDATE!>e<!>() <!INAPPLICABLE_CANDIDATE!>e<!>()
<!INAPPLICABLE_CANDIDATE!>(e)()<!> (<!INAPPLICABLE_CANDIDATE!>e<!>)()
} }
} }
@@ -15,7 +15,7 @@ fun test(a: A, b: B) {
with(a) { with(a) {
b.<!UNRESOLVED_REFERENCE!>foo<!>() b.<!UNRESOLVED_REFERENCE!>foo<!>()
b.<!UNRESOLVED_REFERENCE!>(foo)()<!> b.(<!UNRESOLVED_REFERENCE!>foo<!>)()
<!UNRESOLVED_REFERENCE!>(b.<!INAPPLICABLE_CANDIDATE!>foo<!>)()<!> <!UNRESOLVED_REFERENCE!>(b.<!INAPPLICABLE_CANDIDATE!>foo<!>)()<!>
@@ -25,7 +25,7 @@ fun test(a: A, b: B) {
with(b) { with(b) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.<!UNRESOLVED_REFERENCE!>(foo)()<!> a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!> <!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
@@ -36,7 +36,7 @@ fun test(a: A, b: B) {
with(a) { with(a) {
with(b) { with(b) {
<!INAPPLICABLE_CANDIDATE!>foo<!>() <!INAPPLICABLE_CANDIDATE!>foo<!>()
<!INAPPLICABLE_CANDIDATE!>(foo)()<!> (<!INAPPLICABLE_CANDIDATE!>foo<!>)()
} }
} }
} }
@@ -57,7 +57,7 @@ fun test(a: A, b: B) {
with(a) { with(a) {
b.<!UNRESOLVED_REFERENCE!>foo<!>() b.<!UNRESOLVED_REFERENCE!>foo<!>()
b.<!UNRESOLVED_REFERENCE!>(foo)()<!> b.(<!UNRESOLVED_REFERENCE!>foo<!>)()
<!UNRESOLVED_REFERENCE!>(b.<!UNRESOLVED_REFERENCE!>foo<!>)()<!> <!UNRESOLVED_REFERENCE!>(b.<!UNRESOLVED_REFERENCE!>foo<!>)()<!>
@@ -67,7 +67,7 @@ fun test(a: A, b: B) {
with(b) { with(b) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.<!UNRESOLVED_REFERENCE!>(foo)()<!> a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!> <!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
@@ -78,7 +78,7 @@ fun test(a: A, b: B) {
with(a) { with(a) {
with(b) { with(b) {
<!INAPPLICABLE_CANDIDATE!>foo<!>() <!INAPPLICABLE_CANDIDATE!>foo<!>()
<!INAPPLICABLE_CANDIDATE!>(foo)()<!> (<!INAPPLICABLE_CANDIDATE!>foo<!>)()
} }
} }
} }
@@ -9,10 +9,10 @@ val B.a: () -> Int get() = { 5 }
fun test(a: A, b: B) { fun test(a: A, b: B) {
val x: Int = b.a() val x: Int = b.a()
b.<!UNRESOLVED_REFERENCE!>(a)()<!> b.(a)()
with(b) { with(b) {
val y: Int = <!UNRESOLVED_REFERENCE!>a<!>() val y: Int = <!UNRESOLVED_REFERENCE!>a<!>()
<!UNRESOLVED_REFERENCE!>(a)()<!> (<!UNRESOLVED_REFERENCE!>a<!>)()
} }
} }
@@ -0,0 +1,14 @@
// FIR_IGNORE
fun test(e: Int.() -> String) {
// String
// │ Int
// │ │ fun Int.invoke(): String
// │ │ │
val s = 3.e()
// String
// │ Int
// │ │ fun Int.invoke(): String
// │ │ │test.e: Int.() -> String
// │ │ ││
val ss = 3.(e)()
}
@@ -213,6 +213,11 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizer {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt");
}
@TestMetadata("init.kt") @TestMetadata("init.kt")
public void testInit() throws Exception { public void testInit() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");
@@ -213,6 +213,11 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizer {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt");
} }
@TestMetadata("inBrackets.kt")
public void testInBrackets() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt");
}
@TestMetadata("init.kt") @TestMetadata("init.kt")
public void testInit() throws Exception { public void testInit() throws Exception {
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");