From a2431f0d85af8bcc1b1919cfa32f04033b5cd434 Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Fri, 3 Feb 2017 17:50:08 +0300 Subject: [PATCH] JS: fixed inlining functions called through inheritor ("fake" override) from another module (#KT-16144) --- .../js/test/semantics/BoxJsTestGenerated.java | 6 ++++ .../kotlin/js/translate/context/Namer.java | 10 ++++--- .../js/translate/utils/JsDescriptorUtils.java | 30 +++++++++++++++++-- .../testData/box/inlineMultiModule/kt16144.kt | 28 +++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 js/js.translator/testData/box/inlineMultiModule/kt16144.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 5eef7b80a43..7061dc06426 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -4565,6 +4565,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("kt16144.kt") + public void testKt16144() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/kt16144.kt"); + doTest(fileName); + } + @TestMetadata("lambda.kt") public void testLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/lambda.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index f7426a424e1..ed99be264fc 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -16,10 +16,6 @@ package org.jetbrains.kotlin.js.translate.context; -import org.jetbrains.kotlin.js.backend.ast.*; -import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; -import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind; -import org.jetbrains.kotlin.js.backend.ast.metadata.TypeCheck; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,10 +25,15 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.idea.KotlinLanguage; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; +import org.jetbrains.kotlin.js.backend.ast.*; +import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; +import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind; +import org.jetbrains.kotlin.js.backend.ast.metadata.TypeCheck; import org.jetbrains.kotlin.js.naming.NameSuggestion; import org.jetbrains.kotlin.js.naming.SuggestedName; import org.jetbrains.kotlin.js.resolve.JsPlatform; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; +import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNameUnsafe; import org.jetbrains.kotlin.name.Name; @@ -113,6 +114,7 @@ public final class Namer { @NotNull public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor) { + functionDescriptor = (CallableDescriptor) JsDescriptorUtils.findRealInlineDeclaration(functionDescriptor); String moduleName = getModuleName(functionDescriptor); FqNameUnsafe fqNameParent = DescriptorUtils.getFqName(functionDescriptor).parent(); String qualifier = null; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java index 1d21a213ea5..2dffc92a900 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java @@ -184,8 +184,34 @@ public final class JsDescriptorUtils { return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); } - private static String getModuleNameFromDescriptorName(DeclarationDescriptor descriptor) { - ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(descriptor); + @NotNull + public static DeclarationDescriptor findRealInlineDeclaration(@NotNull DeclarationDescriptor descriptor) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor d = (FunctionDescriptor) descriptor; + if (d.getKind().isReal() || !d.isInline()) return descriptor; + CallableMemberDescriptor real = findRealDeclaration(d); + assert real != null : "Couldn't find definition of a fake inline descriptor " + descriptor; + return real; + } + return descriptor; + } + + @Nullable + private static FunctionDescriptor findRealDeclaration(FunctionDescriptor descriptor) { + if (descriptor.getModality() == Modality.ABSTRACT) return null; + if (descriptor.getKind().isReal()) return descriptor; + + for (FunctionDescriptor o : descriptor.getOverriddenDescriptors()) { + FunctionDescriptor child = findRealDeclaration(o); + if (child != null) { + return child; + } + } + return null; + } + + private static String getModuleNameFromDescriptorName(@NotNull DeclarationDescriptor descriptor) { + ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(findRealInlineDeclaration(descriptor)); String moduleName = moduleDescriptor.getName().asString(); return moduleName.substring(1, moduleName.length() - 1); } diff --git a/js/js.translator/testData/box/inlineMultiModule/kt16144.kt b/js/js.translator/testData/box/inlineMultiModule/kt16144.kt new file mode 100644 index 00000000000..6accf2a1a88 --- /dev/null +++ b/js/js.translator/testData/box/inlineMultiModule/kt16144.kt @@ -0,0 +1,28 @@ +// MODULE: m3 +// FILE: m3.kt + +interface M3 { + fun foo(): Int +} + +// MODULE: m2 +// FILE: m2.kt + +open class M2 { + inline fun foo() = 1 + inline fun bar() = T::class +} + +// MODULE: m1(m2, m3) +// FILE: m1.kt + +class M1 : M2(), M3 + +// MODULE: main(m1, m2) +// FILE: main.kt + +fun box(): String { + if (M1().foo() != 1) return "fail" + if (M1().bar().simpleName != "M1") return "fail" + return "OK" +} \ No newline at end of file