JS: fixed inlining functions called through inheritor ("fake" override) from another module (#KT-16144)

This commit is contained in:
Anton Bannykh
2017-02-03 17:50:08 +03:00
parent 0709561869
commit a2431f0d85
4 changed files with 68 additions and 6 deletions
@@ -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");
@@ -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;
@@ -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);
}
@@ -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 <reified T : Any> 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<M1>().simpleName != "M1") return "fail"
return "OK"
}