JS backend: don't aliasing captured variable foo as foo.v.
Moved isVarCapturedInClosure from CodegenBinding to BindingContextUtils.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+10
-6
@@ -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<JsNode> {
|
||||
}
|
||||
|
||||
@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<JsNode> {
|
||||
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);
|
||||
|
||||
+8
-3
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public final class BindingUtils {
|
||||
public static ResolvedCall<?> getResolvedCallForProperty(@NotNull BindingContext context,
|
||||
@NotNull JetExpression expression) {
|
||||
ResolvedCall<? extends CallableDescriptor> 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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user