Properties work
diff --git a/compiler/testData/codegen/box/callableReference/bound/simpleProperty.kt b/compiler/testData/codegen/box/callableReference/bound/simpleProperty.kt
index bcf45ee0..11d4828 100644
--- a/compiler/testData/codegen/box/callableReference/bound/simpleProperty.kt
+++ b/compiler/testData/codegen/box/callableReference/bound/simpleProperty.kt
@@ -4,23 +4,30 @@
fun A.bar(x: Int) = foo() * x;
+object Foo {
+ val qqq = 6
+}
+
fun box(): String {
- var a = "kotlin".length
- print(a)
- val g = A::foo
- print(g(A(78)))
+// var a = "kotlin".length
+// print(a)
+// val g = A::foo
+// print(g(A(78)))
+//
+// val f = (if (1 < 2) A(6) else { print(1); A(2)})::foo
+// if (f() != 6) return "fail"
+//
+// val z = A(3)::bar
+// if (z(11) != 33) return "fail"
+//
+// val q = 100
+// fun A.zzz(x: Int) = (x + q) * foo()
+// val w = A(5)::zzz
+//
+// if (w(11) != 555) return "fail"
- val f = (if (1 < 2) A(6) else { print(1); A(2)})::foo
- if (f() != 6) return "fail"
-
- val z = A(3)::bar
- if (z(11) != 33) return "fail"
-
- val q = 100
- fun A.zzz(x: Int) = (x + q) * foo()
- val w = A(5)::zzz
-
- if (w(11) != 555) return "fail"
+ val ddd = Foo::qqq
+ if (ddd() != 6) return "fail"
return "OK"
}
diff --git a/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt b/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt
index d13956b..b8be540 100644
--- a/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt
+++ b/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt
@@ -1,3 +1,4 @@
+// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: A.java
diff --git a/compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt b/compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt
index ab6fb03..fc4f7f5 100644
--- a/compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt
+++ b/compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt
@@ -1,3 +1,5 @@
+// Enable when callble references for intrinsics are suported.
+// IGNORE_BACKEND: JS
// FILE: 1.kt
package test
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
index 6847c3c..4ca51b8 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
@@ -85,7 +85,9 @@
private static final String CALLABLE_REF_FOR_CONSTRUCTOR_NAME = "getCallableRefForConstructor";
private static final String CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY = "getCallableRefForTopLevelProperty";
private static final String CALLABLE_REF_FOR_MEMBER_PROPERTY = "getCallableRefForMemberProperty";
+ private static final String BOUND_CALLABLE_REF_FOR_MEMBER_PROPERTY = "getBoundCallableRefForMemberProperty";
private static final String CALLABLE_REF_FOR_EXTENSION_PROPERTY = "getCallableRefForExtensionProperty";
+ private static final String BOUND_CALLABLE_REF_FOR_EXTENSION_PROPERTY = "getBoundCallableRefForExtensionProperty";
private static final String DELEGATE = "$delegate";
@@ -210,8 +212,12 @@
@NotNull
private final JsName callableRefForMemberProperty;
@NotNull
+ private final JsName boundCallableRefForMemberProperty;
+ @NotNull
private final JsName callableRefForExtensionProperty;
@NotNull
+ private final JsName boundCallableRefForExtensionProperty;
+ @NotNull
private final JsExpression callGetProperty;
@NotNull
private final JsExpression callSetProperty;
@@ -234,7 +240,9 @@
callableRefForConstructorName = kotlinScope.declareName(CALLABLE_REF_FOR_CONSTRUCTOR_NAME);
callableRefForTopLevelProperty = kotlinScope.declareName(CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY);
callableRefForMemberProperty = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_PROPERTY);
+ boundCallableRefForMemberProperty = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_MEMBER_PROPERTY);
callableRefForExtensionProperty = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_PROPERTY);
+ boundCallableRefForExtensionProperty = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_EXTENSION_PROPERTY);
isTypeName = kotlinScope.declareName("isType");
}
@@ -296,11 +304,21 @@
}
@NotNull
+ public JsExpression boundCallableRefForMemberPropertyReference() {
+ return kotlin(boundCallableRefForMemberProperty);
+ }
+
+ @NotNull
public JsExpression callableRefForExtensionPropertyReference() {
return kotlin(callableRefForExtensionProperty);
}
@NotNull
+ public JsExpression boundCallableRefForExtensionPropertyReference() {
+ return kotlin(boundCallableRefForExtensionProperty);
+ }
+
+ @NotNull
public static JsExpression throwNPEFunctionRef() {
return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
}
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt
index bf1d1b7..6c31736 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt
@@ -25,11 +25,14 @@
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
import java.util.*
object CallableReferenceTranslator {
fun translate(expression: KtCallableReferenceExpression, context: TranslationContext): JsExpression {
+ val descriptor = BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), expression.callableReference)
+
val receiver = expression.receiverExpression?.let { r ->
if (context.bindingContext().getType(r) == null) {
null
@@ -41,9 +44,11 @@
}
e
}
+ } ?: (descriptor as? PropertyImportedFromObject)?.let {
+ ReferenceTranslator.translateAsValueReference(it.containingObject, context)
}
- val descriptor = BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), expression.callableReference)
+
return when (descriptor) {
is PropertyDescriptor ->
translateForProperty(descriptor, context, expression, receiver)
@@ -87,9 +92,9 @@
KotlinBuiltIns.isBuiltIn(descriptor) ->
reportNotSupported(context, expression)
isExtension(descriptor) ->
- translateForExtensionProperty(descriptor, context)
+ translateForExtensionProperty(descriptor, context, receiver)
isMember(descriptor) ->
- translateForMemberProperty(descriptor, context)
+ translateForMemberProperty(descriptor, context, receiver)
else ->
translateForTopLevelProperty(descriptor, context)
}
@@ -157,27 +162,39 @@
return function
}
- private fun translateForMemberProperty(descriptor: PropertyDescriptor, context: TranslationContext): JsExpression {
+ private fun translateForMemberProperty(descriptor: PropertyDescriptor, context: TranslationContext, receiver: JsExpression?): JsExpression {
val jsPropertyName = context.getNameForDescriptor(descriptor)
val jsPropertyNameAsString = context.program().getStringLiteral(jsPropertyName.toString())
- return JsInvocation(context.namer().callableRefForMemberPropertyReference(), jsPropertyNameAsString, isVar(descriptor))
+ if (receiver == null) {
+ return JsInvocation(context.namer().callableRefForMemberPropertyReference(), jsPropertyNameAsString, isVar(descriptor))
+ } else {
+ return JsInvocation(context.namer().boundCallableRefForMemberPropertyReference(), receiver, jsPropertyNameAsString, isVar(descriptor))
+ }
}
- private fun translateForExtensionProperty(descriptor: PropertyDescriptor, context: TranslationContext): JsExpression {
+ private fun translateForExtensionProperty(descriptor: PropertyDescriptor, context: TranslationContext, receiver: JsExpression?): JsExpression {
val jsGetterNameRef = ReferenceTranslator.translateAsValueReference(descriptor.getter!!, context)
val propertyName = descriptor.name
val jsPropertyNameAsString = context.program().getStringLiteral(propertyName.asString())
- val argumentList = ArrayList<JsExpression>(3)
+ val argumentList = ArrayList<JsExpression>(4)
+ if (receiver != null) {
+ argumentList.add(receiver)
+ }
argumentList.add(jsPropertyNameAsString)
argumentList.add(jsGetterNameRef)
if (descriptor.isVar) {
val jsSetterNameRef = ReferenceTranslator.translateAsValueReference(descriptor.setter!!, context)
argumentList.add(jsSetterNameRef)
}
- return if (AnnotationsUtils.isNativeObject(descriptor))
- translateForMemberProperty(descriptor, context)
- else
+ return if (AnnotationsUtils.isNativeObject(descriptor)) {
+ translateForMemberProperty(descriptor, context, receiver)
+ }
+ else if (receiver == null) {
JsInvocation(context.namer().callableRefForExtensionPropertyReference(), argumentList)
+ }
+ else {
+ JsInvocation(context.namer().boundCallableRefForExtensionPropertyReference(), argumentList)
+ }
}
private fun translateForConstructor(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
diff --git a/js/js.translator/testData/kotlin_lib_ecma5.js b/js/js.translator/testData/kotlin_lib_ecma5.js
index 3cfdcf9..a4925ca 100644
--- a/js/js.translator/testData/kotlin_lib_ecma5.js
+++ b/js/js.translator/testData/kotlin_lib_ecma5.js
@@ -183,11 +183,25 @@
return getPropertyRefClass(getFun, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
};
+ Kotlin.getBoundCallableRefForMemberProperty = function(receiver, name, isVar) {
+ var getFun = Function("receiver", "return function " + name + "() { return receiver['" + name + "']; }")(receiver);
+ var setFun = isVar ? function(value) { receiver[name] = value; } : null;
+ return getPropertyRefClass(getFun, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
+ };
+
Kotlin.getCallableRefForExtensionProperty = function(name, getFun, setFun) {
var getFunWrapper = Function("getFun", "return function " + name + "(receiver, extensionReceiver) { return getFun(receiver, extensionReceiver) }")(getFun);
return getPropertyRefClass(getFunWrapper, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
};
+ Kotlin.getBoundCallableRefForExtensionProperty = function(receiver, name, getFun, setFun) {
+ var getFunWrapper = Function("receiver", "getFun", "return function " + name + "(extensionReceiver) { return getFun(receiver, extensionReceiver) }")(receiver, getFun);
+ if (setFun) {
+ setFun = setFun.bind(null, receiver);
+ }
+ return getPropertyRefClass(getFunWrapper, "get_za3rmp$", setFun, "set_wn2jw4$", propertyRefClassMetadataCache.oneArg);
+ };
+
function getPropertyRefClass(getFun, getName, setFun, setName, cache) {
var obj = getFun;
var isMutable = typeof setFun === "function";
diff --git a/js/js.translator/testData/test.html b/js/js.translator/testData/test.html
index 5d94ae1..9a85904 100644
--- a/js/js.translator/testData/test.html
+++ b/js/js.translator/testData/test.html
@@ -2,7 +2,7 @@
<html>
<head>
<script type="application/javascript" src="../../../dist/js/kotlin.js"></script>
- <script type="application/javascript" src="out/codegen/boxInline/callableReference/classLevel_v5.js"></script>
+ <script type="application/javascript" src="out/codegen/boxInline/callableReference/bound/topLevelExtensionProperty_v5.js"></script>
<script type="application/javascript">
console.log(JS_TESTS.box());