From 12e1eb0436ba645d78231d3b39dc745b9c9c3a49 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 13 Oct 2024 15:10:32 -0700 Subject: [PATCH] KT UAST: bail out unexpected expression type ...if source PSI is not expression, e.g., constructor delegation call ^KTIJ-31633 fixed GitOrigin-RevId: 8bfb67cf51262478736862cc05f529aee549714c --- .../KotlinUFunctionCallExpression.kt | 5 +++ .../common/kotlin/UastApiFixtureTestBase.kt | 37 +++++++++++++++++++ .../fir/uast/test/FirUastApiFixtureTest.kt | 4 ++ .../legacyTypes/CommentOwners.types.fir.txt | 2 +- .../legacyTypes/Constructors.types.fir.txt | 14 +++---- .../legacyTypes/SuperCalls.types.fir.txt | 6 +-- .../comparison/FE1UastApiFixtureTest.kt | 4 ++ 7 files changed, 61 insertions(+), 11 deletions(-) diff --git a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt index 81e7b542f1f6..45d3c628dad5 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt @@ -145,6 +145,11 @@ class KotlinUFunctionCallExpression( } override fun getExpressionType(): PsiType? { + if (sourcePsi !is KtExpression) { + // E.g., constructor(...) : this(...) + // [KtConstructorDelegationCall] is a subtype of [KtCallElement], but not [KtExpression] + return null + } // KTIJ-17870: One-off handling for instantiation of local classes if (classReference != null) { // [classReference] is created only if this call expression is resolved to constructor. diff --git a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt index fa0e80d9644a..6fb1808b313c 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt @@ -994,6 +994,43 @@ interface UastApiFixtureTestBase { }) } + fun checkExpressionTypeForConstructorDelegationCall(myFixture: JavaCodeInsightTestFixture) { + // Regression test from KTIJ-31633 + myFixture.configureByText( + "main.kt", """ + class Constructors { + class ThisCall { + constructor() // (1) + constructor(i: Int) : this() // (2) + } + open class SuperCallToImplicit { + class C : SuperCallToImplicit { + constructor() : super() // (3) + } + } + open class SuperCallToExplicit { + constructor() // (4) + class C : SuperCallToExplicit { + constructor() : super() // (5) + } + } + } + """.trimIndent() + ) + var count = 0 + myFixture.file.toUElement()!!.accept( + object : AbstractUastVisitor() { + override fun visitCallExpression(node: UCallExpression): Boolean { + val t = node.getExpressionType() + TestCase.assertNull(node.sourcePsi?.text ?: "", t) + count++ + return super.visitCallExpression(node) + } + } + ) + TestCase.assertEquals(5, count) + } + fun checkFlexibleFunctionalInterfaceType(myFixture: JavaCodeInsightTestFixture) { myFixture.addClass( """ diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt index c59fc8047221..10da89ca83f7 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt @@ -126,6 +126,10 @@ class FirUastApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), UastApiFi checkExpressionTypeForCallToInternalOperator(myFixture) } + fun testExpressionTypeForConstructorDelegationCall() { + checkExpressionTypeForConstructorDelegationCall(myFixture) + } + fun testFlexibleFunctionalInterfaceType() { checkFlexibleFunctionalInterfaceType(myFixture) } diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fir.txt index 520e7634aa13..de3233facac8 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fir.txt @@ -58,7 +58,7 @@ UFile (package = ) [public final class CommentOwnersKt {...] UParameter (name = t) [@org.jetbrains.annotations.NotNull var t: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] : java.lang.Object + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] UIdentifier (Identifier ()) [UIdentifier (Identifier ())] USimpleNameReferenceExpression (identifier = Object, resolvesTo = PsiClass: Object) [Object] UClass (name = NestedClass) [public static final class NestedClass {...}] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/Constructors.types.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/Constructors.types.fir.txt index eb3dfb93459b..c310eb86eec2 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/Constructors.types.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/Constructors.types.fir.txt @@ -10,7 +10,7 @@ UFile (package = ) [public final class A {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i.toString())] : A + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i.toString())] UIdentifier (Identifier (this)) [UIdentifier (Identifier (this))] USimpleNameReferenceExpression (identifier = A, resolvesTo = PsiClass: A) [A] UQualifiedReferenceExpression [i.toString()] : java.lang.String @@ -32,7 +32,7 @@ UFile (package = ) [public final class A {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [AWithInit(i.toString())] : AWithInit + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [AWithInit(i.toString())] UIdentifier (Identifier (this)) [UIdentifier (Identifier (this))] USimpleNameReferenceExpression (identifier = AWithInit, resolvesTo = PsiClass: AWithInit) [AWithInit] UQualifiedReferenceExpression [i.toString()] : java.lang.String @@ -59,7 +59,7 @@ UFile (package = ) [public final class A {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [AWith2Init(i.toString())] : AWith2Init + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [AWith2Init(i.toString())] UIdentifier (Identifier (this)) [UIdentifier (Identifier (this))] USimpleNameReferenceExpression (identifier = AWith2Init, resolvesTo = PsiClass: AWith2Init) [AWith2Init] UQualifiedReferenceExpression [i.toString()] : java.lang.String @@ -88,7 +88,7 @@ UFile (package = ) [public final class A {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] : java.lang.Object + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] UIdentifier (Identifier ()) [UIdentifier (Identifier ())] USimpleNameReferenceExpression (identifier = Object, resolvesTo = PsiClass: Object) [Object] UBinaryExpression (operator = =) [a = i.toString()] : @org.jetbrains.annotations.NotNull() kotlin.Unit @@ -101,7 +101,7 @@ UFile (package = ) [public final class A {...] UParameter (name = s) [@org.jetbrains.annotations.NotNull var s: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] : java.lang.Object + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] UIdentifier (Identifier ()) [UIdentifier (Identifier ())] USimpleNameReferenceExpression (identifier = Object, resolvesTo = PsiClass: Object) [Object] UBinaryExpression (operator = =) [a = s] : @org.jetbrains.annotations.NotNull() kotlin.Unit @@ -118,7 +118,7 @@ UFile (package = ) [public final class A {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] : java.lang.Object + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] UIdentifier (Identifier ()) [UIdentifier (Identifier ())] USimpleNameReferenceExpression (identifier = Object, resolvesTo = PsiClass: Object) [Object] UBlockExpression [{...}] : @org.jetbrains.annotations.NotNull() kotlin.Unit @@ -134,7 +134,7 @@ UFile (package = ) [public final class A {...] UParameter (name = s) [@org.jetbrains.annotations.NotNull var s: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] : java.lang.Object + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [Object()] UIdentifier (Identifier ()) [UIdentifier (Identifier ())] USimpleNameReferenceExpression (identifier = Object, resolvesTo = PsiClass: Object) [Object] UBinaryExpression (operator = =) [a = s] : @org.jetbrains.annotations.NotNull() kotlin.Unit diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/SuperCalls.types.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/SuperCalls.types.fir.txt index 45a4f43f6bdc..d2355c558963 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/SuperCalls.types.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/SuperCalls.types.fir.txt @@ -56,7 +56,7 @@ UFile (package = ) [public final class SuperCallsKt {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i.toString())] : A + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i.toString())] UIdentifier (Identifier (this)) [UIdentifier (Identifier (this))] USimpleNameReferenceExpression (identifier = A, resolvesTo = PsiClass: A) [A] UQualifiedReferenceExpression [i.toString()] : java.lang.String @@ -86,7 +86,7 @@ UFile (package = ) [public final class SuperCallsKt {...] UParameter (name = p) [@org.jetbrains.annotations.NotNull var p: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(p)] : A + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(p)] UIdentifier (Identifier (super)) [UIdentifier (Identifier (super))] USimpleNameReferenceExpression (identifier = A, resolvesTo = PsiClass: A) [A] USimpleNameReferenceExpression (identifier = p) [p] : java.lang.String @@ -94,7 +94,7 @@ UFile (package = ) [public final class SuperCallsKt {...] UParameter (name = i) [@org.jetbrains.annotations.NotNull var i: int] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i)] : A + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [A(i)] UIdentifier (Identifier (super)) [UIdentifier (Identifier (super))] USimpleNameReferenceExpression (identifier = A, resolvesTo = PsiClass: A) [A] USimpleNameReferenceExpression (identifier = i) [i] : int diff --git a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt index 874635116084..dc9db6e41cee 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt @@ -126,6 +126,10 @@ class FE1UastApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), UastApiFi checkExpressionTypeForCallToInternalOperator(myFixture) } + fun testExpressionTypeForConstructorDelegationCall() { + checkExpressionTypeForConstructorDelegationCall(myFixture) + } + fun testFlexibleFunctionalInterfaceType() { checkFlexibleFunctionalInterfaceType(myFixture) }