Rewrote name resolving logic. Improved DeclarationExtractor and renamed to Declarations.

This commit is contained in:
Pavel Talanov
2011-11-18 16:12:14 +04:00
parent f06fa3c295
commit 694902103d
13 changed files with 285 additions and 113 deletions
@@ -11,19 +11,22 @@ import java.util.Map;
/**
* @author Talanov Pavel
*/
public final class DeclarationExtractor {
public final class Declarations {
private final Map<DeclarationDescriptor, JsScope> descriptorToScopeMap
= new HashMap<DeclarationDescriptor, JsScope>();
private final Map<DeclarationDescriptor, JsName> descriptorToNameMap
= new HashMap<DeclarationDescriptor, JsName>();
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);
}
@@ -13,32 +13,58 @@ import org.jetbrains.k2js.translate.Namer;
public final class ExtractionVisitor extends DeclarationDescriptorVisitor<Void, JsScope> {
@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<Void,
String accessorName = Namer.getNameForAccessor(propertyName, isGetter);
JsName jsName = enclosingScope.declareName(accessorName);
JsScope accessorScope = new JsScope(enclosingScope, (isGetter ? "getter " : "setter ") + propertyName);
extractor.putScope(descriptor, accessorScope);
extractor.putName(descriptor, jsName);
// Note : We do not put backing field name into extractor because it can't be referenced from outside
declarations.putScope(descriptor, accessorScope);
declarations.putName(descriptor, jsName);
// Note : We do not put backing field name into declarations because it can't be referenced from outside
//TODO: find if there is repetetive code like descriptor.getCorrespondingProperty().getName())
accessorScope.declareName(Namer.getKotlinBackingFieldName(descriptor.getCorrespondingProperty().getName()));
}
@Override
public Void visitNamespaceDescriptor(NamespaceDescriptor descriptor, JsScope enclosingScope) {
JsScope namespaceScope = extractNamespaceDeclaration(descriptor, enclosingScope);
visitMemberDeclarations(descriptor, namespaceScope);
return null;
}
@NotNull
private JsScope extractNamespaceDeclaration(@NotNull NamespaceDescriptor descriptor,
@NotNull JsScope enclosingScope) {
String namespaceName = descriptor.getName();
extractor.putName(descriptor, enclosingScope.declareName(namespaceName));
declarations.putName(descriptor, enclosingScope.declareName(namespaceName));
JsScope namespaceScope = new JsScope(enclosingScope, "namespace " + namespaceName);
extractor.putScope(descriptor, namespaceScope);
declarations.putScope(descriptor, namespaceScope);
return namespaceScope;
}
private void visitMemberDeclarations(@NotNull NamespaceDescriptor descriptor, @NotNull JsScope namespaceScope) {
for (DeclarationDescriptor memberDescriptor :
descriptor.getMemberScope().getAllDescriptors()) {
memberDescriptor.accept(this, namespaceScope);
}
return null;
}
}
@@ -126,6 +126,12 @@ public final class BindingUtils {
return getClassDescriptorForType(getTypeByReference(context, typeReference));
}
@Nullable
static public DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
@NotNull JetReferenceExpression reference) {
return context.get(BindingContext.REFERENCE_TARGET, reference);
}
//TODO better implementation?
static private boolean isNotAny(@NotNull DeclarationDescriptor superClassDescriptor) {
return !superClassDescriptor.getName().equals("Any");
@@ -11,7 +11,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.NullValue;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
@@ -85,52 +84,6 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
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<JsNode> {
} 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<JsNode> {
@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<JsNode> {
return new JsContinue();
}
@Override
@NotNull
public JsNode visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression,
@NotNull TranslationContext context) {
return Translation.functionTranslator(context).translateAsLiteral(expression.getFunctionLiteral());
}
}
@@ -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<JsParameter> 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<JsParameter> translateParameters(@NotNull List<JetParameter> jetParameters,
@NotNull JsScope functionScope) {
@@ -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<JetNamespace> namespaces) {
@NotNull
public JsProgram compileCorrectNamespaces(@NotNull BindingContext bindingContext, @NotNull List<JetNamespace> 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;
}
@@ -41,7 +41,7 @@ public class NamespaceDeclarationVisitor extends TranslatorVisitor<JsStatement>
@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));
}
}
@@ -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);
}
}
@@ -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);
@@ -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);
}
}
@@ -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);
@@ -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");
}
}
@@ -0,0 +1,8 @@
namespace foo
fun box() : Boolean {
var sum = 0
val addFive = {(a: Int) => a + 5 }
sum = addFive(sum)
return sum == 5
}