[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:
Alexey Andreev
2016-02-09 19:55:46 +03:00
parent 133b84160e
commit c48c6bc055
12 changed files with 194 additions and 169 deletions
@@ -1063,6 +1063,9 @@ fun main(args: Array<String>) {
model("codegen/box/secondaryConstructors", targetBackend = TargetBackend.JS)
}
testClass<AbstractNestedTypesTest>() {
model("codegen/box/classes/inner", targetBackend = TargetBackend.JS)
}
}
}
@@ -35,19 +35,11 @@ public class NestedTypesTest extends SingleFileTranslationTest {
checkFooBoxIsOk();
}
public void testInstantiateInDerived() throws Exception {
public void testOuterCompanion() throws Exception {
checkFooBoxIsOk();
}
public void testInstantiateInDerivedLabeled() throws Exception {
checkFooBoxIsOk();
}
public void testInstantiateInSameClass() throws Exception {
checkFooBoxIsOk();
}
public void testProperOuter() throws Exception {
public void testOuterObject() throws Exception {
checkFooBoxIsOk();
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.test.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/box/classes/inner")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class NestedTypesTestGenerated extends AbstractNestedTypesTest {
public void testAllFilesPresentInInner() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classes/inner"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("instantiateInDerived.kt")
public void testInstantiateInDerived() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInDerived.kt");
doTest(fileName);
}
@TestMetadata("instantiateInDerivedLabeled.kt")
public void testInstantiateInDerivedLabeled() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInDerivedLabeled.kt");
doTest(fileName);
}
@TestMetadata("instantiateInSameClass.kt")
public void testInstantiateInSameClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInSameClass.kt");
doTest(fileName);
}
@TestMetadata("kt6708.kt")
public void testKt6708() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/kt6708.kt");
doTest(fileName);
}
@TestMetadata("properOuter.kt")
public void testProperOuter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properOuter.kt");
doTest(fileName);
}
@TestMetadata("properSuperLinking.kt")
public void testProperSuperLinking() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properSuperLinking.kt");
doTest(fileName);
}
}
@@ -51,3 +51,5 @@ abstract class AbstractInlineMultiModuleTest : MultipleModulesTranslationTest("i
abstract class AbstractReservedWordTest : SingleFileTranslationTest("reservedWords/")
abstract class AbstractSecondaryConstructorTest : AbstractBlackBoxTest("secondaryConstructors/")
abstract class AbstractNestedTypesTest : AbstractBlackBoxTest("nestedTypes/")
@@ -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
View File
@@ -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;
}