Rewrote name resolving logic. Improved DeclarationExtractor and renamed to Declarations.
This commit is contained in:
+11
-4
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user