diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index efe446bc8c5..81ec777e818 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -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"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java index b49e4a323e9..881e71165fc 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java @@ -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); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java index a9334e9c0c2..52da5ec5039 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java @@ -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 aliases = new HashMap(); + 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(); } diff --git a/js/js.translator/testData/box/nameClashes/localFunctionInLambda.kt b/js/js.translator/testData/box/nameClashes/localFunctionInLambda.kt new file mode 100644 index 00000000000..47a7f93c0ad --- /dev/null +++ b/js/js.translator/testData/box/nameClashes/localFunctionInLambda.kt @@ -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() +}() \ No newline at end of file