Issue related to KT-1962
Correctly reference this object in wrapped function literal
This commit is contained in:
@@ -31,8 +31,11 @@ public final class ClosureTest extends SingleFileTranslationTest {
|
||||
fooBoxTest();
|
||||
}
|
||||
|
||||
|
||||
public void testLocalParameterInCallback() throws Exception {
|
||||
fooBoxTest();
|
||||
}
|
||||
|
||||
public void testClosureReferencingMember() throws Exception {
|
||||
fooBoxTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,13 @@ public final class TemporaryVariable {
|
||||
private final JsExpression assignmentExpression;
|
||||
@NotNull
|
||||
private final JsName variableName;
|
||||
@NotNull
|
||||
private final JsExpression initExpression;
|
||||
|
||||
/*package*/ TemporaryVariable(@NotNull JsName temporaryName, @NotNull JsExpression initExpression) {
|
||||
this.variableName = temporaryName;
|
||||
this.assignmentExpression = AstUtil.newAssignment(variableName.makeRef(), initExpression);
|
||||
this.initExpression = initExpression;
|
||||
this.assignmentExpression = AstUtil.newAssignment(variableName.makeRef(), this.initExpression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -51,4 +54,9 @@ public final class TemporaryVariable {
|
||||
public JsExpression assignmentExpression() {
|
||||
return assignmentExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression initExpression() {
|
||||
return initExpression;
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -40,9 +40,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
||||
import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setParameters;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
|
||||
@NotNull TranslationContext context) {
|
||||
@NotNull TranslationContext context) {
|
||||
return new FunctionTranslator(function, context);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
private final JsBlock functionBody;
|
||||
|
||||
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
|
||||
@NotNull TranslationContext context) {
|
||||
@NotNull TranslationContext context) {
|
||||
super(context);
|
||||
this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration);
|
||||
this.functionDeclaration = functionDeclaration;
|
||||
@@ -140,7 +140,11 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
public JsExpression translateAsLiteral() {
|
||||
assert getExpectedThisDescriptor(descriptor) == null;
|
||||
generateFunctionObject();
|
||||
return mayBeWrapInClosureCaptureExpression(mayBeWrapWithThisAlias());
|
||||
ClosureContext closureContext = ClosureUtils.captureClosure(context(), (JetElement) functionDeclaration);
|
||||
if (closureContext.getDescriptors().isEmpty()) {
|
||||
return mayBeWrapWithThisAlias();
|
||||
}
|
||||
return wrapInClosureCaptureExpression(functionObject, closureContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -160,23 +164,18 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
return containingClass != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression mayBeWrapInClosureCaptureExpression(@NotNull JsExpression wrappedExpression) {
|
||||
ClosureContext closureContext = ClosureUtils.captureClosure(context(), (JetElement)functionDeclaration);
|
||||
if (closureContext.getDescriptors().isEmpty()) {
|
||||
return wrappedExpression;
|
||||
}
|
||||
return wrapInClosureCaptureExpression(wrappedExpression, closureContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression wrapInClosureCaptureExpression(@NotNull JsExpression wrappedExpression,
|
||||
@NotNull ClosureContext closureContext) {
|
||||
@NotNull ClosureContext closureContext) {
|
||||
JsFunction dummyFunction = new JsFunction(context().jsScope());
|
||||
JsInvocation dummyFunctionInvocation = AstUtil.newInvocation(dummyFunction);
|
||||
for (VariableDescriptor variableDescriptor : closureContext.getDescriptors()) {
|
||||
dummyFunction.getParameters().add(new JsParameter(context().getNameForDescriptor(variableDescriptor)));
|
||||
dummyFunctionInvocation.getArguments().add(ReferenceTranslator.translateAsLocalNameReference(variableDescriptor, context()));
|
||||
if (aliasForContainingClassThis != null) {
|
||||
dummyFunction.getParameters().add(new JsParameter(aliasForContainingClassThis.name()));
|
||||
dummyFunctionInvocation.getArguments().add(aliasForContainingClassThis.initExpression());
|
||||
}
|
||||
}
|
||||
dummyFunction.setBody(AstUtil.newBlock(new JsReturn(wrappedExpression)));
|
||||
return dummyFunctionInvocation;
|
||||
|
||||
+3
@@ -56,6 +56,7 @@ public class CaptureClosureVisitor extends JetTreeVisitor<ClosureContext> {
|
||||
if (!(descriptor instanceof VariableDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
|
||||
PsiElement variableDeclaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
|
||||
if (variableDeclaration == null) {
|
||||
@@ -69,6 +70,8 @@ public class CaptureClosureVisitor extends JetTreeVisitor<ClosureContext> {
|
||||
context.put(variableDescriptor);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
boolean isLoopParameter = variableDeclaration.getNode().getElementType().equals(JetNodeTypes.LOOP_PARAMETER);
|
||||
if (isLoopParameter) {
|
||||
context.put(variableDescriptor);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package foo
|
||||
|
||||
class A() {
|
||||
|
||||
var i = 0
|
||||
|
||||
fun f() {
|
||||
for (j in 0..2) {
|
||||
foo {
|
||||
i += j
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(f : ()->Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
fun box() : Boolean {
|
||||
val a = A()
|
||||
a.f()
|
||||
return a.i == 3
|
||||
}
|
||||
Reference in New Issue
Block a user