KT-12417: add support of RTTI against K(Mutable)Property* types

This commit is contained in:
Alexey Andreev
2016-06-14 16:38:17 +03:00
parent 048b6b60e9
commit 2e6a48576d
13 changed files with 256 additions and 36 deletions
@@ -0,0 +1,21 @@
package foo
import kotlin.reflect.KProperty1
import kotlin.reflect.KMutableProperty1
class A
var A.x: Int
get() = 23
set(value) { }
fun box(): String {
assertEquals(true, (A::x as Any) is KProperty1<*, *>)
assertEquals(true, (A::x as Any) is KMutableProperty1<*, *>)
assertEquals(23, ((A::x as Any) as KProperty1<A, Any>)(A()))
assertEquals(23, ((A::x as Any) as KMutableProperty1<A, Any>)(A()))
assertEquals(false, (23 as Any) is KMutableProperty1<*, *>)
assertEquals(false, ({ A().x } as Any) is KMutableProperty1<*, *>)
return "OK"
}
@@ -0,0 +1,17 @@
package foo
import kotlin.reflect.KProperty1
class A
val A.x: Int
get() = 23
fun box(): String {
assertEquals(true, (A::x as Any) is KProperty1<*, *>)
assertEquals(23, ((A::x as Any) as KProperty1<A, Any>)(A()))
assertEquals(false, (23 as Any) is KProperty1<*, *>)
assertEquals(false, ({ A().x } as Any) is KProperty1<*, *>)
return "OK"
}
@@ -0,0 +1,17 @@
package foo
import kotlin.reflect.KProperty0
import kotlin.reflect.KMutableProperty0
var x = 23
fun box(): String {
assertEquals(true, (::x as Any) is KProperty0<*>)
assertEquals(true, (::x as Any) is KMutableProperty0<*>)
assertEquals(23, ((::x as Any) as KProperty0<Any>)())
assertEquals(23, ((::x as Any) as KMutableProperty0<Any>)())
assertEquals(false, (23 as Any) is KMutableProperty0<*>)
assertEquals(false, ({ x } as Any) is KMutableProperty0<*>)
return "OK"
}
@@ -0,0 +1,20 @@
package foo
import kotlin.reflect.KProperty1
import kotlin.reflect.KMutableProperty1
class A {
var x = 23
}
fun box(): String {
assertEquals(true, (A::x as Any) is KProperty1<*, *>)
assertEquals(true, (A::x as Any) is KMutableProperty1<*, *>)
assertEquals(23, ((A::x as Any) as KProperty1<A, Any>)(A()))
assertEquals(23, ((A::x as Any) as KMutableProperty1<A, Any>)(A()))
assertEquals(false, (23 as Any) is KProperty1<*, *>)
assertEquals(false, (23 as Any) is KMutableProperty1<*, *>)
assertEquals(false, ({ A().x } as Any) is KMutableProperty1<*, *>)
return "OK"
}
@@ -0,0 +1,14 @@
package foo
import kotlin.reflect.KProperty0
val x = 23
fun box(): String {
assertEquals(true, (::x as Any) is KProperty0<*>)
assertEquals(23, ((::x as Any) as KProperty0<Any>)())
assertEquals(false, (23 as Any) is KProperty0<*>)
assertEquals(false, ({ x } as Any) is KProperty0<*>)
return "OK"
}
@@ -0,0 +1,16 @@
package foo
import kotlin.reflect.KProperty1
class A {
val x = 23
}
fun box(): String {
assertEquals(true, (A::x as Any) is KProperty1<*, *>)
assertEquals(23, ((A::x as Any) as KProperty1<A, Any>)(A()))
assertEquals(false, (23 as Any) is KProperty1<*, *>)
assertEquals(false, ({ A().x } as Any) is KProperty1<*, *>)
return "OK"
}
@@ -0,0 +1,19 @@
package foo
interface A
class B
fun box(): String {
assertEquals(false, (23 as Any) is A)
assertEquals(false, (23 as Any) is B)
assertEquals(false, (23L as Any) is A)
assertEquals(false, (23L as Any) is B)
assertEquals(false, ("qwe" as Any) is A)
assertEquals(false, ("qwe" as Any) is B)
assertEquals(false, ({ 23 } as Any) is A)
assertEquals(false, ({ 23 } as Any) is B)
assertEquals(false, (true as Any) is A)
assertEquals(false, (true as Any) is B)
return "OK"
}
+64 -27
View File
@@ -348,11 +348,11 @@ var Kotlin = {};
klass.$metadata$.properties[propertyName].set.call(thisObject, value);
};
function isInheritanceFromTrait(objConstructor, trait) {
if (isNativeClass(objConstructor) || objConstructor.$metadata$.classIndex < trait.$metadata$.classIndex) {
function isInheritanceFromTrait(metadata, trait) {
if (metadata == null || metadata.classIndex < trait.$metadata$.classIndex) {
return false;
}
var baseClasses = objConstructor.$metadata$.baseClasses;
var baseClasses = metadata.baseClasses;
var i;
for (i = 0; i < baseClasses.length; i++) {
if (baseClasses[i] === trait) {
@@ -360,7 +360,7 @@ var Kotlin = {};
}
}
for (i = 0; i < baseClasses.length; i++) {
if (isInheritanceFromTrait(baseClasses[i], trait)) {
if (isInheritanceFromTrait(baseClasses[i].$metadata$, trait)) {
return true;
}
}
@@ -368,7 +368,7 @@ var Kotlin = {};
}
Kotlin.isType = function (object, klass) {
if (object == null || klass == null) {
if (object == null || klass == null || (typeof object !== 'object' && typeof object !== 'function')) {
return false;
}
else {
@@ -379,7 +379,8 @@ var Kotlin = {};
return false;
}
else {
return isInheritanceFromTrait(object.constructor, klass);
var metadata = "$metadata$" in object ? object.$metadata$ : object.constructor.$metadata$;
return isInheritanceFromTrait(metadata, klass);
}
}
};
@@ -418,34 +419,70 @@ var Kotlin = {};
};
Kotlin.getCallableRefForTopLevelProperty = function(packageName, name, isVar) {
var obj = {};
obj.name = name;
obj.get = function() { return packageName[name]; };
if (isVar) {
obj.set_za3rmp$ = function(value) { packageName[name] = value; };
}
return obj;
var getFun = function() { return packageName[name]; };
var setFun = isVar ? function(value) { packageName[name] = value; } : null;
return getPropertyRefClass(name, getFun, "get", setFun, "set_za3rmp$", propertyRefClassMetadataCache.zeroArg);
};
Kotlin.getCallableRefForMemberProperty = function(name, isVar) {
var obj = {};
obj.name = name;
obj.get_za3rmp$ = function(receiver) { return receiver[name]; };
if (isVar) {
obj.set_wn2jw4$ = function(receiver, value) { receiver[name] = value; };
}
return obj;
var getFun = function(receiver) { return receiver[name]; };
var setFun = isVar ? function(receiver, value) { receiver[name] = value; } : null;
return getPropertyRefClass(name, getFun, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
};
Kotlin.getCallableRefForExtensionProperty = function(name, getFun, setFun) {
var obj = {};
obj.name = name;
obj.get_za3rmp$ = getFun;
if (typeof setFun === "function") {
obj.set_wn2jw4$ = setFun;
}
return obj;
var getFunWrapper = function(receiver, extensionReceiver) { return getFun(receiver, extensionReceiver) };
return getPropertyRefClass(name, getFunWrapper, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
};
function getPropertyRefClass(name, getFun, getName, setFun, setName, cache) {
var obj = getFun;
var isMutable = typeof setFun === "function";
obj.$metadata$ = getPropertyRefMetadata(isMutable ? cache.mutable : cache.immutable);
obj[getName] = getFun;
if (isMutable) {
obj[setName] = setFun;
}
obj.constructor = obj;
Object.defineProperty(obj, "name", { get : function() { return name; } });
return obj;
}
var propertyRefClassMetadataCache = {
zeroArg: {
mutable: { value: null, implementedInterface: function () {
return Kotlin.modules['stdlib'].kotlin.reflect.KMutableProperty0 }
},
immutable: { value: null, implementedInterface: function () {
return Kotlin.modules['stdlib'].kotlin.reflect.KProperty0 }
}
},
oneArg: {
mutable: { value: null, implementedInterface: function () {
return Kotlin.modules['stdlib'].kotlin.reflect.KMutableProperty1 }
},
immutable: { value: null, implementedInterface: function () {
return Kotlin.modules['stdlib'].kotlin.reflect.KProperty1 }
}
}
};
function getPropertyRefMetadata(cache) {
if (cache.value === null) {
cache.value = {
baseClasses: [cache.implementedInterface()],
baseClass: null,
classIndex: Kotlin.newClassIndex(),
functions: {},
properties: {},
types: {},
staticMembers: {}
};
}
return cache.value;
}
////////////////////////////////// packages & modules //////////////////////////////
Kotlin.modules = {};