JS backend: fixed accessing to nested native "elements".

#KT-4298 fixed
This commit is contained in:
Zalim Bashorov
2014-08-07 22:48:20 +04:00
parent 50a59982aa
commit ac4ffd7d2c
6 changed files with 311 additions and 22 deletions
@@ -116,4 +116,8 @@ public final class NativeInteropTest extends SingleFileTranslationTest {
public void testPassTopLevelFunctionFromNative() throws Exception {
checkFooBoxIsOk();
}
public void testNestedElements() throws Exception {
checkFooBoxIsOk();
}
}
@@ -170,13 +170,10 @@ object ConstructorCallCase : FunctionCallCase {
}
override fun FunctionCallInfo.noReceivers(): JsExpression {
if (isNative()) {
return JsNew(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
}
val fqName = context.getQualifiedReference(callableDescriptor)
val functionRef = if (isNative()) fqName else context.aliasOrValue(callableDescriptor) { fqName }
val functionRef = context.aliasOrValue(callableDescriptor) {
context.getQualifiedReference(it)
}
return JsNew(functionRef, argumentsInfo.getTranslateArguments())
}
}
@@ -209,4 +206,4 @@ fun FunctionCallInfo.translateFunctionCall(): JsExpression {
else ->
DefaultFunctionCallCase.translate(this)
}
}
}
@@ -32,14 +32,12 @@ import org.jetbrains.k2js.config.LibrarySourcesConfig;
import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
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.AnnotationsUtils.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMangledName;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getSuggestedName;
@@ -436,6 +434,8 @@ public final class StaticContext {
Rule<JsNameRef> packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (isNativeObject(descriptor)) return null;
DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
if (!(containingDescriptor instanceof PackageFragmentDescriptor)) {
return null;
@@ -489,10 +489,25 @@ public final class StaticContext {
return null;
}
};
Rule<JsNameRef> nativeObjectsHaveNativePartOfFullQualifier = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ConstructorDescriptor || !isNativeObject(descriptor)) return null;
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration != null && isNativeObject(containingDeclaration)) {
return getQualifiedReference(containingDeclaration);
}
return null;
}
};
addRule(libraryObjectsHaveKotlinQualifier);
addRule(constructorHaveTheSameQualifierAsTheClass);
addRule(standardObjectsHaveKotlinQualifier);
addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier);
addRule(nativeObjectsHaveNativePartOfFullQualifier);
}
}
@@ -508,18 +523,7 @@ public final class StaticContext {
return null;
}
};
//TODO: hack! it seems like needed, only for Inheritance from native class
Rule<Boolean> nativeObjectsHaveNoQualifiers = new Rule<Boolean>() {
@Override
public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
if (!AnnotationsUtils.isNativeObject(descriptor)) {
return null;
}
return true;
}
};
addRule(propertiesInClassHaveNoQualifiers);
addRule(nativeObjectsHaveNoQualifiers);
}
}
}
@@ -143,6 +143,6 @@ public final class AnnotationsUtils {
return true;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
return containingClass != null && getAnnotationByName(containingClass, fqn) != null;
return containingClass != null && hasAnnotationOrInsideAnnotatedClass(containingClass, fqn);
}
}
@@ -0,0 +1,218 @@
package foo
fun box(): String {
// in object
assertEquals("Object.Object.a", Object.Object.a)
assertEquals("Object.Object.b", Object.Object.b)
assertEquals(123, Object.Object.test())
assertEquals("Object.Object.Class().a", Object.Object.Class("Object.Object.Class().a").a)
assertEquals("Object.Object.Class().b", Object.Object.Class("something").b)
assertEquals(42, Object.Object.Class("something").test())
assertEquals("Object.Object.Class.a", Object.Object.Class.a)
assertEquals("Object.Object.Class.b", Object.Object.Class.b)
assertEquals(142, Object.Object.Class.test())
assertEquals("Object.Class().a", Object.Class("Object.Class().a").a)
assertEquals("Object.Class().b", Object.Class("something").b)
assertEquals(42, Object.Class("something").test())
assertEquals("Object.Class.a", Object.Class.a)
assertEquals("Object.Class.b", Object.Class.b)
assertEquals(142, Object.Class.test())
assertEquals("Object.Trait.a", Object.Trait.a)
assertEquals("Object.Trait.b", Object.Trait.b)
assertEquals(324, Object.Trait.test())
assertEquals("Object.a.a", Object.a.a)
assertEquals("Object.a.b", Object.a.b)
assertEquals(34, Object.a.test())
assertEquals("Object.b", Object.b)
assertEquals(23, Object.test())
// in class
assertEquals("Class.Object.a", Class.Object.a)
assertEquals("Class.Object.b", Class.Object.b)
assertEquals(55, Class.Object.test())
assertEquals("Class.Class().a", Class.Class("Class.Class().a").a)
assertEquals("Class.Class().b", Class.Class("something").b)
assertEquals(66, Class.Class("something").test())
assertEquals("Class.Class.a", Class.Class.a)
assertEquals("Class.Class.b", Class.Class.b)
assertEquals(88, Class.Class.test())
//TODO inner class
// assertEquals("Class.InnerClass().a", Class().InnerClass("Class.InnerClass().a").a)
// assertEquals("Class.InnerClass().b", Class().InnerClass("something").b)
// assertEquals(66, Class().InnerClass("something").test())
assertEquals("Class.Trait.a", Class.Trait.a)
assertEquals("Class.Trait.b", Class.Trait.b)
assertEquals(55, Class.Trait.test())
assertEquals("Class.a.a", Class.a.a)
assertEquals("Class.a.b", Class.a.b)
assertEquals(22, Class.a.test())
assertEquals("Class.b", Class.b)
assertEquals(77, Class.test())
// in trit
assertEquals("Trait.Object.a", Trait.Object.a)
assertEquals("Trait.Object.b", Trait.Object.b)
assertEquals(90, Trait.Object.test())
assertEquals("Trait.Class().a", Trait.Class("Trait.Class().a").a)
assertEquals("Trait.Class().b", Trait.Class("something").b)
assertEquals(66, Trait.Class("something").test())
assertEquals("Trait.Class.a", Trait.Class.a)
assertEquals("Trait.Class.b", Trait.Class.b)
assertEquals(88, Trait.Class.test())
assertEquals("Trait.Trait.a", Trait.Trait.a)
assertEquals("Trait.Trait.b", Trait.Trait.b)
assertEquals(55, Trait.Trait.test())
assertEquals("Trait.a.a", Trait.a.a)
assertEquals("Trait.a.b", Trait.a.b)
assertEquals(22, Trait.a.test())
assertEquals("Trait.b", Trait.b)
assertEquals(277, Trait.test())
return "OK";
}
native
object Object {
object Object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
native("AnotherClass")
class Class(val a: String) {
var b: String = noImpl
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
}
class Class(val a: String) {
var b: String = noImpl
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
trait Trait {
val a: String
var b: String
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
val a: Trait = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
native("SomeClass")
class Class {
object Object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
class Class(val a: String) {
var b: String = noImpl
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
inner class InnerClass(val a: String) {
var b: String = noImpl
fun test(): Int = noImpl
}
trait Trait {
val a: String
var b: String
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
class object {
native("aaa")
val a: Trait = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
native
trait Trait {
native("SomeObject")
object Object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
class Class(val a: String) {
var b: String = noImpl
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
native("SomeTrait")
trait Trait {
val a: String
var b: String
fun test(): Int = noImpl
class object {
val a: String = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
class object {
val a: Trait = noImpl
var b: String = noImpl
fun test(): Int = noImpl
}
}
@@ -0,0 +1,66 @@
var Object = createTestObject("Object", 23);
extend(Object, {
Object: extend(createTestObject("Object.Object", 123), { AnotherClass : createTestClass("Object.Object.Class", 42, 142) }),
Class: createTestClass("Object.Class", 42, 142),
Trait : createTestObject("Object.Trait", 324),
a: createTestObject("Object.a", 34)
});
var SomeClass = function () {};
extend(SomeClass, createTestObject("Class", 77));
extend(SomeClass, {
Object: createTestObject("Class.Object", 55),
Class: createTestClass("Class.Class", 66, 88),
InnerClass: createTestInnerClass("Class.InnerClass", 57),
Trait: createTestObject("Class.Trait", 55),
aaa: createTestObject("Class.a", 22)
});
var Trait = createTestObject("Trait", 277);
extend(Trait, {
SomeObject: createTestObject("Trait.Object", 90),
Class: createTestClass("Trait.Class", 66, 88),
SomeTrait: createTestObject("Trait.Trait", 55),
a: createTestObject("Trait.a", 22)
});
// Helpers
function extend(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
}
function createTestClass(fqName, memberFunResult, staticFunResult) {
function Class(a) {
this.a = a;
this.b = fqName + "().b"
}
Class.prototype.test = function () { return memberFunResult };
extend(Class, createTestObject(fqName, staticFunResult));
return Class;
}
function createTestInnerClass(fqName, memberFunResult) {
function Class(parent, a) {
this.a = a;
this.b = fqName + "().b"
}
Class.prototype.test = function () { return memberFunResult };
}
function createTestObject(fqName, funResult) {
return {
a: fqName + ".a",
b: fqName + ".b",
test: function () { return funResult }
}
}