Prohibit callable references to object members
To be able to make them more useful in the future, i.e. bound to the object instance
This commit is contained in:
Vendored
-17
@@ -1,17 +0,0 @@
|
||||
import A.foo
|
||||
import A.bar
|
||||
|
||||
object A {
|
||||
fun foo() = "O"
|
||||
fun String.foo() = "K"
|
||||
|
||||
@JvmStatic
|
||||
fun bar(s: Int) = "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val static = (::bar)(0)
|
||||
if (static != "OK") return "1"
|
||||
|
||||
return (::foo)() + (String::foo)("")
|
||||
}
|
||||
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
object A {
|
||||
var result = "Fail"
|
||||
|
||||
fun foo() {
|
||||
result = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = A::foo
|
||||
x(A)
|
||||
return A.result
|
||||
}
|
||||
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
object A {
|
||||
var result = "Fail"
|
||||
|
||||
fun foo(newResult: String) {
|
||||
result = newResult
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = A::foo
|
||||
x(A, "OK")
|
||||
return A.result
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class A {
|
||||
companion object B {
|
||||
var state: String = "12345"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val p = A.B::state
|
||||
|
||||
if (p.name != "state") return "Fail state: ${p.name}"
|
||||
if (p.get(A.B) != "12345") return "Fail value: ${p.get(A.B)}"
|
||||
p.set(A.B, "OK")
|
||||
|
||||
return p[A.B]
|
||||
}
|
||||
Vendored
-33
@@ -1,33 +0,0 @@
|
||||
import A.foo
|
||||
import A.bar
|
||||
import A.baz
|
||||
|
||||
object A {
|
||||
var foo = "NotOk"
|
||||
var String.foo: String
|
||||
get() = "K"
|
||||
set(i) {}
|
||||
|
||||
@JvmStatic
|
||||
val bar: String = "OK"
|
||||
|
||||
@JvmStatic
|
||||
val String.baz: String
|
||||
get() = "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
val static = (::bar).get()
|
||||
if (static != "OK") return static
|
||||
|
||||
val staticExt = (String::baz).get("a")
|
||||
if (staticExt != "OK") return staticExt
|
||||
|
||||
val nonExt = ::foo
|
||||
|
||||
nonExt.set("O")
|
||||
val ext = String::foo
|
||||
ext.set("", "Whatever")
|
||||
return nonExt.get() + ext.get("")
|
||||
}
|
||||
@@ -4,12 +4,15 @@ fun box(): String {
|
||||
assertEquals(java.lang.Integer.MIN_VALUE, Int.MIN_VALUE)
|
||||
assertEquals(java.lang.Byte.MAX_VALUE, Byte.MAX_VALUE)
|
||||
|
||||
/*
|
||||
// TODO: uncomment when callable references to object members are supported
|
||||
assertEquals("MIN_VALUE", (Int.Companion::MIN_VALUE).name)
|
||||
assertEquals("MAX_VALUE", (Double.Companion::MAX_VALUE).name)
|
||||
assertEquals("MIN_VALUE", (Float.Companion::MIN_VALUE).name)
|
||||
assertEquals("MAX_VALUE", (Long.Companion::MAX_VALUE).name)
|
||||
assertEquals("MIN_VALUE", (Short.Companion::MIN_VALUE).name)
|
||||
assertEquals("MAX_VALUE", (Byte.Companion::MAX_VALUE).name)
|
||||
*/
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ class A(val s1: String, val s2: String) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// TODO: uncomment when callable references to object members are supported
|
||||
class AWithCompanion {
|
||||
companion object {
|
||||
@JvmField public val publicField = "1";
|
||||
@@ -26,10 +28,11 @@ class AWithCompanion {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fun box(): String {
|
||||
A("1", "2").testAccessors()
|
||||
AWithCompanion.testAccessors()
|
||||
// AWithCompanion.testAccessors()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.test.assertNotEquals
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
@@ -32,10 +33,12 @@ class AWithCompanion {
|
||||
@JvmField internal val internalField = "OK";
|
||||
@JvmField protected val protectedfield = "OK";
|
||||
|
||||
operator fun get(name: String) = AWithCompanion.Companion::class.members.single { it.name == name } as KProperty<*>
|
||||
|
||||
fun testVisibilities() {
|
||||
checkVisibility(AWithCompanion.Companion::publicField.javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(AWithCompanion.Companion::internalField.javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(AWithCompanion.Companion::protectedfield.javaField!!, Modifier.PROTECTED)
|
||||
checkVisibility(this["publicField"].javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(this["internalField"].javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(this["protectedfield"].javaField!!, Modifier.PROTECTED)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,10 +48,12 @@ object Object {
|
||||
@JvmField internal val internalField = "OK";
|
||||
@JvmField protected val protectedfield = "OK";
|
||||
|
||||
operator fun get(name: String) = Object::class.members.single { it.name == name } as KProperty<*>
|
||||
|
||||
fun testVisibilities() {
|
||||
checkVisibility(Object::publicField.javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(Object::internalField.javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(Object::protectedfield.javaField!!, Modifier.PROTECTED)
|
||||
checkVisibility(this["publicField"].javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(this["internalField"].javaField!!, Modifier.PUBLIC)
|
||||
checkVisibility(this["protectedfield"].javaField!!, Modifier.PROTECTED)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +66,4 @@ fun box(): String {
|
||||
|
||||
public fun checkVisibility(field: Field, visibility: Int) {
|
||||
assertNotEquals(field.modifiers and visibility, 0, "Field ${field} has wrong visibility")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
object A {
|
||||
|
||||
val b: String = "OK"
|
||||
|
||||
@platformStatic var c: String = "Fail"
|
||||
|
||||
@platformStatic fun test1() : String {
|
||||
return b
|
||||
}
|
||||
|
||||
@platformStatic fun test2() : String {
|
||||
return test1()
|
||||
}
|
||||
|
||||
fun test3(): String {
|
||||
return "1".test5()
|
||||
}
|
||||
|
||||
@platformStatic fun test4(): String {
|
||||
return "1".test5()
|
||||
}
|
||||
|
||||
@platformStatic fun String.test5() : String {
|
||||
return this + b
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if ((A::test1)(A) != "OK") return "fail 1"
|
||||
|
||||
if ((A::test2)(A) != "OK") return "fail 2"
|
||||
|
||||
if ((A::test3)(A) != "1OK") return "fail 3"
|
||||
|
||||
if ((A::test4)(A) != "1OK") return "fail 4"
|
||||
|
||||
(A::c).set(A, "OK")
|
||||
|
||||
if (((A::c).get(A)) != "OK") return "fail 5"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+7
-3
@@ -1,6 +1,8 @@
|
||||
import kotlin.jvm.JvmStatic as static
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KMutableProperty
|
||||
|
||||
var foo: String = ""
|
||||
|
||||
@@ -11,7 +13,9 @@ class A(private var bar: String = "") {
|
||||
object O {
|
||||
private @static var baz: String = ""
|
||||
|
||||
@static fun getBaz() = O::baz.apply { isAccessible = true }
|
||||
@static fun getBaz() = (O::class.members.single { it.name == "baz" } as KMutableProperty<*>).apply { isAccessible = true }
|
||||
|
||||
fun getGetBaz() = O::class.members.single { it.name == "getBaz" } as KFunction<*>
|
||||
}
|
||||
|
||||
fun check(callable: KCallable<*>, vararg args: Any?) {
|
||||
@@ -44,8 +48,8 @@ fun box(): String {
|
||||
check(::A)
|
||||
check(::A, null, "")
|
||||
|
||||
check(O::getBaz)
|
||||
check(O::getBaz, null, "")
|
||||
check(O.getGetBaz())
|
||||
check(O.getGetBaz(), null, "")
|
||||
|
||||
|
||||
val f = ::foo
|
||||
|
||||
@@ -11,7 +11,7 @@ class C {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
(Obj::foo).call(Obj)
|
||||
(C.Companion::bar).call(C.Companion)
|
||||
(Obj::class.members.single { it.name == "foo" }).call(Obj)
|
||||
(C.Companion::class.members.single { it.name == "bar" }).call(C.Companion)
|
||||
return "OK"
|
||||
}
|
||||
|
||||
Vendored
+9
-7
@@ -4,32 +4,34 @@ object Obj {
|
||||
@static fun foo(s: String) {}
|
||||
@static fun bar() {}
|
||||
@static fun sly(obj: Obj) {}
|
||||
|
||||
operator fun get(name: String) = Obj::class.members.single { it.name == name }
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
// This should succeed
|
||||
(Obj::foo).call(Obj, "")
|
||||
(Obj::bar).call(Obj)
|
||||
(Obj::sly).call(Obj, Obj)
|
||||
(Obj["foo"]).call(Obj, "")
|
||||
(Obj["bar"]).call(Obj)
|
||||
(Obj["sly"]).call(Obj, Obj)
|
||||
|
||||
// This shouldn't: first argument should always be Obj
|
||||
try {
|
||||
(Obj::foo).call(null, "")
|
||||
(Obj["foo"]).call(null, "")
|
||||
return "Fail foo"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::bar).call("")
|
||||
(Obj["bar"]).call("")
|
||||
return "Fail bar"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::sly).call(Obj)
|
||||
(Obj["sly"]).call(Obj)
|
||||
return "Fail sly 1"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::sly).call(null, Obj)
|
||||
(Obj["sly"]).call(null, Obj)
|
||||
return "Fail sly 2"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ fun nullableUnit(unit: Boolean): Unit? = if (unit) Unit else null
|
||||
fun box(): String {
|
||||
assertEquals(Unit, ::foo.call())
|
||||
assertEquals(Unit, A::bar.call(A()))
|
||||
assertEquals(Unit, O::baz.call(O))
|
||||
assertEquals(Unit, O::class.members.single { it.name == "baz" }.call(O))
|
||||
|
||||
assertEquals(Unit, (::nullableUnit).call(true))
|
||||
assertEquals(null, (::nullableUnit).call(false))
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ object Obj {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val f = Obj::foo
|
||||
val f = Obj::class.members.single { it.name == "foo" }
|
||||
|
||||
// Any object method currently requires the object instance passed
|
||||
try {
|
||||
|
||||
compiler/testData/codegen/boxWithStdlib/reflection/mapping/platformStatic/companionObjectFunction.kt
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
||||
import kotlin.jvm.JvmStatic as static
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.failsWith
|
||||
@@ -10,7 +11,7 @@ class C {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = C.Companion::foo
|
||||
val foo = C.Companion::class.members.single { it.name == "foo" } as KFunction<*>
|
||||
|
||||
val j = foo.javaMethod ?: return "Fail: no Java method found for C::foo"
|
||||
assertEquals(3, j.invoke(C, "abc"))
|
||||
|
||||
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
||||
import kotlin.jvm.JvmStatic as static
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@@ -7,7 +8,7 @@ object O {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = O::foo
|
||||
val foo = O::class.members.single { it.name == "foo" } as KFunction<*>
|
||||
|
||||
val j = foo.javaMethod ?: return "Fail: no Java method found for O::foo"
|
||||
assertEquals(3, j.invoke(null, "abc"))
|
||||
|
||||
+6
-4
@@ -11,11 +11,13 @@ object O {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(listOf(javaClass<A>(), javaClass<java.lang.Long>()), A::foo.parameters.map { it.type.javaType })
|
||||
assertEquals(listOf(javaClass<O>(), javaClass<A>()), O::bar.parameters.map { it.type.javaType })
|
||||
val foo = A::foo
|
||||
assertEquals(listOf(javaClass<A>(), javaClass<java.lang.Long>()), foo.parameters.map { it.type.javaType })
|
||||
assertEquals(java.lang.Long.TYPE, foo.returnType.javaType)
|
||||
|
||||
assertEquals(java.lang.Long.TYPE, A::foo.returnType.javaType)
|
||||
assertEquals(javaClass<String>(), O::bar.returnType.javaType)
|
||||
val bar = O::class.members.single { it.name == "bar" }
|
||||
assertEquals(listOf(javaClass<O>(), javaClass<A>()), bar.parameters.map { it.type.javaType })
|
||||
assertEquals(javaClass<String>(), bar.returnType.javaType)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user