works?
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java
index af13c69..ec92c35 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java
@@ -20,9 +20,11 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsInvocation;
+import org.jetbrains.kotlin.js.backend.ast.JsName;
import org.jetbrains.kotlin.js.backend.ast.JsNameRef;
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
import org.jetbrains.kotlin.js.patterns.NamePredicate;
@@ -31,11 +33,17 @@
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed;
+import org.jetbrains.kotlin.js.translate.reference.CallableReferenceTranslator;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
+import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
+import org.jetbrains.kotlin.psi.KtCallableReferenceExpression;
+import org.jetbrains.kotlin.psi.KtPsiUtil;
import org.jetbrains.kotlin.resolve.DescriptorFactory;
+import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
+import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.List;
@@ -150,13 +158,37 @@
}
};
+ private static final FunctionIntrinsic LATEINIT_KPROPERTY_ISINITIALIZED_INTRINSIC = new FunctionIntrinsic() {
+ @NotNull
+ @Override
+ public JsExpression apply(
+ @NotNull CallInfo callInfo,
+ @NotNull List<? extends JsExpression> arguments,
+ @NotNull TranslationContext context
+ ) {
+ ResolvedCall<? extends CallableDescriptor> call = callInfo.getResolvedCall();
+ ExpressionReceiver receiver = (ExpressionReceiver)call.getExtensionReceiver();
+
+ KtCallableReferenceExpression expression = (KtCallableReferenceExpression)KtPsiUtil.safeDeparenthesize(receiver.getExpression());
+ ResolvedCall<? extends CallableDescriptor> referencedProperty =
+ CallUtilKt.getResolvedCall(expression.getCallableReference(), context.bindingContext());
+ PropertyDescriptor propertyDescriptor = (PropertyDescriptor)referencedProperty.getResultingDescriptor();
+
+ JsExpression receiverExpression = CallableReferenceTranslator.INSTANCE.calculateReceiver(expression, context);
+ JsName backingFieldName = TranslationUtils.getNameForBackingField(
+ context, (PropertyDescriptor)JsDescriptorUtils.findRealDeclaration(propertyDescriptor));
+ JsNameRef backingFieldRef = new JsNameRef(backingFieldName, receiverExpression);
+ return TranslationUtils.nullCheck(backingFieldRef, true);
+ }
+ };
+
private static final FunctionIntrinsic STRING_SUBSTRING = new FunctionIntrinsicWithReceiverComputed() {
@NotNull
@Override
public JsExpression apply(
@Nullable JsExpression receiver,
- @NotNull List<? extends JsExpression> arguments,
- @NotNull TranslationContext context
+ @NotNull List<? extends JsExpression> arguments,
+ @NotNull TranslationContext context
) {
return new JsInvocation(new JsNameRef("substring", receiver), arguments);
}
@@ -202,6 +234,9 @@
add(pattern("kotlin", "enumValues"), ENUM_VALUES_INTRINSIC);
add(pattern("kotlin", "enumValueOf"), ENUM_VALUE_OF_INTRINSIC);
+
+ add(pattern("kotlin", "<get-isInitialized>").isExtensionOf("kotlin.reflect.KProperty0"),
+ LATEINIT_KPROPERTY_ISINITIALIZED_INTRINSIC);
}
}
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 82d2e1f..69fdab9 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
@@ -50,23 +50,8 @@
object CallableReferenceTranslator {
fun translate(expression: KtCallableReferenceExpression, context: TranslationContext): JsExpression {
- val referencedFunction = expression.callableReference.getResolvedCallWithAssert(context.bindingContext())
- val descriptor = referencedFunction.getResultingDescriptor()
-
- val extensionReceiver = referencedFunction.extensionReceiver
- val dispatchReceiver = referencedFunction.dispatchReceiver
- assert(dispatchReceiver == null || extensionReceiver == null) { "Cannot generate reference with both receivers: " + descriptor }
-
- val receiver = (dispatchReceiver ?: extensionReceiver)?.let {
- when (it) {
- is TransientReceiver -> null
- is ImplicitClassReceiver -> context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForReceiver(it))
- is ExtensionReceiver -> JsThisRef()
- is ExpressionReceiver -> Translation.translateAsExpression(it.expression, context)
- else -> throw UnsupportedOperationException("Unsupported receiver value: " + it)
- }
- }
-
+ val receiver = calculateReceiver(expression, context)
+ val descriptor = referencedDescriptor(expression, context)
return when (descriptor) {
is PropertyDescriptor ->
translateForProperty(descriptor, context, expression, receiver)
@@ -77,6 +62,28 @@
}
}
+ fun calculateReceiver(expression: KtCallableReferenceExpression, context: TranslationContext): JsExpression? {
+ val referencedFunction = expression.callableReference.getResolvedCallWithAssert(context.bindingContext())
+ val descriptor = referencedFunction.getResultingDescriptor()
+
+ val extensionReceiver = referencedFunction.extensionReceiver
+ val dispatchReceiver = referencedFunction.dispatchReceiver
+ assert(dispatchReceiver == null || extensionReceiver == null) { "Cannot generate reference with both receivers: " + descriptor }
+
+ return (dispatchReceiver ?: extensionReceiver)?.let {
+ when (it) {
+ is TransientReceiver -> null
+ is ImplicitClassReceiver -> context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForReceiver(it))
+ is ExtensionReceiver -> JsThisRef()
+ is ExpressionReceiver -> Translation.translateAsExpression(it.expression, context)
+ else -> throw UnsupportedOperationException("Unsupported receiver value: " + it)
+ }
+ }
+ }
+
+ fun referencedDescriptor(expression: KtCallableReferenceExpression, context: TranslationContext)
+ = expression.callableReference.getResolvedCallWithAssert(context.bindingContext()).getResultingDescriptor()
+
private fun translateForFunction(
descriptor: FunctionDescriptor,
context: TranslationContext,
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java
index 142ce06..8e11fc6 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java
@@ -170,12 +170,12 @@
}
@Nullable
- private static FunctionDescriptor findRealDeclaration(@NotNull FunctionDescriptor descriptor) {
+ public static CallableMemberDescriptor findRealDeclaration(@NotNull CallableMemberDescriptor descriptor) {
if (descriptor.getModality() == Modality.ABSTRACT) return null;
if (descriptor.getKind().isReal()) return descriptor;
- for (FunctionDescriptor o : descriptor.getOverriddenDescriptors()) {
- FunctionDescriptor child = findRealDeclaration(o);
+ for (CallableMemberDescriptor o : descriptor.getOverriddenDescriptors()) {
+ CallableMemberDescriptor child = findRealDeclaration(o);
if (child != null) {
return child;
}
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
index 9aec904..79c4a5f 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
@@ -54,9 +54,7 @@
import static org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator.*;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDescriptorForOperationExpression;
-import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment;
-import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.createDataDescriptor;
-import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
+import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*;
public final class TranslationUtils {
@@ -172,16 +170,22 @@
}
@NotNull
- public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
+ public static JsName getNameForBackingField(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
- JsName backingFieldName = containingDescriptor instanceof PackageFragmentDescriptor ?
- context.getInnerNameForDescriptor(descriptor) :
- context.getNameForDescriptor(descriptor);
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
- backingFieldName = context.getNameForBackingField(descriptor);
+ return context.getNameForBackingField(descriptor);
}
+ return containingDescriptor instanceof PackageFragmentDescriptor ?
+ context.getInnerNameForDescriptor(descriptor) :
+ context.getNameForDescriptor(descriptor);
+ }
+
+ @NotNull
+ public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
+ DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
+
JsExpression receiver;
if (containingDescriptor instanceof PackageFragmentDescriptor) {
receiver = null;
@@ -190,7 +194,7 @@
receiver = context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForDeclaration(containingDescriptor));
}
- JsNameRef result = new JsNameRef(backingFieldName, receiver);
+ JsNameRef result = new JsNameRef(getNameForBackingField(context, descriptor), receiver);
MetadataProperties.setType(result, getReturnTypeForCoercion(descriptor));
return result;
diff --git a/js/js.translator/testData/box/propertyAccess/simpleLateInitIsInitialized.kt b/js/js.translator/testData/box/propertyAccess/simpleLateInitIsInitialized.kt
index 5f4cc8f..2743597 100644
--- a/js/js.translator/testData/box/propertyAccess/simpleLateInitIsInitialized.kt
+++ b/js/js.translator/testData/box/propertyAccess/simpleLateInitIsInitialized.kt
@@ -1,3 +1,4 @@
+// EXPECTED_REACHABLE_NODES: 1035
// LANGUAGE_VERSION: 1.2
// WITH_RUNTIME