JS backend: support for explicit delegation

#KT-4479 Fixed
This commit is contained in:
Michael Nedzelsky
2014-08-06 11:02:52 +04:00
parent 82af542747
commit 12db8f1551
26 changed files with 942 additions and 75 deletions
@@ -0,0 +1,27 @@
// This test was adapted from compiler/testData/codegen/box/classes
package foo
trait Trait1 {
fun foo(): String
}
trait Trait2 {
fun bar(): String
}
class T1 : Trait1 {
override fun foo() = "aaa"
}
class T2 : Trait2 {
override fun bar() = "bbb"
}
class C(a: Trait1, b: Trait2) : Trait1 by a, Trait2 by b
fun box(): String {
val c = C(T1(), T2())
if (c.foo() != "aaa") return "fail"
if (c.bar() != "bbb") return "fail"
return "OK"
}
@@ -0,0 +1,38 @@
// This test was adapted from compiler/testData/codegen/box/classes
package foo
trait One {
public open fun foo(): Int
public open fun faz(): Int = 10
}
trait Two {
public open fun foo(): Int
public open fun quux(): Int = 100
}
class OneImpl : One {
public override fun foo() = 1
}
class TwoImpl : Two {
public override fun foo() = 2
}
class Test2(a: One, b: Two) : Two by b, One by a {
public override fun foo() = 0
}
fun box(): String {
var t2 = Test2(OneImpl(), TwoImpl())
if (t2.foo() != 0)
return "Fail #1"
if (t2.faz() != 10)
return "Fail #2"
if (t2.quux() != 100)
return "Fail #3"
if (t2 !is One)
return "Fail #4"
if (t2 !is Two)
return "Fail #5"
return "OK"
}
@@ -0,0 +1,31 @@
// This test was adapted from compiler/testData/codegen/box/classes
package foo
open trait First {
public open fun foo(): Int
}
open trait Second : First {
public open fun bar(): Int
}
class Impl : Second {
public override fun foo() = 1
public override fun bar() = 2
}
class Test(s: Second) : Second by s {}
fun box(): String {
var t = Test(Impl())
if (t.foo() != 1)
return "Fail #1"
if (t.bar() != 2)
return "Fail #2"
if (t !is First)
return "Fail #3"
if (t !is Second)
return "Fail #4"
return "OK"
}
@@ -0,0 +1,27 @@
package foo
trait Base {
abstract fun foo(x: String): String
var prop: String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
override var prop: String = "prop"
}
class Derived(b: Base) : Base by b
fun box(): String {
var d = Derived(BaseImpl("test"))
assertEquals("Base: test:!!", d.foo("!!"), "delegation by argument, function member")
assertEquals("prop", d.prop, "delegation by argument, get property")
d.prop = "new value"
assertEquals("new value", d.prop, "delegation by argument, set property")
return "OK"
}
@@ -0,0 +1,18 @@
package foo
trait Base {
abstract fun foo(arg: String): String
}
class BaseImpl(val s1: String, val s2: String) : Base {
override fun foo(arg: String): String = "BaseImpl:foo ${s1}:${s2}:${arg}"
}
class Derived(s1: String, s2: String) : Base by BaseImpl(s1, s2)
fun box(): String {
assertEquals("BaseImpl:foo arg1:arg2:!!", Derived("arg1", "arg2").foo("!!"), "delegation with two arguments")
return "OK"
}
@@ -0,0 +1,20 @@
package foo
trait Base {
abstract fun foo(x: String): String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
}
fun newBase(s: String): Base = BaseImpl(s)
class Derived() : Base by newBase("test")
fun box(): String {
assertEquals("Base: test:!!", Derived().foo("!!"), "delegation by function expression")
return "OK"
}
@@ -0,0 +1,22 @@
package foo
trait Base {
abstract fun foo(x: String): String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
}
var global = true
class Derived() : Base by if (global) BaseImpl("then") else BaseImpl("else")
fun box(): String {
assertEquals("Base: then:!!", Derived().foo("!!"), "delegation by if expression")
global = false
assertEquals("Base: else:!!", Derived().foo("!!"), "delegation by if expression")
return "OK"
}
@@ -0,0 +1,47 @@
package foo
trait Base {
abstract fun foo(s: String): String
var prop: String
}
trait Base1 : Base {
}
trait Base2 : Base1 {
override fun foo(s: String): String = "Base2:foo ${s}"
}
class Base2Impl() : Base2 {
override var prop: String = ""
set(value) {
$prop = "prop:${value}"
}
}
class Derived() : Base by Base2Impl()
class Derived1() : Base1 by Base2Impl()
class Derived2() : Base2 by Base2Impl()
fun box(): String {
assertEquals("Base2:foo !!", Derived().foo("!!"), "delegation (Base)")
assertEquals("Base2:foo !!", Derived1().foo("!!"), "delegation (Base1)")
assertEquals("Base2:foo !!", Derived2().foo("!!"), "delegation (Base2)")
var d = Derived()
d.prop = "A"
assertEquals("prop:A", d.prop, "delegation (Base) set property")
var d1 = Derived1()
d1.prop = "B"
assertEquals("prop:B", d1.prop, "delegation (Base1) set property")
var d2 = Derived1()
d2.prop = "C"
assertEquals("prop:C", d2.prop, "delegation (Base2) set property")
return "OK"
}
@@ -0,0 +1,17 @@
package foo
trait Base {
abstract fun foo(x: String): String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
}
class Derived() : Base by BaseImpl("test")
fun box(): String {
assertEquals("Base: test:!!", Derived().foo("!!"), "delegation by new instance")
return "OK"
}
@@ -0,0 +1,31 @@
package foo
trait Base {
abstract fun foo(x: String): String
var prop: String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String) = "BaseImpl.foo: ${s}:${x}"
override var prop: String = "init"
set(value) {
$prop = "prop:${value}"
}
}
class Base2Impl(val s: String) : Base by BaseImpl("${s} by BaseImpl")
class Derived(val s: String) : Base by Base2Impl("${s} by Base2Impl")
fun box(): String {
assertEquals("BaseImpl.foo: Derived by Base2Impl by BaseImpl:!!", Derived("Derived").foo("!!"))
var d = Derived("Derived")
assertEquals("init", d.prop)
d.prop = "A"
assertEquals("prop:A", d.prop)
return "OK"
}
@@ -0,0 +1,45 @@
package foo
trait Base {
abstract fun foo(x: String): String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
}
var global = ""
open class DerivedBase() {
{
global += ":DerivedBase"
}
}
fun newBase(): Base {
global += ":newBase"
return BaseImpl("test")
}
class Derived() : DerivedBase(), Base by newBase() {
{
global += ":Derived"
}
}
class Derived1() : Base by newBase(), DerivedBase() {
{
global += ":Derived"
}
}
fun box(): String {
var d = Derived()
assertEquals(":DerivedBase:newBase:Derived", global, "evaluation order")
global = ""
var d1 = Derived1()
assertEquals(":DerivedBase:newBase:Derived", global, "evaluation order")
return "OK"
}
@@ -0,0 +1,68 @@
package foo
trait Base {
abstract fun foo(x: String): String
}
class BaseImpl(val s: String) : Base {
override fun foo(x: String): String = "Base: ${s}:${x}"
}
trait Base2 {
abstract fun bar(x: String): String
}
class Base2Impl(val s: String) : Base2 {
override fun bar(x: String): String = "Base2: ${s}:${x}"
}
var global = ""
open class DerivedBase() {
{
global += ":DerivedBase"
}
}
fun newBase(): Base {
global += ":newBase"
return BaseImpl("test")
}
fun newBase2(): Base2 {
global += ":newBase2"
return Base2Impl("test")
}
class Derived() : DerivedBase(), Base by newBase(), Base2 by newBase2() {
{
global += ":Derived"
}
}
class Derived1() : Base by newBase(), DerivedBase(), Base2 by newBase2() {
{
global += ":Derived"
}
}
class Derived2() : Base by newBase(), Base2 by newBase2(), DerivedBase() {
{
global += ":Derived"
}
}
fun box(): String {
var d = Derived()
assertEquals(":DerivedBase:newBase:newBase2:Derived", global, "evaluation order 1")
global = ""
var d1 = Derived1()
assertEquals(":DerivedBase:newBase:newBase2:Derived", global, "evaluation order 2")
global = ""
var d2 = Derived2()
assertEquals(":DerivedBase:newBase:newBase2:Derived", global, "evaluation order 3")
return "OK"
}
@@ -0,0 +1,19 @@
package foo
trait Base {
abstract fun Int.foo(): String
}
open class BaseImpl(val s: String) : Base {
override fun Int.foo(): String = "Int.foo ${s}:${this}"
}
class Derived() : Base by BaseImpl("test") {
fun bar(x: Int): String = x.foo()
}
fun box(): String {
assertEquals("Int.foo test:5", Derived().bar(5))
return "OK"
}
@@ -0,0 +1,19 @@
package foo
trait Base {
abstract fun String.foo(arg: String): String
}
open class BaseImpl(val s: String) : Base {
override fun String.foo(arg: String): String = "Int.foo ${s}:${this}:${arg}"
}
class Derived() : Base by BaseImpl("test") {
fun bar(x: String, arg: String): String = x.foo(arg)
}
fun box(): String {
assertEquals("Int.foo test:A:B", Derived().bar("A", "B"))
return "OK"
}
@@ -0,0 +1,33 @@
package foo
trait Base {
var prop: String
var Int.foo: String
}
open class BaseImpl(val s: String) : Base {
override var prop: String = "init"
override var Int.foo: String
get() = "get Int.foo:${s}:${this}"
set(value) {
prop = "set Int.foo:${s}:${this}:${value}"
}
}
class Derived() : Base by BaseImpl("test") {
fun getFooValue(x: Int): String = x.foo
fun setFooValue(x: Int, value: String) {
x.foo = value
}
}
fun box(): String {
var d = Derived()
assertEquals("get Int.foo:test:5", d.getFooValue(5))
d.setFooValue(10, "A")
assertEquals("set Int.foo:test:10:A", d.prop)
return "OK"
}
@@ -0,0 +1,15 @@
// This test was adapted from compiler/testData/codegen/box/classes
package foo
trait A<T> {
fun foo(t: T): String
}
class Derived(a: A<Int>) : A<Int> by a
fun box(): String {
val o = object : A<Int> {
override fun foo(t: Int) = if (t == 42) "OK" else "Fail $t"
}
return Derived(o).foo(42)
}
@@ -0,0 +1,35 @@
// This test was adapted from compiler/testData/codegen/box/classes
package foo
trait TextField {
fun getText(): String
}
trait InputTextField : TextField {
fun setText(text: String)
}
trait MooableTextField : InputTextField {
fun moo(a: Int, b: Int, c: Int): Int
}
class SimpleTextField : MooableTextField {
private var text2 = ""
override fun getText() = text2
override fun setText(text: String) {
this.text2 = text
}
override fun moo(a: Int, b: Int, c: Int) = a + b + c
}
class TextFieldWrapper(textField: MooableTextField) : MooableTextField by textField
fun box(): String {
val textField = TextFieldWrapper(SimpleTextField())
textField.setText("hello world!")
if (!textField.getText().equals("hello world!")) return "FAIL #!1"
if (textField.moo(1, 2, 3) != 6) return "FAIL #2"
return "OK"
}