From 090fd1b7f6c54dcb4da363bfab74c83523f4abf8 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Thu, 15 Mar 2012 19:13:40 +0400 Subject: [PATCH] Fixes for cases where unexpected declaration descriptor hierarchy caused invalid scoping structure in js backend. Minor refactorings. --- .../k2js/test/semantics/MiscTest.java | 16 +++++ .../translate/context/DynamicContext.java | 28 +++----- .../k2js/translate/context/StaticContext.java | 7 +- .../translate/context/TranslationContext.java | 28 +++++--- .../declaration/PropertyTranslator.java | 4 +- .../expression/FunctionTranslator.java | 19 ++---- .../k2js/translate/general/Translation.java | 6 +- .../AbstractInitializerTranslator.java | 68 ------------------- .../ClassInitializerTranslator.java | 21 +++--- .../initializer/InitializerUtils.java | 42 ++++++++++++ .../NamespaceInitializerTranslator.java | 26 ++++--- .../k2js/translate/utils/BindingUtils.java | 2 +- .../k2js/translate/utils/JsAstUtils.java | 7 ++ ...extensionLiteralCreatedAtNamespaceLevel.kt | 19 ++++++ .../misc/cases/funInConstructorBlock.kt | 19 ++++++ .../cases/namespacePropertyCalledAsFun.kt | 7 ++ ...ryVariableCreatedInNamespaceInitializer.kt | 6 ++ 17 files changed, 186 insertions(+), 139 deletions(-) delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/initializer/AbstractInitializerTranslator.java create mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java create mode 100644 js/js.translator/testFiles/expression/misc/cases/extensionLiteralCreatedAtNamespaceLevel.kt create mode 100644 js/js.translator/testFiles/expression/misc/cases/funInConstructorBlock.kt create mode 100644 js/js.translator/testFiles/expression/misc/cases/namespacePropertyCalledAsFun.kt create mode 100644 js/js.translator/testFiles/expression/misc/cases/temporaryVariableCreatedInNamespaceInitializer.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java index b0d45f22385..df9da889db9 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java @@ -93,7 +93,23 @@ public final class MiscTest extends AbstractExpressionTest { checkFooBoxIsTrue("funInConstructor.kt"); } + public void testFunInConstructorBlock() throws Exception { + checkFooBoxIsTrue("funInConstructorBlock.kt"); + } + public void testPropertyAsFunCalledOnConstructor() throws Exception { checkFooBoxIsTrue("propertyAsFunCalledOnConstructor.kt"); } + + public void testNamespacePropertyCalledAsFun() throws Exception { + checkFooBoxIsTrue("namespacePropertyCalledAsFun.kt"); + } + + public void testExtensionLiteralCreatedAtNamespaceLevel() throws Exception { + checkFooBoxIsTrue("extensionLiteralCreatedAtNamespaceLevel.kt"); + } + + public void testTemporaryVariableCreatedInNamespaceInitializer() throws Exception { + checkFooBoxIsTrue("temporaryVariableCreatedInNamespaceInitializer.kt"); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java index 3538df77839..ace277b175d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java @@ -26,54 +26,48 @@ public class DynamicContext { @NotNull public static DynamicContext rootContext(@NotNull NamingScope rootScope, @NotNull JsBlock globalBlock) { - return new DynamicContext(rootScope, rootScope, globalBlock); + return new DynamicContext(rootScope, globalBlock); } @NotNull - public static DynamicContext contextWithScope(@NotNull NamingScope scope) { - return new DynamicContext(scope, scope, new JsBlock()); + public static DynamicContext newContext(@NotNull NamingScope scope, @NotNull JsBlock block) { + return new DynamicContext(scope, block); } - //TODO: current/block scope logic unclear. is it necessary? @NotNull private final NamingScope currentScope; - @NotNull - private final NamingScope blockScope; - @NotNull private final JsBlock currentBlock; - private DynamicContext(@NotNull NamingScope scope, @NotNull NamingScope blockScope, @NotNull JsBlock block) { + private DynamicContext(@NotNull NamingScope scope, @NotNull JsBlock block) { this.currentScope = scope; this.currentBlock = block; - this.blockScope = blockScope; - } - - @NotNull - public DynamicContext innerScope(@NotNull JsScope scope) { - return new DynamicContext(currentScope.innerScope(scope), blockScope, currentBlock); } @NotNull public DynamicContext innerBlock(@NotNull JsBlock block) { - return new DynamicContext(currentScope, currentScope, block); + return new DynamicContext(currentScope, block); } @NotNull public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) { - JsName temporaryName = blockScope.declareTemporary(); + JsName temporaryName = currentScope.declareTemporary(); JsVars temporaryDeclaration = newVar(temporaryName, /*no init expression in var statement*/ null); addVarDeclaration(jsBlock(), temporaryDeclaration); return new TemporaryVariable(temporaryName, initExpression); } - @NotNull public JsScope jsScope() { return currentScope.jsScope(); } + @NotNull + public NamingScope getScope() { + return currentScope; + } + @NotNull public JsBlock jsBlock() { return currentBlock; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index 5e24fd58b9c..1602554cc5e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -27,6 +27,7 @@ import org.jetbrains.k2js.translate.context.generator.Generator; import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; +import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.PredefinedAnnotation; import java.util.Map; @@ -84,7 +85,6 @@ public final class StaticContext { private final Generator qualifiers = new QualifierGenerator(); @NotNull private final Generator qualifierIsNull = new QualifierIsNullGenerator(); - @NotNull private final Map scopeToFunction = Maps.newHashMap(); @@ -135,7 +135,7 @@ public final class StaticContext { @NotNull public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { - NamingScope namingScope = scopes.get(descriptor); + NamingScope namingScope = scopes.get(descriptor.getOriginal()); assert namingScope != null : "Must have a scope for descriptor"; return namingScope; } @@ -337,8 +337,9 @@ public final class StaticContext { return null; } NamingScope enclosingScope = getEnclosingScope(descriptor); - JsFunction correspondingFunction = new JsFunction(enclosingScope.jsScope()); + JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(enclosingScope.jsScope()); NamingScope newScope = enclosingScope.innerScope(correspondingFunction.getScope()); + assert (!scopeToFunction.containsKey(newScope)) : "Scope to function value overriden for " + descriptor; scopeToFunction.put(newScope, correspondingFunction); return newScope; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java index c4550def09b..d55d61bb2c7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java @@ -53,14 +53,8 @@ public final class TranslationContext { } @NotNull - public TranslationContext contextWithScope(@NotNull NamingScope newScope) { - return new TranslationContext(staticContext, DynamicContext.contextWithScope(newScope)); - } - - // Note: Should be used ONLY if scope has no corresponding descriptor - @NotNull - public TranslationContext innerJsScope(@NotNull JsScope enclosingScope) { - return new TranslationContext(staticContext, dynamicContext.innerScope(enclosingScope)); + public TranslationContext contextWithScope(@NotNull NamingScope newScope, @NotNull JsBlock block) { + return new TranslationContext(staticContext, DynamicContext.newContext(newScope, block)); } @NotNull @@ -70,7 +64,23 @@ public final class TranslationContext { @NotNull public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) { - return contextWithScope(getScopeForDescriptor(descriptor)); + return contextWithScope(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor)); + } + + //TODO: consider passing a function here + @NotNull + public TranslationContext innerContextWithGivenScopeAndBlock(@NotNull JsScope scope, @NotNull JsBlock block) { + return contextWithScope(dynamicContext.getScope().innerScope(scope), block); + } + + @NotNull + public JsBlock getBlockForDescriptor(@NotNull DeclarationDescriptor descriptor) { + if (descriptor instanceof CallableDescriptor) { + return getFunctionObject((CallableDescriptor) descriptor).getBody(); + } + else { + return new JsBlock(); + } } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java index 00ed05c5ea8..aef94dd94e1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java @@ -125,7 +125,7 @@ public final class PropertyTranslator extends AbstractTranslator { private JsFunction generateDefaultGetterFunction(@NotNull PropertyGetterDescriptor descriptor) { JsReturn returnExpression = new JsReturn(backingFieldReference(context(), property)); JsFunction getterFunction = context().getFunctionObject(descriptor); - getterFunction.setBody(convertToBlock(returnExpression)); + getterFunction.getBody().getStatements().add(returnExpression); return getterFunction; } @@ -144,7 +144,7 @@ public final class PropertyTranslator extends AbstractTranslator { new JsParameter(propertyAccessContext(propertySetterDescriptor).jsScope().declareTemporary()); JsStatement assignment = assignmentToBackingField(context(), property, defaultParameter.getName().makeRef()).makeStmt(); setParameters(result, defaultParameter); - result.setBody(convertToBlock(assignment)); + result.getBody().getStatements().add(assignment); return result; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java index 5057622d53b..1b0402c4d12 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java @@ -52,6 +52,8 @@ import static org.jetbrains.k2js.translate.utils.mutator.LastExpressionMutator.m /** * @author Pavel Talanov */ + +//TODO: class has convoluted code. REFACTOR before changing public final class FunctionTranslator extends AbstractTranslator { @NotNull @@ -75,10 +77,10 @@ public final class FunctionTranslator extends AbstractTranslator { private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration, @NotNull TranslationContext context) { super(context); - this.functionBody = new JsBlock(); this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration); this.functionDeclaration = functionDeclaration; - this.functionObject = createFunctionObject(); + this.functionObject = context().getFunctionObject(descriptor); + this.functionBody = functionObject.getBody(); this.functionBodyContext = functionBodyContext().innerBlock(functionBody); } @@ -147,7 +149,6 @@ public final class FunctionTranslator extends AbstractTranslator { private void generateFunctionObject() { setParameters(functionObject, translateParameters()); translateBody(); - functionObject.setBody(functionBody); restoreContext(); } @@ -159,11 +160,6 @@ public final class FunctionTranslator extends AbstractTranslator { } } - @NotNull - private JsFunction createFunctionObject() { - return context().getFunctionObject(descriptor); - } - private void translateBody() { JetExpression jetBodyExpression = functionDeclaration.getBodyExpression(); if (jetBodyExpression == null) { @@ -203,12 +199,7 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull private TranslationContext functionBodyContext() { - if (isLiteral()) { - return context().innerJsScope(functionObject.getScope()); - } - else { - return context().newDeclaration(functionDeclaration); - } + return context().newDeclaration(functionDeclaration); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java index 55dae894c54..b9164a722cc 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -100,13 +100,15 @@ public final class Translation { @NotNull public static JsPropertyInitializer generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - return (new ClassInitializerTranslator(classDeclaration, context)).generateInitializeMethod(); + final ClassInitializerTranslator classInitializerTranslator = new ClassInitializerTranslator(classDeclaration, context); + return classInitializerTranslator.generateInitializeMethod(); } @NotNull public static JsPropertyInitializer generateNamespaceInitializerMethod(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) { - return (new NamespaceInitializerTranslator(namespace, context)).generateInitializeMethod(); + final NamespaceInitializerTranslator namespaceInitializerTranslator = new NamespaceInitializerTranslator(namespace, context); + return namespaceInitializerTranslator.generateInitializeMethod(); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/AbstractInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/AbstractInitializerTranslator.java deleted file mode 100644 index 15d0a807b4b..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/AbstractInitializerTranslator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.k2js.translate.initializer; - -import com.google.dart.compiler.backend.js.ast.JsFunction; -import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; -import com.google.dart.compiler.backend.js.ast.JsStatement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.k2js.translate.context.Namer; -import org.jetbrains.k2js.translate.context.NamingScope; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.general.AbstractTranslator; - -import java.util.List; - -/** - * @author Pavel Talanov - */ -public abstract class AbstractInitializerTranslator extends AbstractTranslator { - - @NotNull - private final InitializerVisitor visitor; - @NotNull - protected final NamingScope initializerMethodScope; - - protected AbstractInitializerTranslator(@NotNull NamingScope scope, @NotNull TranslationContext context) { - super(context.contextWithScope(scope)); - this.visitor = new InitializerVisitor(); - this.initializerMethodScope = scope; - } - - abstract protected JsFunction generateInitializerFunction(); - - @NotNull - public JsPropertyInitializer generateInitializeMethod() { - JsPropertyInitializer initializer = new JsPropertyInitializer(); - initializer.setLabelExpr(Namer.initializeMethodReference()); - initializer.setValueExpr(generateInitializerFunction()); - return initializer; - } - - @NotNull - protected List translateClassInitializers(@NotNull JetClassOrObject declaration) { - return visitor.traverseClass(declaration, context()); - } - - @NotNull - protected List translateNamespaceInitializers(@NotNull NamespaceDescriptor namespace) { - return visitor.traverseNamespace(namespace, context()); - - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index 5c9065633e1..3db146a9563 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.general.AbstractTranslator; import java.util.ArrayList; import java.util.List; @@ -41,7 +42,7 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateArgum /** * @author Pavel Talanov */ -public final class ClassInitializerTranslator extends AbstractInitializerTranslator { +public final class ClassInitializerTranslator extends AbstractTranslator { @NotNull private final JetClassOrObject classDeclaration; @@ -51,13 +52,12 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { // Note: it's important we use scope for class descriptor because anonymous function used in property initializers // belong to the properties themselves - super(context.getScopeForDescriptor(getClassDescriptor(context.bindingContext(), classDeclaration)), context); + super(context.newDeclaration(getConstructor(context.bindingContext(), classDeclaration))); this.classDeclaration = classDeclaration; } - @Override @NotNull - protected JsFunction generateInitializerFunction() { + public JsPropertyInitializer generateInitializeMethod() { //TODO: it's inconsistent that we scope for class and function for constructor, currently have problems implementing better way ConstructorDescriptor primaryConstructor = getConstructor(bindingContext(), classDeclaration); JsFunction result = context().getFunctionObject(primaryConstructor); @@ -65,14 +65,9 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla // for properties declared as constructor parameters setParameters(result, translatePrimaryConstructorParameters()); mayBeAddCallToSuperMethod(); - result.setBody(generateInitializerMethodBody()); - return result; - } - - @NotNull - private JsBlock generateInitializerMethodBody() { - initializerStatements.addAll(translateClassInitializers(classDeclaration)); - return newBlock(initializerStatements); + initializerStatements.addAll((new InitializerVisitor()).traverseClass(classDeclaration, context())); + result.getBody().getStatements().addAll(initializerStatements); + return InitializerUtils.generateInitializeMethod(result); } private void mayBeAddCallToSuperMethod() { @@ -85,7 +80,7 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall) { //TODO: can be problematic to maintain - JsName superMethodName = initializerMethodScope.jsScope().declareName(Namer.superMethodName()); + JsName superMethodName = context().jsScope().declareName(Namer.superMethodName()); superMethodName.setObfuscatable(false); List arguments = translateArguments(superCall); initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments))); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java new file mode 100644 index 00000000000..8eb8589935a --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.translate.initializer; + +import com.google.dart.compiler.backend.js.ast.JsFunction; +import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.translate.context.Namer; +import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.general.AbstractTranslator; + +/** + * @author Pavel Talanov + */ +public final class InitializerUtils { + + private InitializerUtils() { + } + + @NotNull + public static JsPropertyInitializer generateInitializeMethod(@NotNull JsFunction initializerFunction) { + JsPropertyInitializer initializer = new JsPropertyInitializer(); + initializer.setLabelExpr(Namer.initializeMethodReference()); + initializer.setValueExpr(initializerFunction); + return initializer; + } + +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java index 206888a5d1b..923cb522cce 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java @@ -17,33 +17,39 @@ package org.jetbrains.k2js.translate.initializer; import com.google.dart.compiler.backend.js.ast.JsFunction; +import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; +import com.google.dart.compiler.backend.js.ast.JsStatement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.utils.JsAstUtils; -import static org.jetbrains.k2js.translate.utils.JsAstUtils.newBlock; +import java.util.List; /** * @author Pavel Talanov */ -public final class NamespaceInitializerTranslator extends AbstractInitializerTranslator { +public final class NamespaceInitializerTranslator { @NotNull private final NamespaceDescriptor namespace; + @NotNull + private final TranslationContext namespaceContext; public NamespaceInitializerTranslator(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) { - //NOTE: - super(context.getScopeForDescriptor(namespace), context); this.namespace = namespace; + this.namespaceContext = context; } - @Override @NotNull - protected JsFunction generateInitializerFunction() { - //NOTE: namespace has no constructor - JsFunction result = new JsFunction(initializerMethodScope.jsScope()); - result.setBody(newBlock(translateNamespaceInitializers(namespace))); - return result; + public JsPropertyInitializer generateInitializeMethod() { + JsFunction result = JsAstUtils.createFunctionWithEmptyBody(namespaceContext.jsScope()); + TranslationContext namespaceInitializerContext + = namespaceContext.innerContextWithGivenScopeAndBlock(result.getScope(), result.getBody()); + List initializerStatements = + (new InitializerVisitor()).traverseNamespace(namespace, namespaceInitializerContext); + result.getBody().getStatements().addAll(initializerStatements); + return InitializerUtils.generateInitializeMethod(result); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index e9e895f4679..70821648f5e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -347,7 +347,7 @@ public final class BindingUtils { return resolvedCall; } - public static ConstructorDescriptor getConstructor(BindingContext bindingContext, + public static ConstructorDescriptor getConstructor(@NotNull BindingContext bindingContext, @NotNull JetClassOrObject declaration) { ConstructorDescriptor primaryConstructor = getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor(); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java index 11d46e3e663..f2b19b49f23 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java @@ -264,4 +264,11 @@ public final class JsAstUtils { } return result; } + + @NotNull + public static JsFunction createFunctionWithEmptyBody(@NotNull JsScope parent) { + JsFunction correspondingFunction = new JsFunction(parent); + correspondingFunction.setBody(new JsBlock()); + return correspondingFunction; + } } diff --git a/js/js.translator/testFiles/expression/misc/cases/extensionLiteralCreatedAtNamespaceLevel.kt b/js/js.translator/testFiles/expression/misc/cases/extensionLiteralCreatedAtNamespaceLevel.kt new file mode 100644 index 00000000000..1f1bbb2117c --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/extensionLiteralCreatedAtNamespaceLevel.kt @@ -0,0 +1,19 @@ +package foo + +class A() { + fun foo() = 1 + fun a(f : A.()->Int) : Int { + return f() + } +} + +var d = 0 + +val p : A.()->Int = { + d = foo() + d++ +} + +val c = A().a(p) + +fun box() = (c == 1) diff --git a/js/js.translator/testFiles/expression/misc/cases/funInConstructorBlock.kt b/js/js.translator/testFiles/expression/misc/cases/funInConstructorBlock.kt new file mode 100644 index 00000000000..34fab35d9b8 --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/funInConstructorBlock.kt @@ -0,0 +1,19 @@ +package foo + +class A() { + + fun lold() = true + val p : ()->Boolean + { + $p = {{lold()}()} + } +} + + +fun box() : Boolean { + return A().p() +} + +fun main(arg : Array) { + println(box()) +} \ No newline at end of file diff --git a/js/js.translator/testFiles/expression/misc/cases/namespacePropertyCalledAsFun.kt b/js/js.translator/testFiles/expression/misc/cases/namespacePropertyCalledAsFun.kt new file mode 100644 index 00000000000..b148cb89d2b --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/namespacePropertyCalledAsFun.kt @@ -0,0 +1,7 @@ +package foo + +fun lold() = true + +val p = {{lold()}()} + +fun box() = p() && foo.p() \ No newline at end of file diff --git a/js/js.translator/testFiles/expression/misc/cases/temporaryVariableCreatedInNamespaceInitializer.kt b/js/js.translator/testFiles/expression/misc/cases/temporaryVariableCreatedInNamespaceInitializer.kt new file mode 100644 index 00000000000..e18f4dc7784 --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/temporaryVariableCreatedInNamespaceInitializer.kt @@ -0,0 +1,6 @@ +package foo + +var p = 0 +val c = p++ // creates temporary value + +fun box() = (p == 1) && (c == 0) \ No newline at end of file