diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 183d34a878c..a1bdf47ef3a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -47,6 +47,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.evaluate.EvaluatePackage; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; @@ -75,6 +76,7 @@ import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplType; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull; +import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java index 7f9a2a6eca1..917e4db3ef8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -319,12 +319,6 @@ public class CodegenBinding { return containerInternalName + "$" + klass.getName().getIdentifier(); } - public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) { - if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false; - VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; - return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar(); - } - public static boolean hasThis0(BindingContext bindingContext, ClassDescriptor classDescriptor) { //noinspection SuspiciousMethodCalls CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index a805c4b670c..7e2f8261e37 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -55,6 +55,7 @@ import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType; import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; +import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index ef98c328fe0..cfe65cb746c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -40,6 +40,7 @@ import java.util.*; import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*; import static org.jetbrains.jet.lang.diagnostics.Errors.AMBIGUOUS_LABEL; import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_LABEL_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR; public class BindingContextUtils { @@ -363,4 +364,10 @@ public class BindingContextUtils { } return result; } + + public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) { + if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false; + VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; + return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar(); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/callTranslator/VarialbeCallCases.kt b/js/js.translator/src/org/jetbrains/k2js/translate/callTranslator/VarialbeCallCases.kt index 45723565b74..b32f9bdd9b9 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/callTranslator/VarialbeCallCases.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/callTranslator/VarialbeCallCases.kt @@ -19,14 +19,12 @@ package org.jetbrains.k2js.translate.callTranslator import com.google.dart.compiler.backend.js.ast.JsExpression import com.google.dart.compiler.backend.js.ast.JsNameRef import com.google.dart.compiler.backend.js.ast.JsLiteral -import org.jetbrains.k2js.translate.utils.JsAstUtils import com.google.dart.compiler.backend.js.ast.JsInvocation -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor import org.jetbrains.jet.lang.descriptors.CallableDescriptor import java.util.Collections -import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.jet.lang.resolve.DescriptorFactory import org.jetbrains.jet.lang.descriptors.PropertyDescriptor +import org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure +import org.jetbrains.k2js.translate.context.Namer.getCapturedVarAccessor object NativeVariableAccessCase : VariableAccessCase { @@ -39,7 +37,7 @@ object NativeVariableAccessCase : VariableAccessCase { } override fun VariableAccessInfo.noReceivers(): JsExpression { - return constructAccessExpression(variableName.makeRef()!!) + return constructAccessExpression(variableName.makeRef()) } } @@ -48,7 +46,15 @@ object DefaultVariableAccessCase : VariableAccessCase { val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(variableDescriptor) } - return constructAccessExpression(functionRef) + + val ref = + if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) { + getCapturedVarAccessor(functionRef) + } else { + functionRef + } + + return constructAccessExpression(ref) } override fun VariableAccessInfo.thisObject(): JsExpression { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java index 89b2ac83ef0..211dacac432 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java @@ -52,6 +52,7 @@ public final class Namer { private static final String CLASS_OBJECT_GETTER = "object"; private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$"; private static final String PROTOTYPE_NAME = "prototype"; + public static final String CAPTURED_VAR_FIELD = "v"; private static final String DELEGATE_POSTFIX = "$delegate"; @@ -144,6 +145,11 @@ public final class Namer { return new JsNameRef(APPLY_FUNCTION, functionExpression); } + @NotNull + public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) { + return new JsNameRef(CAPTURED_VAR_FIELD, ref); + } + @NotNull public static Namer newInstance(@NotNull JsScope rootScope) { return new Namer(rootScope); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 07c109d3254..42a6baee971 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -37,7 +38,10 @@ import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator; import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; -import org.jetbrains.k2js.translate.reference.*; +import org.jetbrains.k2js.translate.reference.AccessTranslationUtils; +import org.jetbrains.k2js.translate.reference.CallExpressionTranslator; +import org.jetbrains.k2js.translate.reference.QualifiedExpressionTranslator; +import org.jetbrains.k2js.translate.reference.ReferenceTranslator; import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; @@ -45,6 +49,8 @@ import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator; import java.util.List; +import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure; +import static org.jetbrains.k2js.translate.context.Namer.getCapturedVarAccessor; import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression; import static org.jetbrains.k2js.translate.reference.ReferenceTranslator.translateAsFQReference; import static org.jetbrains.k2js.translate.utils.BindingUtils.*; @@ -121,7 +127,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { } @Override - public JsNode visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, @NotNull TranslationContext context) { + public JsNode visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, @NotNull TranslationContext context) { JetExpression jetInitializer = multiDeclaration.getInitializer(); assert jetInitializer != null : "Initializer for multi declaration must be not null"; JsExpression initializer = Translation.translateAsExpression(jetInitializer, context); @@ -164,11 +170,9 @@ public final class ExpressionVisitor extends TranslatorVisitor { VariableDescriptor descriptor = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.VARIABLE, expression); JsExpression initializer = translateInitializerForProperty(expression, context); JsName name = context.getNameForDescriptor(descriptor); - if (descriptor.isVar() && context.bindingContext().get(BindingContext.CAPTURED_IN_CLOSURE, descriptor) != null) { - // well, wrap it - JsNameRef alias = new JsNameRef("v", new JsNameRef(name)); + if (isVarCapturedInClosure(context.bindingContext(), descriptor)) { + JsNameRef alias = getCapturedVarAccessor(name.makeRef()); initializer = JsAstUtils.wrapValue(alias, initializer == null ? JsLiteral.NULL : initializer); - context.aliasingContext().registerAlias(descriptor, alias); } return newVar(name, initializer).source(expression); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index 10d86ef2bd0..43dbabac7cc 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetQualifiedExpression; @@ -92,8 +92,13 @@ public final class ReferenceTranslator { else if (expression instanceof JetSimpleNameExpression) { simpleNameExpression = (JetSimpleNameExpression) expression; } - return simpleNameExpression != null && - (getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression) instanceof PropertyDescriptor); + + if (simpleNameExpression == null) return false; + + DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression); + + // Skip ValueParameterDescriptor because sometime we can miss resolved call for it, e.g. when set something to delegated property. + return descriptor instanceof VariableDescriptor && !(descriptor instanceof ValueParameterDescriptor); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 375d10c3a3f..a1dc805c997 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -148,7 +148,7 @@ public final class BindingUtils { public static ResolvedCall getResolvedCallForProperty(@NotNull BindingContext context, @NotNull JetExpression expression) { ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, expression); - assert resolvedCall != null : message(expression, expression.getText() + "must resolve to a call"); + assert resolvedCall != null : message(expression, expression.getText() + " must resolve to a call"); if (resolvedCall instanceof VariableAsFunctionResolvedCall) { return ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall(); }