JS: fix translation of local function in lambdas

This commit is contained in:
Alexey Andreev
2016-11-24 16:22:52 +03:00
parent 8ef72935a8
commit 9c9b23a0fb
4 changed files with 51 additions and 16 deletions
@@ -5528,6 +5528,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("localFunctionInLambda.kt")
public void testLocalFunctionInLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/nameClashes/localFunctionInLambda.kt");
doTest(fileName);
}
@TestMetadata("methodAndPrivateProperty.kt")
public void testMethodAndPrivateProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/nameClashes/methodAndPrivateProperty.kt");
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.js.translate.context.AliasingContext;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
import org.jetbrains.kotlin.psi.KtLambdaExpression;
@@ -70,8 +69,9 @@ public final class FunctionTranslator extends AbstractTranslator {
this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration);
this.functionDeclaration = functionDeclaration;
this.functionObject = function;
assert this.functionObject.getParameters().isEmpty()
: message(descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
if (!this.functionObject.getParameters().isEmpty()) {
throw new AssertionError(message(descriptor, "Function " + functionDeclaration.getText() + " processed for the second time."));
}
//NOTE: it's important we compute the context before we start the computation
this.functionBodyContext = getFunctionBodyContext();
MetadataProperties.setFunctionDescriptor(functionObject, descriptor);
@@ -88,18 +88,8 @@ public final class FunctionTranslator extends AbstractTranslator {
aliases.put(expectedReceiverDescriptor, extensionFunctionReceiverName.makeRef());
}
LocalFunctionCollector functionCollector = new LocalFunctionCollector(context().bindingContext());
functionDeclaration.acceptChildren(functionCollector, null);
for (FunctionDescriptor localFunction : functionCollector.getFunctions()) {
String localIdent = localFunction.getName().isSpecial() ? "lambda" : localFunction.getName().asString();
JsName localName = functionObject.getScope().getParent().declareTemporaryName(localIdent);
JsExpression alias = JsAstUtils.pureFqn(localName, null);
aliases.put(localFunction, alias);
}
AliasingContext aliasingContext = !aliases.isEmpty() ? context().aliasingContext().withDescriptorsAliased(aliases) : null;
return context().newFunctionBody(functionObject, aliasingContext, descriptor);
}
@@ -21,10 +21,12 @@ import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.expression.LocalFunctionCollector;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.utils.mutator.Mutator;
@@ -34,7 +36,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDefaultArgument;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*;
@@ -43,9 +47,26 @@ import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMuta
public final class FunctionBodyTranslator extends AbstractTranslator {
@NotNull
public static JsBlock translateFunctionBody(@NotNull FunctionDescriptor descriptor,
@NotNull KtDeclarationWithBody declarationWithBody,
@NotNull TranslationContext functionBodyContext) {
public static JsBlock translateFunctionBody(
@NotNull FunctionDescriptor descriptor,
@NotNull KtDeclarationWithBody declarationWithBody,
@NotNull TranslationContext functionBodyContext
) {
Map<DeclarationDescriptor, JsExpression> aliases = new HashMap<DeclarationDescriptor, JsExpression>();
LocalFunctionCollector functionCollector = new LocalFunctionCollector(functionBodyContext.bindingContext());
declarationWithBody.acceptChildren(functionCollector, null);
for (FunctionDescriptor localFunction : functionCollector.getFunctions()) {
String localIdent = localFunction.getName().isSpecial() ? "lambda" : localFunction.getName().asString();
JsName localName = functionBodyContext.scope().getParent().declareTemporaryName(localIdent);
JsExpression alias = JsAstUtils.pureFqn(localName, null);
aliases.put(localFunction, alias);
}
if (!aliases.isEmpty()) {
functionBodyContext = functionBodyContext.innerContextWithDescriptorsAliased(aliases);
}
return (new FunctionBodyTranslator(descriptor, declarationWithBody, functionBodyContext)).translate();
}
@@ -0,0 +1,18 @@
// MODULE: lib
// FILE: lib.kt
package lib
fun String.bar() = this
// MODULE: main(lib)
// FILE: main.kt
package foo
import lib.*
object O
fun box(): String = {
fun O.bar() = "O"
O.bar() + "K".bar()
}()