From 5848cce95e1df6e82a0634bbc8466edcfe69dea1 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Mon, 11 Oct 2021 17:09:27 +0300 Subject: [PATCH] KTIJ-2448 Correctly filter synthetic declarations in `buildDecompiledText` We used to render any callable declaration that's either a directly-declared one, or which name starts with `component*`. It works incorrectly when there are delegated or fake overridden callables named `component*` coming from base classes or interfaces. This makes `buildDecompiledText` render only synthesised `component*` functions (which should come only from the data-classes). ^KTIJ-2448 Fixed GitOrigin-RevId: 5f4b0625eaf95424f268b776f5cfd8a2b6820338 --- .../textBuilder/buildDecompiledText.kt | 20 ++++++++++++++----- ...mpiledTextFromJsMetadataTestGenerated.java | 5 +++++ .../CommonDecompiledTextTestGenerated.java | 5 +++++ ...ithDelegatedComponentFunctions.expected.kt | 7 +++++++ .../ClassWithDelegatedComponentFunction.kt | 5 +++++ .../Dependency.kt | 8 ++++++++ 6 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions.expected.kt create mode 100644 plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/ClassWithDelegatedComponentFunction.kt create mode 100644 plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/Dependency.kt diff --git a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/buildDecompiledText.kt b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/buildDecompiledText.kt index 9faf60705935..45031ab6456a 100644 --- a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/buildDecompiledText.kt +++ b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/buildDecompiledText.kt @@ -54,6 +54,20 @@ fun buildDecompiledText( textIndex.addToIndex(descriptor, TextRange(startOffset, endOffset)) } + fun CallableMemberDescriptor.isConsideredSynthetic(): Boolean { + return when (kind) { + CallableMemberDescriptor.Kind.DECLARATION -> false + + CallableMemberDescriptor.Kind.FAKE_OVERRIDE, + CallableMemberDescriptor.Kind.DELEGATION -> true + + CallableMemberDescriptor.Kind.SYNTHESIZED -> { + // Of all synthesized functions, only `component*` functions are rendered (for historical reasons) + !DataClassDescriptorResolver.isComponentLike(name) + } + } + } + fun appendDescriptor(descriptor: DeclarationDescriptor, indent: String, lastEnumEntry: Boolean? = null) { val startOffset = builder.length if (isEnumEntry(descriptor)) { @@ -128,11 +142,7 @@ fun buildDecompiledText( if (member == companionObject) { continue } - if (member is CallableMemberDescriptor - && member.kind != CallableMemberDescriptor.Kind.DECLARATION - //TODO: not synthesized and component like - && !DataClassDescriptorResolver.isComponentLike(member.name) - ) { + if (member is CallableMemberDescriptor && member.isConsideredSynthetic()) { continue } newlineExceptFirst() diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextFromJsMetadataTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextFromJsMetadataTestGenerated.java index 202a2870fdd8..94005c864c16 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextFromJsMetadataTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextFromJsMetadataTestGenerated.java @@ -54,6 +54,11 @@ public class CommonDecompiledTextFromJsMetadataTestGenerated extends AbstractCom runTest("testData/decompiler/decompiledText/ClassWithClassObject/"); } + @TestMetadata("ClassWithDelegatedComponentFunctions") + public void testClassWithDelegatedComponentFunctions() throws Exception { + runTest("testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/"); + } + @TestMetadata("ClassWithNamedClassObject") public void testClassWithNamedClassObject() throws Exception { runTest("testData/decompiler/decompiledText/ClassWithNamedClassObject/"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextTestGenerated.java index fffeb8e31dbc..4e37852ac385 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/decompiler/textBuilder/CommonDecompiledTextTestGenerated.java @@ -53,6 +53,11 @@ public class CommonDecompiledTextTestGenerated extends AbstractCommonDecompiledT runTest("testData/decompiler/decompiledText/ClassWithClassObject/"); } + @TestMetadata("ClassWithDelegatedComponentFunctions") + public void testClassWithDelegatedComponentFunctions() throws Exception { + runTest("testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/"); + } + @TestMetadata("ClassWithNamedClassObject") public void testClassWithNamedClassObject() throws Exception { runTest("testData/decompiler/decompiledText/ClassWithNamedClassObject/"); diff --git a/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions.expected.kt b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions.expected.kt new file mode 100644 index 000000000000..7b3382a9c712 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions.expected.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package test + +public final class ClassWithDelegatedComponentFunctions public constructor(delegate: dependency.ComponentInterface) : dependency.ComponentInterface { +} diff --git a/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/ClassWithDelegatedComponentFunction.kt b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/ClassWithDelegatedComponentFunction.kt new file mode 100644 index 000000000000..ff4965094f82 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/ClassWithDelegatedComponentFunction.kt @@ -0,0 +1,5 @@ +package test + +import dependency.ComponentInterface + +class ClassWithDelegatedComponentFunctions(delegate: ComponentInterface): ComponentInterface by delegate \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/Dependency.kt b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/Dependency.kt new file mode 100644 index 000000000000..d2dec9c264c6 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/decompiler/decompiledText/ClassWithDelegatedComponentFunctions/Dependency.kt @@ -0,0 +1,8 @@ +package dependency + +interface ComponentInterface { + operator fun component1(): Int + fun component2(): Int + + val component3: Int +} \ No newline at end of file