JS backend: detect outer class if used in child local fun.

Fix closure fields when use it from nested functions in method.

(cherry picked from commit 20eea36)
This commit is contained in:
develar
2013-08-08 19:51:49 +04:00
committed by Zalim Bashorov
parent 632d878877
commit b9396ff7e8
2 changed files with 18 additions and 17 deletions
@@ -34,8 +34,6 @@ public final class UsageTracker {
@NotNull
private final MemberDescriptor memberDescriptor;
@Nullable
private final UsageTracker parent;
@Nullable
private List<UsageTracker> children;
@@ -47,7 +45,6 @@ public final class UsageTracker {
public UsageTracker(@NotNull MemberDescriptor memberDescriptor, @Nullable UsageTracker parent, @Nullable ClassDescriptor trackedClassDescriptor) {
this.memberDescriptor = memberDescriptor;
this.trackedClassDescriptor = trackedClassDescriptor;
this.parent = parent;
if (parent != null) {
parent.addChild(this);
}
@@ -119,16 +116,18 @@ public final class UsageTracker {
@Nullable
public ClassDescriptor getOuterClassDescriptor() {
if (outerClassDescriptor == null && parent != null) {
UsageTracker p = parent;
do {
if (p.outerClassDescriptor != null) {
return p.outerClassDescriptor;
}
}
while ((p = p.parent) != null);
if (outerClassDescriptor != null || children == null) {
return outerClassDescriptor;
}
return outerClassDescriptor;
for (UsageTracker child : children) {
ClassDescriptor childOuterClassDescriptor = child.getOuterClassDescriptor();
if (childOuterClassDescriptor != null) {
return childOuterClassDescriptor;
}
}
return null;
}
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
@@ -116,7 +116,9 @@ public class LiteralFunctionTranslator {
if (asInner) {
addRegularParameters(descriptor, fun, funContext, receiverName);
if (outerClass != null) {
if (funContext.usageTracker().isUsed()) {
UsageTracker usageTracker = funContext.usageTracker();
assert usageTracker != null;
if (usageTracker.isUsed()) {
return new JsInvocation(rootContext.namer().kotlin("assignOwner"), fun, JsLiteral.THIS);
}
else {
@@ -159,15 +161,15 @@ public class LiteralFunctionTranslator {
@NotNull ClassTranslator classTranslator) {
JsFunction fun = createFunction();
JsNameRef outerClassRef = fun.getScope().declareName("$this").makeRef();
TranslationContext funContext = rootContext
.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef), new UsageTracker(descriptor, null,
outerClass));
UsageTracker usageTracker = new UsageTracker(descriptor, null, outerClass);
TranslationContext funContext = rootContext.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef),
usageTracker);
fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext)));
JetClassBody body = declaration.getBody();
assert body != null;
InnerObjectTranslator translator = new InnerObjectTranslator(funContext, fun);
return translator.translate(createReference(fun), funContext.usageTracker().isUsed() ? outerClassRef : null);
return translator.translate(createReference(fun), usageTracker.isUsed() ? outerClassRef : null);
}
}