Resolve invoke on any kind of expressions, not only on simple name expressions

This commit is contained in:
Svetlana Isakova
2014-02-04 19:07:06 +04:00
parent c7087d170e
commit a829da185d
31 changed files with 391 additions and 101 deletions
@@ -14,11 +14,11 @@ L0:
r(11)
call(array[11], get)
r(3)
call(array[11], <for expression array[11]>)
call(array[11], invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -11,11 +11,11 @@ L0:
mark((f)())
mark((f))
r(f)
call((f), <for expression (f)>)
call((f), invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -7,12 +7,11 @@ L0:
1 <START>
2 mark({ this() })
mark(this())
r(this)
call(this, <for expression this>)
call(this, invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -0,0 +1,21 @@
class A
class B {
fun A.invoke() = "##"
fun A.invoke(i: Int) = "#${i}"
}
fun foo() = A()
fun B.test(): String {
if (A()() != "##") return "fail1"
if (A()(1) != "#1") return "fail2"
if (foo()() != "##") return "fail3"
if (foo()(42) != "#42") return "fail4"
if ((foo())(42) != "#42") return "fail5"
if ({() -> A()}()() != "##") return "fail6"
if ({() -> A()}()(37) != "#37") return "fail7"
return "OK"
}
fun box(): String = B().test()
@@ -0,0 +1,20 @@
//KT-3217 Invoke convention after function invocation doesn't work
//KT-2728 Can't compile A()()
class A {
fun invoke() = "##"
fun invoke(i: Int) = "#${i}"
}
fun foo() = A()
fun box(): String {
if (A()() != "##") return "fail1"
if (A()(1) != "#1") return "fail2"
if (foo()() != "##") return "fail3"
if (foo()(42) != "#42") return "fail4"
if ((foo())(42) != "#42") return "fail5"
if ({() -> A()}()() != "##") return "fail6"
if ({() -> A()}()(37) != "#37") return "fail7"
return "OK"
}
@@ -0,0 +1,13 @@
//KT-3450 get and invoke are not parsed in one expression
public class A(val s: String) {
public fun get(i: Int) : A = A("$s + $i")
public fun invoke(builder : A.() -> String): String = builder()
}
fun x(y : String) : A = A(y)
fun foo() = x("aaa")[42] { "$s!!" }
fun box() = if (foo() == "aaa + 42!!") "OK" else "fail"
@@ -0,0 +1,5 @@
//KT-3631 String.invoke doesn't work with literals
fun String.invoke(i: Int) = "$this$i"
fun box() = if ("a"(12) == "a12") "OK" else "fail"
@@ -0,0 +1,21 @@
//KT-3772 Invoke and overload resolution ambiguity
open class A {
fun invoke(f: A.() -> Unit) = 1
}
class B {
fun invoke(f: B.() -> Unit) = 2
}
open class C
val C.attr = A()
open class D: C()
val D.attr = B()
fun box(): String {
val d = D()
return if (d.attr {} == 2) "OK" else "fail"
}
@@ -0,0 +1,8 @@
//KT-3821 Invoke convention doesn't work for `this`
class A() {
fun invoke() = 42
fun foo() = this() // Expecting a function type, but found A
}
fun box() = if (A().foo() == 42) "OK" else "fail"
@@ -0,0 +1,9 @@
//KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
class B() : Function0<Boolean> {
override fun invoke() = true
fun foo() = this() // Exception
}
fun box() = if (B().foo()) "OK" else "fail"
@@ -7,4 +7,4 @@ class Z{
}
}
// 2 invoke \(LZ;I\)V
// 1 invoke \(LZ;I\)V
@@ -2,4 +2,4 @@ fun test() {
1.{Int.() -> 2}()
}
// 2 invoke \(I\)I
// 1 invoke \(I\)I
@@ -0,0 +1,23 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
public class A {
public fun get(vararg attrs : Pair<String, String>) : A = this
}
fun String.plus() : A = A()
fun A.div(s : String) : A = A()
fun test() {
(+"node2" / "node3" / "zzz") ["attr" to "value", "a2" to "v2"]
}
//---------
class B {
public fun get(s : String, q : String) : B = this
public fun get(s : Pair<String, String>) : B = this
public fun invoke(q : B.() -> Unit) : B = this
}
val x = B()["a", "v"]["a" to "b"] {} ["q" to "p"] // does not parses around {}
//from library
data class Pair<out A, out B> (val first: A, val second: B)
fun <A,B> A.to(that: B) = Pair(this, that)
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun Int.invoke(i: Int, a: Any) {}
fun Int.invoke(a: Any, i: Int) {}
fun foo(i: Int) {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>i<!>(1, 1)
<!OVERLOAD_RESOLUTION_AMBIGUITY!>5<!>(1, 2)
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class My {
private fun Int.invoke(s: String) {}
}
fun My.foo(i: Int) {
<!INVISIBLE_MEMBER!>i<!>("")
<!INVISIBLE_MEMBER!>1<!>("")
}
@@ -0,0 +1,13 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T>
fun <T> T.invoke(a: A<T>) {}
fun foo(s: String, ai: A<Int>) {
1(ai)
<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>s<!>(ai)
<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>""<!>(ai)
}
@@ -0,0 +1,4 @@
fun foo(i: Int) {
<!FUNCTION_EXPECTED!>i<!>()
<!CALLEE_NOT_A_FUNCTION!>1<!>()
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun String.invoke(i: Int) {}
fun foo(s: String?) {
<!UNSAFE_CALL!>s<!>(1)
<!UNSAFE_CALL!>(s ?: null)<!>(1)
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun String.invoke(i: Int) {}
fun foo(i: Int) {
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>i<!>(1)
<!CALLEE_NOT_A_FUNCTION!>1<!>(1)
}