diff --git a/translator/src/org/jetbrains/k2js/declarations/DeclarationExtractor.java b/translator/src/org/jetbrains/k2js/declarations/Declarations.java similarity index 74% rename from translator/src/org/jetbrains/k2js/declarations/DeclarationExtractor.java rename to translator/src/org/jetbrains/k2js/declarations/Declarations.java index c9d9dd2c13c..4aa19b139ce 100644 --- a/translator/src/org/jetbrains/k2js/declarations/DeclarationExtractor.java +++ b/translator/src/org/jetbrains/k2js/declarations/Declarations.java @@ -11,19 +11,22 @@ import java.util.Map; /** * @author Talanov Pavel */ -public final class DeclarationExtractor { +public final class Declarations { private final Map descriptorToScopeMap = new HashMap(); private final Map descriptorToNameMap = new HashMap(); - public DeclarationExtractor() { + private Declarations() { } - public void extractDeclarations(@NotNull DeclarationDescriptor descriptor, JsScope rootScope) { - ExtractionVisitor visitor = new ExtractionVisitor(this); + @NotNull + static public Declarations extractDeclarations(@NotNull DeclarationDescriptor descriptor, JsScope rootScope) { + Declarations declarations = new Declarations(); + ExtractionVisitor visitor = new ExtractionVisitor(declarations); descriptor.accept(visitor, rootScope); + return declarations; } @NotNull @@ -40,6 +43,10 @@ public final class DeclarationExtractor { return name; } + public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { + return descriptorToNameMap.containsKey(descriptor); + } + /*package*/ void putScope(@NotNull DeclarationDescriptor descriptor, @NotNull JsScope scope) { descriptorToScopeMap.put(descriptor, scope); } diff --git a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java b/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java index 02880fa7949..4e16bf9dea6 100644 --- a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java +++ b/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java @@ -13,32 +13,58 @@ import org.jetbrains.k2js.translate.Namer; public final class ExtractionVisitor extends DeclarationDescriptorVisitor { @NotNull - private final DeclarationExtractor extractor; + private final Declarations declarations; - /*package*/ ExtractionVisitor(@NotNull DeclarationExtractor extractor) { - this.extractor = extractor; + /*package*/ ExtractionVisitor(@NotNull Declarations declarations) { + this.declarations = declarations; } - @Override public Void visitClassDescriptor(@NotNull ClassDescriptor descriptor, @NotNull JsScope enclosingScope) { + JsScope classScope = extractClassDeclarations(descriptor, enclosingScope); + visitClassMembers(descriptor, classScope); + return null; + } + + @NotNull + private JsScope extractClassDeclarations(@NotNull ClassDescriptor descriptor, @NotNull JsScope enclosingScope) { String className = descriptor.getName(); - extractor.putName(descriptor, enclosingScope.declareName(className)); + declarations.putName(descriptor, enclosingScope.declareName(className)); JsScope classScope = new JsScope(enclosingScope, "class " + className); - extractor.putScope(descriptor, classScope); + declarations.putScope(descriptor, classScope); + return classScope; + } + + private void visitClassMembers(@NotNull ClassDescriptor descriptor, @NotNull JsScope classScope) { + visitClassConstructor(descriptor, classScope); for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { memberDescriptor.accept(this, classScope); } + } + + private void visitClassConstructor(@NotNull ClassDescriptor descriptor, @NotNull JsScope classScope) { + for (ConstructorDescriptor constructorDescriptor : descriptor.getConstructors()) { + constructorDescriptor.accept(this, classScope); + } + } + + //TODO: think about the ways to make this less hacky + //For now constructor just references the name of the class. Initialize method scope is defined independently. + @Override + public Void visitConstructorDescriptor(@NotNull ConstructorDescriptor descriptor, @NotNull JsScope enclosingScope) { + String className = descriptor.getContainingDeclaration().getName(); + JsName alreadyDeclaredClassName = enclosingScope.findExistingName(className); + declarations.putName(descriptor, alreadyDeclaredClassName); return null; } @Override public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull JsScope enclosingScope) { String functionName = descriptor.getName(); - extractor.putName(descriptor, enclosingScope.declareName(functionName)); + declarations.putName(descriptor, enclosingScope.declareName(functionName)); JsScope functionScope = new JsScope(enclosingScope, "function " + functionName); - extractor.putScope(descriptor, functionScope); + declarations.putScope(descriptor, functionScope); return null; } @@ -59,23 +85,35 @@ public final class ExtractionVisitor extends DeclarationDescriptorVisitor { return Translation.operationTranslator(context).translate(expression); } - - //TODO support other cases - @Override - @NotNull - public JsNode visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, - @NotNull TranslationContext context) { - - //TODO: this is only a hack for now - // Problem is that namespace properties do not generate getters and setter actually so they must be referenced - // by name - JsName referencedName = getReferencedName(expression, context); - if (referencedName != null) { - if (requiresNamespaceQualifier(context, referencedName)) { - return context.getNamespaceQualifiedReference(referencedName); - } - JsNameRef nameRef = referencedName.makeRef(); - if (requiresThisQualifier(expression, context)) { - nameRef.setQualifier(new JsThisRef()); - } - return nameRef; - } - - JsInvocation getterCall = Translation.propertyAccessTranslator(context).resolveAsPropertyGet(expression); - if (getterCall != null) { - return getterCall; - } - throw new AssertionError("Undefined name in this scope: " + expression.getReferencedName()); - } - - private boolean requiresNamespaceQualifier(TranslationContext context, JsName referencedName) { - return context.namespaceScope().ownsName(referencedName); - } - - private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression, - @NotNull TranslationContext context) { - boolean isClassMember = context.classScope().ownsName(getReferencedName(expression, context)); - boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; - return isClassMember || isBackingFieldAccess; - } - - @Nullable - private JsName getReferencedName(@NotNull JetSimpleNameExpression expression, @NotNull TranslationContext context) { - String referencedName = expression.getReferencedName(); - return context.enclosingScope().findExistingName(referencedName); - } - @Override @NotNull // assume it is a local variable declaration @@ -182,9 +135,16 @@ public final class ExpressionVisitor extends TranslatorVisitor { } else { return translateAsConditionalExpression(expression, context); } - } + @Override + @NotNull + public JsNode visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, + @NotNull TranslationContext context) { + return Translation.referenceTranslator(context).translateSimpleName(expression); + } + + @NotNull private JsIf translateAsIfStatement(@NotNull JetIfExpression expression, @NotNull TranslationContext context) { @@ -373,7 +333,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { @NotNull public JsNode visitIsExpression(@NotNull JetIsExpression expression, @NotNull TranslationContext context) { - return Translation.typeOperationTranslator(context).translateIsExpression(expression); + return Translation.patternTranslator(context).translateIsExpression(expression); } @Override @@ -418,5 +378,12 @@ public final class ExpressionVisitor extends TranslatorVisitor { return new JsContinue(); } + @Override + @NotNull + public JsNode visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, + @NotNull TranslationContext context) { + return Translation.functionTranslator(context).translateAsLiteral(expression.getFunctionLiteral()); + } + } diff --git a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java index 798f043dada..510bc34c3ab 100644 --- a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java @@ -3,9 +3,7 @@ package org.jetbrains.k2js.translate; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import com.sun.istack.internal.NotNull; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetNamedFunction; -import org.jetbrains.jet.lang.psi.JetParameter; +import org.jetbrains.jet.lang.psi.*; import java.util.ArrayList; import java.util.List; @@ -25,43 +23,68 @@ public final class FunctionTranslator extends AbstractTranslator { } @NotNull - public JsStatement translateAsFunction(@NotNull JetNamedFunction jetFunction) { - JsName functionName = translationContext().namespaceScope().declareFreshName(jetFunction.getName()); - JsFunction function = generateFunctionObject(jetFunction); + public JsStatement translateAsFunctionDeclaration(@NotNull JetNamedFunction expression) { + JsName functionName = translationContext().getNameForElement(expression); + JsFunction function = generateFunctionObject(expression); return AstUtil.newAssignmentStatement (translationContext().getNamespaceQualifiedReference(functionName), function); } @NotNull - JsPropertyInitializer translateAsMethod(@NotNull JetNamedFunction jetFunction) { - JsName functionName = translationContext().namespaceScope().declareFreshName(jetFunction.getName()); - JsFunction function = generateFunctionObject(jetFunction); + JsPropertyInitializer translateAsMethod(@NotNull JetNamedFunction expression) { + JsName functionName = translationContext().getNameForElement(expression); + JsFunction function = generateFunctionObject(expression); return new JsPropertyInitializer(functionName.makeRef(), function); } @NotNull - private JsFunction generateFunctionObject(@NotNull JetNamedFunction jetFunction) { - JsFunction result = JsFunction.getAnonymousFunctionWithScope - (translationContext().getScopeForElement(jetFunction)); + JsFunction translateAsLiteral(@NotNull JetFunctionLiteral expression) { + return generateFunctionObject(expression); + } + + @NotNull + private JsFunction generateFunctionObject(@NotNull JetFunction jetFunction) { + JsFunction result = createFunctionObject(jetFunction); List jsParameters = translateParameters(jetFunction.getValueParameters(), result.getScope()); - JsNode jsBody = translateBody(jetFunction); + JsNode jsBody = translateBody(jetFunction, result.getScope()); result.setParameters(jsParameters); result.setBody(AstUtil.convertToBlock(jsBody)); return result; } + private JsFunction createFunctionObject(JetFunction function) { + if (function instanceof JetNamedFunction) { + return JsFunction.getAnonymousFunctionWithScope + (translationContext().getScopeForElement(function)); + } + if (function instanceof JetFunctionLiteral) { + return new JsFunction(translationContext().enclosingScope()); + } + throw new AssertionError("Unsupported type of function."); + } + @NotNull - private JsNode translateBody(@NotNull JetNamedFunction jetFunction) { - JetExpression jetBodyExpression = jetFunction.getBodyExpression(); - //TODO support them ffs - assert jetBodyExpression != null : "Function without body not supported at the moment"; - JsNode body = Translation.translateExpression(jetBodyExpression, translationContext().newFunction(jetFunction)); - if (jetFunction.hasBlockBody()) { + private JsStatement translateBody(@NotNull JetFunction function, @NotNull JsScope functionScope) { + JetExpression jetBodyExpression = function.getBodyExpression(); + //TODO decide if there are cases where this assert is illegal + assert jetBodyExpression != null : "Function without body not supported"; + JsNode body = Translation.translateExpression(jetBodyExpression, functionBodyContext(function, functionScope)); + if (function.hasBlockBody()) { return AstUtil.convertToBlock(body); } return AstUtil.convertToBlock(new JsReturn(AstUtil.convertToExpression(body))); } + private TranslationContext functionBodyContext(JetFunction function, JsScope functionScope) { + if (function instanceof JetNamedFunction) { + return translationContext().newFunctionDeclaration((JetNamedFunction) function); + } + if (function instanceof JetFunctionLiteral) { + return translationContext().newFunctionLiteral(functionScope); + } + throw new AssertionError("Unsupported type of function."); + } + @NotNull private List translateParameters(@NotNull List jetParameters, @NotNull JsScope functionScope) { diff --git a/translator/src/org/jetbrains/k2js/translate/GenerationState.java b/translator/src/org/jetbrains/k2js/translate/GenerationState.java index a04e6143a95..453369144ec 100644 --- a/translator/src/org/jetbrains/k2js/translate/GenerationState.java +++ b/translator/src/org/jetbrains/k2js/translate/GenerationState.java @@ -4,10 +4,11 @@ package org.jetbrains.k2js.translate; import com.google.dart.compiler.backend.js.ast.JsProgram; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.k2js.declarations.DeclarationExtractor; +import org.jetbrains.k2js.declarations.Declarations; import java.util.List; @@ -18,14 +19,14 @@ public final class GenerationState { } //TODO method too long - public JsProgram compileCorrectNamespaces(BindingContext bindingContext, List namespaces) { + @NotNull + public JsProgram compileCorrectNamespaces(@NotNull BindingContext bindingContext, @NotNull List namespaces) { //TODO hardcoded JsProgram result = new JsProgram("main"); JetNamespace namespace = namespaces.get(0); NamespaceDescriptor descriptor = BindingUtils.getNamespaceDescriptor(bindingContext, namespace); - DeclarationExtractor extractor = new DeclarationExtractor(); - extractor.extractDeclarations(descriptor, result.getRootScope()); - Translation.namespaceTranslator(TranslationContext.rootContext(result, bindingContext, extractor)) + Declarations declarations = Declarations.extractDeclarations(descriptor, result.getRootScope()); + Translation.namespaceTranslator(TranslationContext.rootContext(result, bindingContext, declarations)) .generateAst(namespace); return result; } diff --git a/translator/src/org/jetbrains/k2js/translate/NamespaceDeclarationVisitor.java b/translator/src/org/jetbrains/k2js/translate/NamespaceDeclarationVisitor.java index ee4dafc1451..be783500ff6 100644 --- a/translator/src/org/jetbrains/k2js/translate/NamespaceDeclarationVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/NamespaceDeclarationVisitor.java @@ -41,7 +41,7 @@ public class NamespaceDeclarationVisitor extends TranslatorVisitor @NotNull @Override public JsStatement visitNamedFunction(@NotNull JetNamedFunction expression, @NotNull TranslationContext context) { - return AstUtil.convertToStatement(Translation.functionTranslator(context).translateAsFunction(expression)); + return AstUtil.convertToStatement(Translation.functionTranslator(context).translateAsFunctionDeclaration(expression)); } } diff --git a/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java b/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java new file mode 100644 index 00000000000..12cda448210 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java @@ -0,0 +1,102 @@ +package org.jetbrains.k2js.translate; + +import com.google.dart.compiler.backend.js.ast.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lexer.JetTokens; + +/** + * @author Talanov Pavel + */ +public class ReferenceTranslator extends AbstractTranslator { + + @NotNull + static public ReferenceTranslator newInstance(@NotNull TranslationContext context) { + return new ReferenceTranslator(context); + } + + private ReferenceTranslator(@NotNull TranslationContext context) { + super(context); + } + + @NotNull + JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression) { + //TODO: this is only a hack for now + // Problem is that namespace properties do not generate getters and setter actually so they must be referenced + // by name + JsExpression result; + result = resolveAsGlobalReference(expression); + if (result != null) { + return result; + } + result = resolveAsLocalReference(expression); + if (result != null) { + return result; + } + JsInvocation getterCall = + Translation.propertyAccessTranslator(translationContext()).resolveAsPropertyGet(expression); + if (getterCall != null) { + return getterCall; + } + throw new AssertionError("Undefined name in this scope: " + expression.getReferencedName()); + + } + + @Nullable + private JsExpression resolveAsGlobalReference(@NotNull JetSimpleNameExpression expression) { + DeclarationDescriptor referencedDescriptor = + BindingUtils.getDescriptorForReferenceExpression(translationContext().bindingContext(), expression); + if (referencedDescriptor == null) { + return null; + } + if (!translationContext().isDeclared(referencedDescriptor)) { + return null; + } + JsName referencedName = translationContext().getNameForDescriptor(referencedDescriptor); + return generateCorrectReference(expression, referencedName); + } + + @Nullable + private JsExpression resolveAsLocalReference(@NotNull JetSimpleNameExpression expression) { + JsName localReferencedName = getLocalReferencedName(expression); + if (localReferencedName == null) { + return null; + } + return generateCorrectReference(expression, localReferencedName); + } + + @NotNull + private JsNameRef generateCorrectReference(@NotNull JetSimpleNameExpression expression, + @NotNull JsName referencedName) { + JsNameRef result; + if (requiresNamespaceQualifier(referencedName)) { + result = translationContext().getNamespaceQualifiedReference(referencedName); + } else { + result = referencedName.makeRef(); + if (requiresThisQualifier(expression)) { + result.setQualifier(new JsThisRef()); + } + } + return result; + } + + private boolean requiresNamespaceQualifier(@NotNull JsName referencedName) { + return translationContext().namespaceScope().ownsName(referencedName); + } + + private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression) { + boolean isClassMember = translationContext().classScope().ownsName(getLocalReferencedName(expression)); + boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; + return isClassMember || isBackingFieldAccess; + } + + @Nullable + private JsName getLocalReferencedName(@NotNull JetSimpleNameExpression expression) { + String referencedName = expression.getReferencedName(); + return translationContext().enclosingScope().findExistingName(referencedName); + } + + +} diff --git a/translator/src/org/jetbrains/k2js/translate/Translation.java b/translator/src/org/jetbrains/k2js/translate/Translation.java index a3e3d6c3f05..ee9cf594979 100644 --- a/translator/src/org/jetbrains/k2js/translate/Translation.java +++ b/translator/src/org/jetbrains/k2js/translate/Translation.java @@ -51,10 +51,15 @@ public final class Translation { } @NotNull - static public PatternTranslator typeOperationTranslator(@NotNull TranslationContext context) { + static public PatternTranslator patternTranslator(@NotNull TranslationContext context) { return PatternTranslator.newInstance(context); } + @NotNull + static public ReferenceTranslator referenceTranslator(@NotNull TranslationContext context) { + return ReferenceTranslator.newInstance(context); + } + @NotNull static public JsNode translateExpression(@NotNull JetExpression expression, @NotNull TranslationContext context) { return expressionTranslator(context).translate(expression); diff --git a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java index 7ae20bc999b..76244da762f 100644 --- a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java +++ b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.k2js.declarations.DeclarationExtractor; +import org.jetbrains.k2js.declarations.Declarations; /** * @author Talanov Pavel @@ -35,7 +35,7 @@ public final class TranslationContext { @NotNull public static TranslationContext rootContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext, - @NotNull DeclarationExtractor extractor) { + @NotNull Declarations extractor) { JsScope rootScope = program.getRootScope(); Scopes scopes = new Scopes(rootScope, rootScope, rootScope); return new TranslationContext(null, program, bindingContext, scopes, extractor); @@ -50,17 +50,17 @@ public final class TranslationContext { @Nullable private final JsName namespaceName; @NotNull - private final DeclarationExtractor extractor; + private final Declarations declarations; private TranslationContext(@Nullable JsName namespaceName, @NotNull JsProgram program, @NotNull BindingContext bindingContext, @NotNull Scopes scopes, - @NotNull DeclarationExtractor extractor) { + @NotNull Declarations declarations) { this.program = program; this.bindingContext = bindingContext; this.namespaceName = namespaceName; this.scopes = scopes; - this.extractor = extractor; + this.declarations = declarations; } @NotNull @@ -70,17 +70,17 @@ public final class TranslationContext { @NotNull public TranslationContext newNamespace(@NotNull NamespaceDescriptor descriptor) { - JsScope namespaceScope = extractor.getScope(descriptor); + JsScope namespaceScope = declarations.getScope(descriptor); JsName namespaceName = scopes.enclosingScope.findExistingName(descriptor.getName()); Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); } @NotNull public TranslationContext newBlock() { Scopes newScopes = new Scopes(new JsScope (scopes.enclosingScope, "Scope for a block"), scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); } @NotNull @@ -90,9 +90,9 @@ public final class TranslationContext { @NotNull public TranslationContext newClass(@NotNull ClassDescriptor descriptor) { - JsScope classScope = extractor.getScope(descriptor); + JsScope classScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); } @NotNull @@ -102,26 +102,32 @@ public final class TranslationContext { @NotNull public TranslationContext newPropertyAccess(@NotNull PropertyAccessorDescriptor descriptor) { - return newFunction(descriptor); + return newFunctionDeclaration(descriptor); } @NotNull - public TranslationContext newFunction(@NotNull JetNamedFunction declaration) { - return newFunction(BindingUtils.getFunctionDescriptor(bindingContext, declaration)); + public TranslationContext newFunctionDeclaration(@NotNull JetNamedFunction declaration) { + return newFunctionDeclaration(BindingUtils.getFunctionDescriptor(bindingContext, declaration)); } @NotNull - public TranslationContext newFunction(@NotNull FunctionDescriptor descriptor) { - JsScope functionScope = extractor.getScope(descriptor); + public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) { + JsScope functionScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); + } + + @NotNull + public TranslationContext newFunctionLiteral(@NotNull JsScope correspondingScope) { + Scopes newScopes = new Scopes(correspondingScope, scopes.classScope, scopes.namespaceScope); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); } // Note: Should be used if and only if scope has no corresponding descriptor @NotNull public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) { Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations); } @@ -165,7 +171,7 @@ public final class TranslationContext { @NotNull public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { - return extractor.getScope(descriptor); + return declarations.getScope(descriptor); } @NotNull @@ -176,7 +182,7 @@ public final class TranslationContext { @NotNull public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { - return extractor.getName(descriptor); + return declarations.getName(descriptor); } @NotNull @@ -191,4 +197,8 @@ public final class TranslationContext { assert descriptor != null : "Element should have a descriptor"; return descriptor; } + + public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { + return declarations.isDeclared(descriptor); + } } diff --git a/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java index b0de57c306f..9f71f74af2e 100644 --- a/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java @@ -151,7 +151,7 @@ public class WhenTranslator extends AbstractTranslator { @NotNull private JsExpression translatePatternCondition(@NotNull JetWhenConditionIsPattern condition) { - JsExpression patternMatchExpression = Translation.typeOperationTranslator(translationContext()). + JsExpression patternMatchExpression = Translation.patternTranslator(translationContext()). translatePattern(getPattern(condition), expressionToMatch); if (condition.isNegated()) { return AstUtil.negated(patternMatchExpression); diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java index ad96579343a..e37f46b64eb 100644 --- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java +++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java @@ -23,4 +23,9 @@ public class FunctionTest extends AbstractExpressionTest { public void functionWithTwoParametersCall() throws Exception { testFooBoxIsTrue("functionWithTwoParametersCall.kt"); } + + @Test + public void functionLiteral() throws Exception { + testFooBoxIsTrue("functionLiteral.kt"); + } } diff --git a/translator/testFiles/expression/function/cases/functionLiteral.kt b/translator/testFiles/expression/function/cases/functionLiteral.kt new file mode 100644 index 00000000000..b0eefc30f42 --- /dev/null +++ b/translator/testFiles/expression/function/cases/functionLiteral.kt @@ -0,0 +1,8 @@ +namespace foo + +fun box() : Boolean { + var sum = 0 + val addFive = {(a: Int) => a + 5 } + sum = addFive(sum) + return sum == 5 +} \ No newline at end of file