JS backend: consider functions which renamed by annotations in simple mangling.
This commit is contained in:
@@ -339,12 +339,13 @@ public class BindingContextUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Set<FunctionDescriptor> getAllOverriddenDeclarations(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
Set<FunctionDescriptor> result = Sets.newHashSet();
|
||||
for (FunctionDescriptor overriddenDeclaration : functionDescriptor.getOverriddenDescriptors()) {
|
||||
public static <T extends CallableMemberDescriptor> Set<T> getAllOverriddenDeclarations(@NotNull T memberDescriptor) {
|
||||
Set<T> result = Sets.newHashSet();
|
||||
for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) {
|
||||
CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
|
||||
if (kind == DECLARATION) {
|
||||
result.add(overriddenDeclaration);
|
||||
//noinspection unchecked
|
||||
result.add((T) overriddenDeclaration);
|
||||
}
|
||||
else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
|
||||
//do nothing
|
||||
@@ -352,7 +353,8 @@ public class BindingContextUtils {
|
||||
else {
|
||||
throw new AssertionError("Unexpected callable kind " + kind);
|
||||
}
|
||||
result.addAll(getAllOverriddenDeclarations(overriddenDeclaration));
|
||||
//noinspection unchecked
|
||||
result.addAll(getAllOverriddenDeclarations((T) overriddenDeclaration));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject;
|
||||
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.getNameForAnnotatedObjectWithOverrides;
|
||||
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.isLibraryObject;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMangledName;
|
||||
@@ -263,7 +263,7 @@ public final class StaticContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
String nameFromAnnotation = getNameForAnnotatedObject(propertyDescriptor);
|
||||
String nameFromAnnotation = getNameForAnnotatedObjectWithOverrides(propertyDescriptor);
|
||||
if (nameFromAnnotation != null) {
|
||||
return declarePropertyOrPropertyAccessorName(descriptor, nameFromAnnotation, false);
|
||||
}
|
||||
@@ -297,7 +297,7 @@ public final class StaticContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
String name = getNameForAnnotatedObject(descriptor);
|
||||
String name = getNameForAnnotatedObjectWithOverrides(descriptor);
|
||||
if (name != null) return getEnclosingScope(descriptor).declareName(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,20 @@
|
||||
|
||||
package org.jetbrains.k2js.translate.utils;
|
||||
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContainingClass;
|
||||
|
||||
public final class AnnotationsUtils {
|
||||
@@ -65,15 +71,30 @@ public final class AnnotationsUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getNameForAnnotatedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) {
|
||||
if (!hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) {
|
||||
continue;
|
||||
}
|
||||
String name = getNameForAnnotatedObject(descriptor, annotation);
|
||||
return name != null ? name : descriptor.getName().asString();
|
||||
public static String getNameForAnnotatedObjectWithOverrides(@NotNull DeclarationDescriptor declarationDescriptor) {
|
||||
Set<DeclarationDescriptor> descriptors;
|
||||
|
||||
if (declarationDescriptor instanceof CallableMemberDescriptor &&
|
||||
((CallableMemberDescriptor) declarationDescriptor).getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
|
||||
Set<CallableMemberDescriptor> overriddenDeclarations =
|
||||
BindingContextUtils.getAllOverriddenDeclarations((CallableMemberDescriptor) declarationDescriptor);
|
||||
//noinspection unchecked
|
||||
descriptors = ContainerUtil.<CallableMemberDescriptor, DeclarationDescriptor>map2Set(overriddenDeclarations, Function.ID);
|
||||
}
|
||||
else {
|
||||
descriptors = ContainerUtil.newHashSet(declarationDescriptor);
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) {
|
||||
if (!hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) {
|
||||
continue;
|
||||
}
|
||||
String name = getNameForAnnotatedObject(descriptor, annotation);
|
||||
return name != null ? name : descriptor.getName().asString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.k2js.translate.utils;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
@@ -26,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
|
||||
@@ -179,7 +179,7 @@ public final class TranslationUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getSimpleMangledName(@NotNull FunctionDescriptor descriptor) {
|
||||
private static String getSimpleMangledName(@NotNull final FunctionDescriptor descriptor) {
|
||||
DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
|
||||
|
||||
JetScope jetScope = null;
|
||||
@@ -193,11 +193,24 @@ public final class TranslationUtils {
|
||||
int counter = 0;
|
||||
|
||||
if (jetScope != null) {
|
||||
Collection<FunctionDescriptor> functions = jetScope.getFunctions(descriptor.getName());
|
||||
List<FunctionDescriptor> overloadedFunctions = ContainerUtil.filter(functions, new Condition<FunctionDescriptor>() {
|
||||
Collection<DeclarationDescriptor> declarations = jetScope.getAllDescriptors();
|
||||
List<FunctionDescriptor> overloadedFunctions = ContainerUtil.mapNotNull(declarations, new Function<DeclarationDescriptor, FunctionDescriptor>() {
|
||||
@Override
|
||||
public boolean value(FunctionDescriptor descriptor) {
|
||||
return !needsStableMangling(descriptor) && !AnnotationsUtils.isNativeObject(descriptor);
|
||||
public FunctionDescriptor fun(DeclarationDescriptor declarationDescriptor) {
|
||||
if (!(declarationDescriptor instanceof FunctionDescriptor)) return null;
|
||||
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||
|
||||
String name = AnnotationsUtils.getNameForAnnotatedObjectWithOverrides(functionDescriptor);
|
||||
|
||||
if (name == null) {
|
||||
// when name == null it's mean that it's not native
|
||||
if (needsStableMangling(functionDescriptor)) return null;
|
||||
|
||||
name = declarationDescriptor.getName().asString();
|
||||
}
|
||||
|
||||
return descriptor.getName().asString().equals(name) ? functionDescriptor : null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -369,6 +382,14 @@ public final class TranslationUtils {
|
||||
private static class OverloadedFunctionComparator implements Comparator<FunctionDescriptor> {
|
||||
@Override
|
||||
public int compare(@NotNull FunctionDescriptor a, @NotNull FunctionDescriptor b) {
|
||||
// native functions first
|
||||
if (isNativeOrOverrideNative(a)) {
|
||||
if (!isNativeOrOverrideNative(b)) return -1;
|
||||
}
|
||||
else if (isNativeOrOverrideNative(b)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// be visibility
|
||||
// Actually "internal" > "private", but we want to have less number for "internal", so compare b with a instead of a with b.
|
||||
Integer result = Visibilities.compare(b.getVisibility(), a.getVisibility());
|
||||
@@ -390,5 +411,13 @@ public final class TranslationUtils {
|
||||
private static int arity(FunctionDescriptor descriptor) {
|
||||
return descriptor.getValueParameters().size() + (descriptor.getReceiverParameter() == null ? 0 : 1);
|
||||
}
|
||||
|
||||
private static boolean isNativeOrOverrideNative(FunctionDescriptor descriptor) {
|
||||
Set<FunctionDescriptor> declarations = BindingContextUtils.getAllOverriddenDeclarations(descriptor);
|
||||
for (FunctionDescriptor memberDescriptor : declarations) {
|
||||
if (AnnotationsUtils.isNativeObject(memberDescriptor)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ fun internal_foo(i: Int): Int = 2
|
||||
fun internal_boo(i: Int): Int = 2
|
||||
fun internal_boo(s: String): Int = 3
|
||||
fun internal_boo(): Int = 1
|
||||
native fun internal_boo(a: Array<Int>) = "should be ingnored"
|
||||
|
||||
val internal_f = { internal_foo() + internal_foo(1) }
|
||||
val internal_b = { internal_boo() + internal_boo(1) }
|
||||
@@ -19,6 +20,7 @@ public fun public_foo(i: Int): Int = 2
|
||||
public fun public_boo(i: Int): Int = 2
|
||||
public fun public_boo(s: String): Int = 3
|
||||
public fun public_boo(): Int = 1
|
||||
native public fun public_boo(a: Array<Int>): String = "should be ingnored"
|
||||
|
||||
val public_f = { public_foo() + public_foo(1) }
|
||||
val public_b = { public_boo() + public_boo(1) }
|
||||
@@ -28,6 +30,7 @@ native private fun private_foo(a: Array<Int>): String = "should be ingnored"
|
||||
private fun private_foo(): Int = 1
|
||||
private fun private_foo(i: Int): Int = 2
|
||||
|
||||
native private fun private_boo(a: Array<Int>): String = "should be ingnored"
|
||||
private fun private_boo(i: Int): Int = 2
|
||||
private fun private_boo(s: String): Int = 3
|
||||
private fun private_boo(): Int = 1
|
||||
@@ -44,6 +47,7 @@ fun mixed_foo(i: Int): Int = 2
|
||||
|
||||
fun mixed_boo(i: Int): Int = 2
|
||||
private fun mixed_boo(s: String, i: Int): Int = 4
|
||||
native fun mixed_boo(a: Array<Int>) = "should be ingnored"
|
||||
public fun mixed_boo(s: String): Int = 3
|
||||
fun mixed_boo(): Int = 1
|
||||
|
||||
|
||||
@@ -1,19 +1,49 @@
|
||||
package foo
|
||||
|
||||
native
|
||||
open class A(b: Int) {
|
||||
open class A(val a: Int) {
|
||||
fun g(): Int = noImpl
|
||||
fun m(): Int = noImpl
|
||||
|
||||
public open fun foo(i: Int): String = noImpl
|
||||
public fun boo(i: Int): String = noImpl
|
||||
native("bar")
|
||||
open fun baz(i: Int): String = noImpl
|
||||
}
|
||||
|
||||
class B(val b: Int) : A(b / 2)
|
||||
class B(val b: Int) : A(b / 2) {
|
||||
override fun foo(i: Int): String = "B.foo($i: Int)"
|
||||
|
||||
fun boo(): String = "B.boo()"
|
||||
fun boo(i: String): String = "B.boo($i: String)"
|
||||
|
||||
fun bar(i: String): String = "B.bar($i: String)"
|
||||
override fun baz(i: Int): String = "B.baz($i: Int)"
|
||||
fun bar(): String = "B.bar()"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
val b = B(10)
|
||||
|
||||
if (b !is A) return "b !is A"
|
||||
if (b.g() != 10) return "b.g() != 10, it: ${b.g()}"
|
||||
if (b.m() != 4) return "b.m() != 4, it: ${b.m()}"
|
||||
|
||||
if (b.foo(4) != "B.foo(4: Int)") return "b.foo(4) != \"B.foo(4: Int)\", it: ${b.foo(4)}"
|
||||
|
||||
if (b.boo(434) != "A.boo(434)") return "b.boo(434) != \"A.boo(434)\", it: ${b.boo(434)}"
|
||||
if (b.boo() != "B.boo()") return "b.boo() != \"B.boo()\", it: ${b.boo()}"
|
||||
if (b.boo("qlfj") != "B.boo(qlfj: String)") return "b.boo(\"qlfj\") != \"B.boo(qlfj: String)\", it: ${b.boo("qlfj")}"
|
||||
|
||||
if (b.bar("apl") != "B.bar(apl: String)") return "b.bar(\"apl\") != \"B.bar(apl: String)\", it: ${b.bar("apl")}"
|
||||
if (b.baz(34) != "B.baz(34: Int)") return "b.baz(34) != \"B.baz(34: Int)\", it: ${b.baz(34)}"
|
||||
if (b.bar() != "B.bar()") return "b.bar() != \"B.bar()\", it: ${b.bar()}"
|
||||
|
||||
val a: A = b
|
||||
|
||||
if (a.foo(4) != "B.foo(4: Int)") return "a.foo(4) != \"B.foo(4: Int)\", it: ${a.foo(4)}"
|
||||
if (a.boo(434) != "A.boo(434)") return "a.boo(434) != \"A.boo(434)\", it: ${a.boo(434)}"
|
||||
if (a.baz(34) != "B.baz(34: Int)") return "a.baz(34) != \"B.baz(34: Int)\", it: ${a.baz(34)}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,8 +1,23 @@
|
||||
function A(b) {
|
||||
this.g = function() {
|
||||
return 2 * b;
|
||||
};
|
||||
this.m = function() {
|
||||
return b - 1;
|
||||
}
|
||||
function A(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
A.prototype.g = function() {
|
||||
return 2 * this.a;
|
||||
};
|
||||
|
||||
A.prototype.m = function() {
|
||||
return this.a - 1;
|
||||
};
|
||||
|
||||
A.prototype.foo = function(i) {
|
||||
return "A.foo(" + i + ")";
|
||||
};
|
||||
|
||||
A.prototype.boo = function(i) {
|
||||
return "A.boo(" + i + ")";
|
||||
};
|
||||
|
||||
A.prototype.bar = function(i) {
|
||||
return "A.bar(" + i + ")";
|
||||
}
|
||||
Reference in New Issue
Block a user