[compiler] preserve fir receiver in tree
when selector is invalid expression, ensure that fir tree still contains receiver as well as selector KTIJ-23578
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
fun main(args: Array<String>) {
|
||||
val anyClass = Any()
|
||||
funOne(<expr>anyClass</expr>.class)
|
||||
}
|
||||
|
||||
fun funOne(x: Any): Unit {}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirPropertyAccessExpressionImpl
|
||||
FIR source kind: KtRealSourceElementKind
|
||||
|
||||
FIR element rendered:
|
||||
R|<local>/anyClass|
|
||||
+16
@@ -540,6 +540,22 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class InvalidCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInInvalidCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaClassLiteral.kt")
|
||||
public void testJavaClassLiteral() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode/javaClassLiteral.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/low-level-api-fir/testdata/getOrBuildFir/qualifiedExpressions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+12
@@ -557,6 +557,18 @@ class ExpressionsConverter(
|
||||
result = convertFirSelector(it, dotQualifiedExpression.toFirSourceElement(), firReceiver!!) as? FirExpression
|
||||
}
|
||||
|
||||
val receiver = firReceiver
|
||||
if (receiver != null) {
|
||||
(firSelector as? FirErrorExpression)?.let { errorExpression ->
|
||||
return buildQualifiedErrorAccessExpression {
|
||||
this.receiver = receiver
|
||||
this.selector = errorExpression
|
||||
source = dotQualifiedExpression.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic("Qualified expression with unexpected selector", DiagnosticKind.Syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result ?: buildErrorExpression {
|
||||
source = null
|
||||
diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax)
|
||||
|
||||
@@ -2462,6 +2462,14 @@ open class RawFirBuilder(
|
||||
|
||||
return convertFirSelector(firSelector, expression.toFirSourceElement(), receiver)
|
||||
}
|
||||
if (firSelector is FirErrorExpression) {
|
||||
return buildQualifiedErrorAccessExpression {
|
||||
this.receiver = receiver
|
||||
this.selector = firSelector
|
||||
source = expression.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic("Qualified expression with unexpected selector", DiagnosticKind.Syntax)
|
||||
}
|
||||
}
|
||||
return firSelector
|
||||
}
|
||||
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.expressions
|
||||
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirQualifiedErrorAccessExpression : FirExpression(), FirDiagnosticHolder {
|
||||
abstract override val source: KtSourceElement?
|
||||
abstract override val typeRef: FirTypeRef
|
||||
abstract override val annotations: List<FirAnnotation>
|
||||
abstract override val diagnostic: ConeDiagnostic
|
||||
abstract val selector: FirErrorExpression
|
||||
abstract val receiver: FirExpression
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedErrorAccessExpression(this, data)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
|
||||
transformer.transformQualifiedErrorAccessExpression(this, data) as E
|
||||
|
||||
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
|
||||
|
||||
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedErrorAccessExpression
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.builder
|
||||
|
||||
import kotlin.contracts.*
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedErrorAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
@FirBuilderDsl
|
||||
class FirQualifiedErrorAccessExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
|
||||
override var source: KtSourceElement? = null
|
||||
override val annotations: MutableList<FirAnnotation> = mutableListOf()
|
||||
lateinit var diagnostic: ConeDiagnostic
|
||||
lateinit var selector: FirErrorExpression
|
||||
lateinit var receiver: FirExpression
|
||||
|
||||
override fun build(): FirQualifiedErrorAccessExpression {
|
||||
return FirQualifiedErrorAccessExpressionImpl(
|
||||
source,
|
||||
annotations,
|
||||
diagnostic,
|
||||
selector,
|
||||
receiver,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Deprecated("Modification of 'typeRef' has no impact for FirQualifiedErrorAccessExpressionBuilder", level = DeprecationLevel.HIDDEN)
|
||||
override var typeRef: FirTypeRef
|
||||
get() = throw IllegalStateException()
|
||||
set(_) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun buildQualifiedErrorAccessExpression(init: FirQualifiedErrorAccessExpressionBuilder.() -> Unit): FirQualifiedErrorAccessExpression {
|
||||
contract {
|
||||
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return FirQualifiedErrorAccessExpressionBuilder().apply(init).build()
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.impl
|
||||
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
internal class FirQualifiedErrorAccessExpressionImpl(
|
||||
override val source: KtSourceElement?,
|
||||
override val annotations: MutableList<FirAnnotation>,
|
||||
override val diagnostic: ConeDiagnostic,
|
||||
override var selector: FirErrorExpression,
|
||||
override var receiver: FirExpression,
|
||||
) : FirQualifiedErrorAccessExpression() {
|
||||
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic), false)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
typeRef.accept(visitor, data)
|
||||
annotations.forEach { it.accept(visitor, data) }
|
||||
selector.accept(visitor, data)
|
||||
receiver.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirQualifiedErrorAccessExpressionImpl {
|
||||
typeRef = typeRef.transform(transformer, data)
|
||||
transformAnnotations(transformer, data)
|
||||
selector = selector.transform(transformer, data)
|
||||
receiver = receiver.transform(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedErrorAccessExpressionImpl {
|
||||
annotations.transformInplace(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
|
||||
typeRef = newTypeRef
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
|
||||
@@ -93,6 +93,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
|
||||
@@ -93,6 +93,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
@@ -500,6 +501,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformElement(qualifiedAccessExpression, data)
|
||||
}
|
||||
|
||||
open fun transformQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: D): FirStatement {
|
||||
return transformElement(qualifiedErrorAccessExpression, data)
|
||||
}
|
||||
|
||||
open fun transformPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression, data: D): FirStatement {
|
||||
return transformElement(propertyAccessExpression, data)
|
||||
}
|
||||
@@ -1048,6 +1053,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformQualifiedAccessExpression(qualifiedAccessExpression, data)
|
||||
}
|
||||
|
||||
final override fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: D): FirStatement {
|
||||
return transformQualifiedErrorAccessExpression(qualifiedErrorAccessExpression, data)
|
||||
}
|
||||
|
||||
final override fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression, data: D): FirStatement {
|
||||
return transformPropertyAccessExpression(propertyAccessExpression, data)
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
@@ -325,6 +326,8 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): R = visitElement(qualifiedAccessExpression, data)
|
||||
|
||||
open fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: D): R = visitElement(qualifiedErrorAccessExpression, data)
|
||||
|
||||
open fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression, data: D): R = visitElement(propertyAccessExpression, data)
|
||||
|
||||
open fun visitFunctionCall(functionCall: FirFunctionCall, data: D): R = visitElement(functionCall, data)
|
||||
|
||||
@@ -93,6 +93,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
@@ -499,6 +500,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(qualifiedAccessExpression)
|
||||
}
|
||||
|
||||
open fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression) {
|
||||
visitElement(qualifiedErrorAccessExpression)
|
||||
}
|
||||
|
||||
open fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression) {
|
||||
visitElement(propertyAccessExpression)
|
||||
}
|
||||
@@ -1047,6 +1052,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitQualifiedAccessExpression(qualifiedAccessExpression)
|
||||
}
|
||||
|
||||
final override fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: Nothing?) {
|
||||
visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression)
|
||||
}
|
||||
|
||||
final override fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression, data: Nothing?) {
|
||||
visitPropertyAccessExpression(propertyAccessExpression)
|
||||
}
|
||||
|
||||
+1
@@ -116,6 +116,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val errorFunction by element(Declaration, function, diagnosticHolder)
|
||||
val errorProperty by element(Declaration, variable, diagnosticHolder)
|
||||
val qualifiedAccessExpression by element(Expression, expression, qualifiedAccess)
|
||||
val qualifiedErrorAccessExpression by element(Expression, expression, diagnosticHolder)
|
||||
val propertyAccessExpression by element(Expression, qualifiedAccessExpression)
|
||||
val functionCall by element(Expression, qualifiedAccessExpression, call)
|
||||
val integerLiteralOperatorCall by element(Expression, functionCall)
|
||||
|
||||
+5
@@ -433,6 +433,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
useTypes(errorTypeRefImplType, coneStubDiagnosticType)
|
||||
}
|
||||
|
||||
impl(qualifiedErrorAccessExpression) {
|
||||
default("typeRef", "FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic), false)")
|
||||
useTypes(errorTypeRefImplType, coneStubDiagnosticType)
|
||||
}
|
||||
|
||||
impl(errorFunction) {
|
||||
defaultNull("receiverParameter", "body", withGetter = true)
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, null, diagnostic, false)")
|
||||
|
||||
+5
@@ -207,6 +207,11 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+fieldList("nonFatalDiagnostics", coneDiagnosticType)
|
||||
}
|
||||
|
||||
qualifiedErrorAccessExpression.configure {
|
||||
+field("selector", errorExpression)
|
||||
+field("receiver", expression)
|
||||
}
|
||||
|
||||
constExpression.configure {
|
||||
withArg("T")
|
||||
+field("kind", constKindType.withArgs("T"), withReplace = true)
|
||||
|
||||
+2
-2
@@ -3,6 +3,6 @@
|
||||
fun test() {
|
||||
"a".<!ILLEGAL_SELECTOR!>"b"<!>::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
"a".<!ILLEGAL_SELECTOR!>"b"<!>::class
|
||||
"a"."b".<!ILLEGAL_SELECTOR!>"c"<!>::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
"a"."b".<!ILLEGAL_SELECTOR!>"c"<!>::class
|
||||
"a".<!ILLEGAL_SELECTOR!>"b"<!>.<!ILLEGAL_SELECTOR!>"c"<!>::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
"a".<!ILLEGAL_SELECTOR!>"b"<!>.<!ILLEGAL_SELECTOR!>"c"<!>::class
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user