From 61ce9fe52445ffec9989b25ec60da1920f61466b Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 27 Sep 2022 02:24:54 +0900 Subject: [PATCH] [FE] Fix source element duplication in object literal expressions --- .../kotlin/analysis/api/fir/utils/firUtils.kt | 1 - .../fir/element/builder/FirElementBuilder.kt | 1 - .../declarations/objectLiteral.kt | 5 ++ .../declarations/objectLiteral.txt | 11 +++++ .../declarations/objectLiteralExpression.kt | 5 ++ .../declarations/objectLiteralExpression.txt | 11 +++++ .../api/fir/GetOrBuildFirTestGenerated.java | 12 +++++ .../FirThrowableSubclassChecker.kt | 13 +++-- .../converter/DeclarationsConverter.kt | 5 +- .../kotlin/fir/builder/RawFirBuilder.kt | 7 ++- .../LightTreePositioningStrategies.kt | 6 ++- .../tests/inline/defaultLambdaInlining.fir.kt | 47 ------------------- .../tests/inline/defaultLambdaInlining.kt | 1 + .../thisInPropertyInitializer.fir.kt | 2 +- 14 files changed, 63 insertions(+), 64 deletions(-) create mode 100644 analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.kt create mode 100644 analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.txt create mode 100644 analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.kt create mode 100644 analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.txt delete mode 100644 compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/firUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/firUtils.kt index 8a0a03743d6..d985d3ef276 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/firUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/firUtils.kt @@ -45,7 +45,6 @@ internal fun KtExpression.unwrap(): KtExpression { return when (this) { is KtLabeledExpression -> baseExpression?.unwrap() is KtAnnotatedExpression -> baseExpression?.unwrap() - is KtObjectLiteralExpression -> objectDeclaration is KtFunctionLiteral -> (parent as? KtLambdaExpression)?.unwrap() else -> this } ?: this diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt index 0c0f54ef21b..1eb83488185 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt @@ -44,7 +44,6 @@ internal class FirElementBuilder( // null will be return in case of invalid KtValueArgument deparenthesized.getArgumentExpression() } - deparenthesized is KtObjectLiteralExpression -> deparenthesized.objectDeclaration deparenthesized is KtStringTemplateEntryWithExpression -> deparenthesized.expression deparenthesized is KtUserType && deparenthesized.parent is KtNullableType -> deparenthesized.parent as KtNullableType else -> deparenthesized diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.kt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.kt new file mode 100644 index 00000000000..06fee355789 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.kt @@ -0,0 +1,5 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtObjectDeclaration + +fun test() { + object {} +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.txt new file mode 100644 index 00000000000..06a17cc3c7d --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.txt @@ -0,0 +1,11 @@ +KT element: KtObjectDeclaration +FIR element: FirAnonymousObjectImpl +FIR source kind: KtRealSourceElementKind + +FIR element rendered: +object : R|kotlin/Any| { + private constructor(): R|| { + super() + } + +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.kt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.kt new file mode 100644 index 00000000000..d275778ad11 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.kt @@ -0,0 +1,5 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtObjectLiteralExpression + +fun test() { + object {} +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.txt new file mode 100644 index 00000000000..623975b3977 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.txt @@ -0,0 +1,11 @@ +KT element: KtObjectLiteralExpression +FIR element: FirAnonymousObjectExpressionImpl +FIR source kind: KtRealSourceElementKind + +FIR element rendered: +object : R|kotlin/Any| { + private constructor(): R|| { + super() + } + +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java index 95c30dfc9e0..d5913b95425 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java @@ -215,6 +215,18 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("objectLiteral.kt") + public void testObjectLiteral() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteral.kt"); + } + + @Test + @TestMetadata("objectLiteralExpression.kt") + public void testObjectLiteralExpression() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/objectLiteralExpression.kt"); + } + @Test @TestMetadata("propertyDelegate.kt") public void testPropertyDelegate() throws Exception { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirThrowableSubclassChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirThrowableSubclassChecker.kt index fe161b69225..b56d0a8c0b4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirThrowableSubclassChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirThrowableSubclassChecker.kt @@ -25,12 +25,15 @@ object FirThrowableSubclassChecker : FirClassChecker() { if (declaration.typeParameters.isNotEmpty()) { reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.GENERIC_THROWABLE_SUBCLASS, context) - val source = when { - (declaration as? FirRegularClass)?.let { it.isInner || it.isLocal } == true -> declaration.source - declaration is FirAnonymousObject -> (declaration.declarations.firstOrNull())?.source - else -> null + val shouldReport = when (declaration) { + is FirRegularClass -> declaration.isInner || declaration.isLocal + is FirAnonymousObject -> true + else -> false + } + + if (shouldReport) { + reporter.reportOn(declaration.source, FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS, context) } - reporter.reportOn(source, FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS, context) } else if (declaration.hasGenericOuterDeclaration(context)) { reporter.reportOn(declaration.source, FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS, context) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 21397724726..67a8533e0a3 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -634,10 +634,9 @@ class DeclarationsConverter( return withChildClassName(SpecialNames.ANONYMOUS, isExpect = false) { var delegatedFieldsMap: Map? = null buildAnonymousObjectExpression { - val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first() - val sourceElement = objectDeclaration.toFirSourceElement() - source = sourceElement + source = objectLiteral.toFirSourceElement() anonymousObject = buildAnonymousObject { + val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first() source = objectDeclaration.toFirSourceElement() origin = FirDeclarationOrigin.Source moduleData = baseModuleData diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 0308be4a745..fb7578d94f4 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1226,14 +1226,13 @@ open class RawFirBuilder( } override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Unit): FirElement { - val objectDeclaration = expression.objectDeclaration return withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) { var delegatedFieldsMap: Map? buildAnonymousObjectExpression { - val sourceElement = objectDeclaration.toFirSourceElement() - source = sourceElement + source = expression.toFirSourceElement() anonymousObject = buildAnonymousObject { - source = sourceElement + val objectDeclaration = expression.objectDeclaration + source = objectDeclaration.toFirSourceElement() moduleData = baseModuleData origin = FirDeclarationOrigin.Source classKind = ClassKind.OBJECT diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt index f27d2fe0145..bc66662b1db 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt @@ -35,8 +35,10 @@ object LightTreePositioningStrategies { ): List { when (node.tokenType) { KtNodeTypes.OBJECT_LITERAL -> { - val objectKeyword = tree.findDescendantByType(node, KtTokens.OBJECT_KEYWORD)!! - return markElement(objectKeyword, startOffset, endOffset, tree, node) + val objectDeclaration = tree.findDescendantByType(node, KtNodeTypes.OBJECT_DECLARATION)!! + val objectKeyword = tree.objectKeyword(objectDeclaration)!! + val supertypeList = tree.supertypesList(objectDeclaration) + return markRange(objectKeyword, supertypeList ?: objectKeyword, startOffset, endOffset, tree, node) } KtNodeTypes.OBJECT_DECLARATION -> { val objectKeyword = tree.objectKeyword(node)!! diff --git a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt deleted file mode 100644 index 94a771094b0..00000000000 --- a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt +++ /dev/null @@ -1,47 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -// !LANGUAGE: +InlineDefaultFunctionalParameters - -fun test() = "OK" - -val prop = "OK" - -class Foo { - fun test() = "OK" - val prop = "OK" -} - -object FooObject { - fun test() = "OK" - val prop = "OK" -} - -inline fun default1(s : () -> String = {"OK"}) {} -inline fun default2(s : () -> String = ::test) {} -inline fun default3(s : () -> String = ::prop) {} -inline fun default4(s : () -> String = FooObject::test) {} -inline fun default5(s : () -> String = FooObject::prop) {} -inline fun default6(s : (a: Foo) -> String = Foo::test) {} -inline fun default7(s : (a: Foo) -> String = Foo::prop) {} - -val a = Foo() - -inline fun default8(s : () -> String = a::test) {} -inline fun default9(s : () -> String = a::prop) {} - -inline fun default10(s : () -> String = object : Function0 { - override fun invoke(): String { - return "FAIL" - } -}) {} - -abstract class Base { - abstract fun foo(f: () -> Unit = { }) -} - -class Derived : Base() { - override final inline fun foo(f: () -> Unit) { - f() - } -} - -inline fun default11(s : () -> Derived = ::Derived) {} diff --git a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.kt b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.kt index c3661e10d3d..d30a1b86588 100644 --- a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.kt +++ b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE // !LANGUAGE: +InlineDefaultFunctionalParameters diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/thisInPropertyInitializer.fir.kt b/compiler/testData/diagnostics/tests/thisAndSuper/thisInPropertyInitializer.fir.kt index 03fb1ff92c5..c19ef867696 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/thisInPropertyInitializer.fir.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/thisInPropertyInitializer.fir.kt @@ -1,7 +1,7 @@ interface Base { fun foo() } -val String.test: Base = object: Base { +val String.test: Base = object: Base { override fun foo() { this@test }