[KT-4124] Use generated test to avoid duplication of test data of inner classes. Add support of classes contained within objects.
This commit is contained in:
+30
-4
@@ -60,6 +60,8 @@ public class TranslationContext {
|
||||
private final DeclarationDescriptor declarationDescriptor;
|
||||
@Nullable
|
||||
private final ClassDescriptor classDescriptor;
|
||||
@Nullable
|
||||
private final ClassDescriptor objectDescriptor;
|
||||
|
||||
@NotNull
|
||||
public static TranslationContext rootContext(@NotNull StaticContext staticContext, JsFunction rootFunction) {
|
||||
@@ -90,9 +92,16 @@ public class TranslationContext {
|
||||
&& !DescriptorUtils.isAnonymousObject(declarationDescriptor)
|
||||
&& !DescriptorUtils.isObject(declarationDescriptor)) {
|
||||
this.classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.classDescriptor = parent != null ? parent.classDescriptor : null;
|
||||
}
|
||||
if (declarationDescriptor instanceof ClassDescriptor && DescriptorUtils.isObject(declarationDescriptor)) {
|
||||
this.objectDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
}
|
||||
else {
|
||||
this.objectDescriptor = parent != null ? parent.objectDescriptor : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -126,7 +135,7 @@ public class TranslationContext {
|
||||
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, fun.getScope());
|
||||
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, this.definitionPlace,
|
||||
this.declarationDescriptor);
|
||||
descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -341,9 +350,27 @@ public class TranslationContext {
|
||||
if (alias != null) {
|
||||
return alias;
|
||||
}
|
||||
if (DescriptorUtils.isObject(descriptor.getContainingDeclaration())) {
|
||||
if (isConstructorOrDirectScope(descriptor.getContainingDeclaration())) {
|
||||
return JsLiteral.THIS;
|
||||
}
|
||||
else {
|
||||
return getQualifiedReference(descriptor.getContainingDeclaration());
|
||||
}
|
||||
}
|
||||
return getDispatchReceiverPath(getNearestClass(descriptor));
|
||||
}
|
||||
|
||||
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
||||
if (descriptor == declarationDescriptor) {
|
||||
return true;
|
||||
}
|
||||
if (declarationDescriptor instanceof ConstructorDescriptor) {
|
||||
return descriptor == declarationDescriptor.getContainingDeclaration();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression getDispatchReceiverPath(@Nullable ClassDescriptor cls) {
|
||||
if (cls != null) {
|
||||
@@ -396,8 +423,7 @@ public class TranslationContext {
|
||||
private static ClassDescriptor getNearestClass(@Nullable DeclarationDescriptor declaration) {
|
||||
while (declaration != null) {
|
||||
if (declaration instanceof ClassDescriptor) {
|
||||
if (!DescriptorUtils.isAnonymousObject(declaration)
|
||||
&& !DescriptorUtils.isObject(declaration)) {
|
||||
if (!DescriptorUtils.isAnonymousObject(declaration) && !DescriptorUtils.isObject(declaration)) {
|
||||
return (ClassDescriptor) declaration;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-16
@@ -150,20 +150,11 @@ var Kotlin = {};
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(Array|Object|null)=} bases
|
||||
* @param {(function(new: T, ?, ?, ?, ?, ?, ?, ?): T)|null=} constructor
|
||||
* @param {Object=} properties
|
||||
* @param {Object=} staticProperties
|
||||
* @returns {function(new: T): T}
|
||||
* @template T
|
||||
*/
|
||||
Kotlin.createClassNow = function (bases, constructor, properties, staticProperties) {
|
||||
Kotlin.doCreateClass = function (metadata, constructor) {
|
||||
if (constructor == null) {
|
||||
constructor = emptyFunction();
|
||||
}
|
||||
|
||||
var metadata = computeMetadata(bases, properties, staticProperties);
|
||||
metadata.type = Kotlin.TYPE.CLASS;
|
||||
copyProperties(constructor, metadata.staticMembers);
|
||||
|
||||
@@ -189,6 +180,19 @@ var Kotlin = {};
|
||||
return constructor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {(Array|Object|null)=} bases
|
||||
* @param {(function(new: T, ?, ?, ?, ?, ?, ?, ?): T)|null=} constructor
|
||||
* @param {Object=} properties
|
||||
* @param {Object=} staticProperties
|
||||
* @returns {function(new: T): T}
|
||||
* @template T
|
||||
*/
|
||||
Kotlin.createClassNow = function (bases, constructor, properties, staticProperties) {
|
||||
var metadata = computeMetadata(bases, properties, staticProperties);
|
||||
return Kotlin.doCreateClass(metadata, constructor);
|
||||
};
|
||||
|
||||
Kotlin.defineInnerTypes = function(constructor, types) {
|
||||
for (var innerTypeName in types) {
|
||||
if (types.hasOwnProperty(innerTypeName)) {
|
||||
@@ -202,11 +206,20 @@ var Kotlin = {};
|
||||
}
|
||||
};
|
||||
|
||||
Kotlin.createObjectNow = function (bases, constructor, functions) {
|
||||
var noNameClass = Kotlin.createClassNow(bases, constructor, functions);
|
||||
Kotlin.createObjectNow = function (bases, constructor, functions, staticProperties) {
|
||||
var metadata = computeMetadata(bases, functions, staticProperties);
|
||||
var noNameClass = Kotlin.doCreateClass(metadata, constructor);
|
||||
var obj = new noNameClass();
|
||||
noNameClass.$metadata$.type = Kotlin.TYPE.OBJECT;
|
||||
return obj;
|
||||
for (var innerTypeName in metadata.types) {
|
||||
if (metadata.types.hasOwnProperty(innerTypeName)) {
|
||||
Object.defineProperty(obj, innerTypeName, {
|
||||
get : metadata.types[innerTypeName],
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
Kotlin.createTraitNow = function (bases, properties, staticProperties) {
|
||||
@@ -243,7 +256,8 @@ var Kotlin = {};
|
||||
*/
|
||||
Kotlin.createClass = function (basesFun, constructor, properties, staticProperties) {
|
||||
function $o() {
|
||||
var klass = Kotlin.createClassNow(getBases(basesFun), constructor, properties, staticProperties);
|
||||
var metadata = computeMetadata(getBases(basesFun), properties, staticProperties);
|
||||
var klass = Kotlin.doCreateClass(metadata, constructor);
|
||||
Object.defineProperty(this, $o.className, {value: klass});
|
||||
return klass;
|
||||
}
|
||||
@@ -313,11 +327,12 @@ var Kotlin = {};
|
||||
* @param {function()|null} basesFun
|
||||
* @param {(function(new: T): T)|null=} constructor
|
||||
* @param {Object=} functions
|
||||
* @param {Object=} staticProperties
|
||||
* @returns {Object}
|
||||
* @template T
|
||||
*/
|
||||
Kotlin.createObject = function (basesFun, constructor, functions) {
|
||||
return Kotlin.createObjectNow(getBases(basesFun), constructor, functions);
|
||||
Kotlin.createObject = function (basesFun, constructor, functions, staticProperties) {
|
||||
return Kotlin.createObjectNow(getBases(basesFun), constructor, functions, staticProperties);
|
||||
};
|
||||
|
||||
Kotlin.callGetter = function (thisObject, klass, propertyName) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package foo
|
||||
|
||||
open class A(val value: String) {
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
}
|
||||
|
||||
class C : A("fromC") {
|
||||
fun classReceiver() = B("OK")
|
||||
fun superReceiver() = super.B("OK")
|
||||
|
||||
fun newAReceiver() = A("fromA").B("OK")
|
||||
fun aReceiver(): B {
|
||||
val a = A("fromA")
|
||||
return a.B("OK")
|
||||
}
|
||||
|
||||
fun A.extReceiver() = this.B("OK")
|
||||
fun extReceiver() = A("fromA").extReceiver()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "fromC_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.superReceiver().result
|
||||
if (result != "fromC_OK") return "fail 2: $result"
|
||||
|
||||
|
||||
result = receiver.aReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.newAReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.extReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package foo
|
||||
|
||||
open class A(val value: String) {
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
}
|
||||
|
||||
class C : A("fromC") {
|
||||
|
||||
inner class X: A("fromX") {
|
||||
fun classReceiver() = B("OK")
|
||||
fun superReceiver() = super.B("OK")
|
||||
fun superXReceiver() = super@X.B("OK")
|
||||
fun superXCastReceiver() = (this@X as A).B("OK")
|
||||
|
||||
fun superCReceiver() = super@C.B("OK")
|
||||
fun superCCastReceiver() = (this@C as A).B("OK")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C().X()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "fromX_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.superReceiver().result
|
||||
if (result != "fromX_OK") return "fail 2: $result"
|
||||
|
||||
result = receiver.superXReceiver().result
|
||||
if (result != "fromX_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.superXCastReceiver().result
|
||||
if (result != "fromX_OK") return "fail 4: $result"
|
||||
|
||||
|
||||
result = receiver.superCReceiver().result
|
||||
if (result != "fromC_OK") return "fail 5: $result"
|
||||
|
||||
result = receiver.superCCastReceiver().result
|
||||
if (result != "fromC_OK") return "fail 6: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package foo
|
||||
|
||||
class C(val value: String = "C") {
|
||||
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
|
||||
fun classReceiver() = B("OK")
|
||||
|
||||
fun newCReceiver() = C("newC").B("OK")
|
||||
fun cReceiver(): B {
|
||||
val c = C("newC")
|
||||
return c.B("OK")
|
||||
}
|
||||
|
||||
fun C.extReceiver1() = this.B("OK")
|
||||
fun extReceiver() = C("newC").extReceiver1()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "C_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.cReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.newCReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.extReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package foo
|
||||
|
||||
class A {
|
||||
inner class B {
|
||||
val x = foo();
|
||||
}
|
||||
|
||||
class C {
|
||||
val x = foo();
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo(): String {
|
||||
return "foo_result";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = A().B().x
|
||||
if (result != "foo_result") {
|
||||
return "fail1_" + result
|
||||
}
|
||||
result = A.C().x
|
||||
if (result != "foo_result") {
|
||||
return "fail2_" + result
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package foo
|
||||
|
||||
val q = "baz"
|
||||
|
||||
object A {
|
||||
val x = "foo"
|
||||
|
||||
class B {
|
||||
val y = x + "_bar"
|
||||
val z = q + "_bar"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = A.B().y
|
||||
if (result != "foo_bar") {
|
||||
return "failed1_" + result
|
||||
}
|
||||
result = A.B().z
|
||||
if (result != "baz_bar") {
|
||||
return "failed2_" + result
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package foo
|
||||
|
||||
open class A(val s: String) {
|
||||
open inner class B(val s: String) {
|
||||
fun testB() = s + this@A.s
|
||||
}
|
||||
|
||||
open inner class C(): A("C") {
|
||||
fun testC() =
|
||||
B("B_").testB()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val res = A("A").C().testC()
|
||||
return if (res == "B_C") "OK" else res;
|
||||
}
|
||||
Reference in New Issue
Block a user