Work on reference expression. Test fixes to follow.

This commit is contained in:
Pavel Talanov
2011-11-30 13:22:48 +04:00
parent ba767e7205
commit f8d342c207
11 changed files with 620 additions and 644 deletions
+427 -459
View File
File diff suppressed because it is too large Load Diff
@@ -74,7 +74,9 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
public Void visitConstructorDescriptor(@NotNull ConstructorDescriptor descriptor, public Void visitConstructorDescriptor(@NotNull ConstructorDescriptor descriptor,
@NotNull DeclarationContext context) { @NotNull DeclarationContext context) {
JsName alreadyDeclaredClassName = declarations.getName(descriptor.getContainingDeclaration()); JsName alreadyDeclaredClassName = declarations.getName(descriptor.getContainingDeclaration());
//already defined in
declarations.putName(descriptor, alreadyDeclaredClassName); declarations.putName(descriptor, alreadyDeclaredClassName);
declarations.putQualifier(descriptor, context.getQualifier());
return null; return null;
} }
@@ -108,7 +110,7 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
@Override @Override
public Void visitNamespaceDescriptor(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) { public Void visitNamespaceDescriptor(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
DeclarationContext namespaceContext = extractNamespaceDeclaration(descriptor, context); DeclarationContext namespaceContext = extractNamespaceDeclaration(descriptor, context);
visitMemberDeclarations(descriptor, namespaceContext); declareMembers(descriptor, namespaceContext);
return null; return null;
} }
@@ -129,7 +131,7 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
return name; return name;
} }
private void visitMemberDeclarations(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) { private void declareMembers(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
for (DeclarationDescriptor memberDescriptor : for (DeclarationDescriptor memberDescriptor :
descriptor.getMemberScope().getAllDescriptors()) { descriptor.getMemberScope().getAllDescriptors()) {
memberDescriptor.accept(this, context); memberDescriptor.accept(this, context);
@@ -62,17 +62,29 @@ public final class Declarations {
return name; return name;
} }
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { public boolean hasDeclaredName(@NotNull DeclarationDescriptor descriptor) {
return descriptorToNameMap.containsKey(descriptor.getOriginal()); return descriptorToNameMap.containsKey(descriptor.getOriginal());
} }
public boolean hasQualifier(@NotNull DeclarationDescriptor descriptor) {
return (descriptorToQualifierMap.get(descriptor) != null);
}
@NotNull
public JsNameRef getQualifier(@NotNull DeclarationDescriptor descriptor) {
JsNameRef qualifier = descriptorToQualifierMap.get(descriptor);
assert qualifier != null : "Cannot be null. Use hasQualifier to check.";
return qualifier;
}
/*package*/ void putScope(@NotNull DeclarationDescriptor descriptor, @NotNull JsScope scope) { /*package*/ void putScope(@NotNull DeclarationDescriptor descriptor, @NotNull JsScope scope) {
assert !descriptorToScopeMap.containsKey(descriptor) : "Already contains that key!"; assert !descriptorToScopeMap.containsKey(descriptor) : "Already contains that key!";
descriptorToScopeMap.put(descriptor, scope); descriptorToScopeMap.put(descriptor, scope);
} }
//TODO: decide what to do about function overriding
/*package*/ void putName(@NotNull DeclarationDescriptor descriptor, @NotNull JsName name) { /*package*/ void putName(@NotNull DeclarationDescriptor descriptor, @NotNull JsName name) {
assert !descriptorToNameMap.containsKey(descriptor) : "Already contains that key!"; // assert !descriptorToNameMap.containsKey(descriptor) : "Already contains that key!";
descriptorToNameMap.put(descriptor, name); descriptorToNameMap.put(descriptor, name);
} }
@@ -14,6 +14,7 @@ import org.jetbrains.k2js.translate.general.TranslatorVisitor;
import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator; import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator;
import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.List; import java.util.List;
@@ -142,7 +143,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull @NotNull
public JsNode visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, public JsNode visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return Translation.referenceTranslator(context).translateSimpleName(expression); return ReferenceTranslator.translateSimpleName(expression, context);
} }
@@ -98,7 +98,8 @@ public final class PatternTranslator extends AbstractTranslator {
(context().bindingContext(), typeReference); (context().bindingContext(), typeReference);
//TODO should reference class by full name here //TODO should reference class by full name here
JsName className = context().getNameForDescriptor(referencedClass); JsName className = context().getNameForDescriptor(referencedClass);
return context().getNamespaceQualifiedReference(className); assert TranslationUtils.hasQualifier(context(), referencedClass);
return TranslationUtils.getQualifiedReference(context(), referencedClass);
} }
@NotNull @NotNull
@@ -18,7 +18,6 @@ import org.jetbrains.k2js.translate.expression.WhenTranslator;
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator; import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
import org.jetbrains.k2js.translate.initializer.NamespaceInitializerTranslator; import org.jetbrains.k2js.translate.initializer.NamespaceInitializerTranslator;
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.BindingUtils;
/** /**
@@ -57,10 +56,10 @@ public final class Translation {
return PatternTranslator.newInstance(context); return PatternTranslator.newInstance(context);
} }
@NotNull // @NotNull
static public ReferenceTranslator referenceTranslator(@NotNull TranslationContext context) { // static public ReferenceTranslator referenceTranslator(@NotNull TranslationContext context) {
return ReferenceTranslator.newInstance(context); // return ReferenceTranslator.translateSimpleName(context);
} // }
@NotNull @NotNull
static public JsNode translateExpression(@NotNull JetExpression expression, @NotNull TranslationContext context) { static public JsNode translateExpression(@NotNull JetExpression expression, @NotNull TranslationContext context) {
@@ -1,13 +1,10 @@
package org.jetbrains.k2js.translate.general; package org.jetbrains.k2js.translate.general;
import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.JsProgram; import com.google.dart.compiler.backend.js.ast.JsProgram;
import com.google.dart.compiler.backend.js.ast.JsScope; import com.google.dart.compiler.backend.js.ast.JsScope;
import com.google.dart.compiler.util.AstUtil;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -45,7 +42,7 @@ public final class TranslationContext {
Namer namer = Namer.newInstance(rootScope); Namer namer = Namer.newInstance(rootScope);
Aliaser aliaser = Aliaser.aliasesForStandardClasses Aliaser aliaser = Aliaser.aliasesForStandardClasses
(JetStandardLibrary.getJetStandardLibrary(project), namer); (JetStandardLibrary.getJetStandardLibrary(project), namer);
return new TranslationContext(null, program, bindingContext, return new TranslationContext(program, bindingContext,
scopes, extractor, aliaser, namer); scopes, extractor, aliaser, namer);
} }
@@ -55,8 +52,6 @@ public final class TranslationContext {
private final BindingContext bindingContext; private final BindingContext bindingContext;
@NotNull @NotNull
private final Scopes scopes; private final Scopes scopes;
@Nullable
private final JsName namespaceName;
@NotNull @NotNull
private final Declarations declarations; private final Declarations declarations;
@NotNull @NotNull
@@ -65,13 +60,12 @@ public final class TranslationContext {
private final Namer namer; private final Namer namer;
private TranslationContext(@Nullable JsName namespaceName, @NotNull JsProgram program, private TranslationContext(@NotNull JsProgram program,
@NotNull BindingContext bindingContext, @NotNull Scopes scopes, @NotNull BindingContext bindingContext, @NotNull Scopes scopes,
@NotNull Declarations declarations, @NotNull Aliaser aliaser, @NotNull Declarations declarations, @NotNull Aliaser aliaser,
@NotNull Namer namer) { @NotNull Namer namer) {
this.program = program; this.program = program;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.namespaceName = namespaceName;
this.scopes = scopes; this.scopes = scopes;
this.declarations = declarations; this.declarations = declarations;
this.aliaser = aliaser; this.aliaser = aliaser;
@@ -86,9 +80,8 @@ public final class TranslationContext {
@NotNull @NotNull
public TranslationContext newNamespace(@NotNull NamespaceDescriptor descriptor) { public TranslationContext newNamespace(@NotNull NamespaceDescriptor descriptor) {
JsScope namespaceScope = declarations.getScope(descriptor); JsScope namespaceScope = declarations.getScope(descriptor);
JsName namespaceName = getNameForDescriptor(descriptor);
Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope); Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, return new TranslationContext(program, bindingContext, newScopes,
declarations, aliaser, namer); declarations, aliaser, namer);
} }
@@ -101,7 +94,7 @@ public final class TranslationContext {
public TranslationContext newClass(@NotNull ClassDescriptor descriptor) { public TranslationContext newClass(@NotNull ClassDescriptor descriptor) {
JsScope classScope = declarations.getScope(descriptor); JsScope classScope = declarations.getScope(descriptor);
Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope); Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, return new TranslationContext(program, bindingContext,
newScopes, declarations, aliaser, namer); newScopes, declarations, aliaser, namer);
} }
@@ -124,7 +117,7 @@ public final class TranslationContext {
public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) { public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) {
JsScope functionScope = declarations.getScope(descriptor); JsScope functionScope = declarations.getScope(descriptor);
Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope); Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, return new TranslationContext(program, bindingContext,
newScopes, declarations, aliaser, namer); newScopes, declarations, aliaser, namer);
} }
@@ -132,20 +125,10 @@ public final class TranslationContext {
@NotNull @NotNull
public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) { public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) {
Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope); Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, return new TranslationContext(program, bindingContext,
newScopes, declarations, aliaser, namer); newScopes, declarations, aliaser, namer);
} }
//TODO: move to namer
@NotNull
public JsNameRef getNamespaceQualifiedReference(@NotNull JsName name) {
if (namespaceName != null) {
return AstUtil.newNameRef(namespaceName.makeRef(), name);
}
return new JsNameRef(name);
}
@NotNull @NotNull
public BindingContext bindingContext() { public BindingContext bindingContext() {
return bindingContext; return bindingContext;
@@ -202,7 +185,7 @@ public final class TranslationContext {
} }
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) {
return declarations.isDeclared(descriptor); return declarations.hasDeclaredName(descriptor);
} }
@NotNull @NotNull
@@ -214,4 +197,9 @@ public final class TranslationContext {
public Namer namer() { public Namer namer() {
return namer; return namer;
} }
@NotNull
public Declarations declarations() {
return declarations;
}
} }
@@ -18,6 +18,7 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.general.TranslationContext;
import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
/** /**
* @author Talanov Pavel * @author Talanov Pavel
@@ -57,6 +58,7 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
return canBePropertyGetterCall(expression); return canBePropertyGetterCall(expression);
} }
//TODO: delete?
public boolean canBePropertySetterCall(@NotNull JetExpression expression) { public boolean canBePropertySetterCall(@NotNull JetExpression expression) {
if (expression instanceof JetQualifiedExpression) { if (expression instanceof JetQualifiedExpression) {
JetSimpleNameExpression selector = getNullableSelector((JetQualifiedExpression) expression); JetSimpleNameExpression selector = getNullableSelector((JetQualifiedExpression) expression);
@@ -91,10 +93,15 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsInvocation resolveAsPropertyGet(@NotNull JetSimpleNameExpression expression) { private JsInvocation resolveAsPropertyGet(@NotNull JetSimpleNameExpression expression) {
JsName getterName = getNotNullGetterName(expression); JsName getterName = getNotNullGetterName(expression);
JsNameRef getterReference = ReferenceProvider.getReference(getterName, context(), expression); JsNameRef getterReference = getAccessorReference(getterName);
return AstUtil.newInvocation(getterReference); return AstUtil.newInvocation(getterReference);
} }
@NotNull
private JsNameRef getAccessorReference(@NotNull JsName getterName) {
return TranslationUtils.getThisQualifiedNameReference(context(), getterName);
}
@NotNull @NotNull
public JsInvocation translateAsPropertySetterCall(@NotNull JetExpression expression) { public JsInvocation translateAsPropertySetterCall(@NotNull JetExpression expression) {
if (expression instanceof JetDotQualifiedExpression) { if (expression instanceof JetDotQualifiedExpression) {
@@ -115,7 +122,7 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsInvocation resolveAsPropertySet(@NotNull JetSimpleNameExpression expression) { private JsInvocation resolveAsPropertySet(@NotNull JetSimpleNameExpression expression) {
JsName setterName = getNotNullSetterName(expression); JsName setterName = getNotNullSetterName(expression);
JsNameRef setterReference = ReferenceProvider.getReference(setterName, context(), expression); JsNameRef setterReference = getAccessorReference(setterName);
return AstUtil.newInvocation(setterReference); return AstUtil.newInvocation(setterReference);
} }
@@ -1,74 +0,0 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.general.TranslationContext;
/**
* @author Talanov Pavel
*/
public final class ReferenceProvider {
@NotNull
private final TranslationContext context;
@NotNull
private final JsName referencedName;
private boolean isBackingFieldAccess;
private boolean requiresThisQualifier;
private boolean requiresNamespaceQualifier;
public static JsNameRef getReference(@NotNull JsName referencedName, @NotNull TranslationContext context,
boolean isBackingFieldAccess) {
return (new ReferenceProvider(referencedName, context, isBackingFieldAccess)).generateCorrectReference();
}
public static JsNameRef getReference(@NotNull JsName referencedName, @NotNull TranslationContext context,
JetSimpleNameExpression expression) {
boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
return (new ReferenceProvider(referencedName, context, isBackingFieldAccess))
.generateCorrectReference();
}
private ReferenceProvider(@NotNull JsName referencedName, @NotNull TranslationContext context,
boolean isBackingFieldAccess) {
this.context = context;
this.referencedName = referencedName;
this.isBackingFieldAccess = isBackingFieldAccess;
this.requiresThisQualifier = requiresThisQualifier();
this.requiresNamespaceQualifier = requiresNamespaceQualifier();
}
@NotNull
public JsNameRef generateCorrectReference() {
if (requiresNamespaceQualifier) {
return context.getNamespaceQualifiedReference(referencedName);
} else if (requiresThisQualifier) {
return thisQualifiedReference();
}
return referencedName.makeRef();
}
private JsNameRef thisQualifiedReference() {
if (!context.aliaser().hasAliasForThis()) {
return AstUtil.thisQualifiedReference(referencedName);
}
JsNameRef reference = referencedName.makeRef();
AstUtil.setQualifier(reference, context.aliaser().getAliasForThis());
return reference;
}
private boolean requiresNamespaceQualifier() {
return context.namespaceScope().ownsName(referencedName);
}
private boolean requiresThisQualifier() {
JsName name = context.enclosingScope().findExistingName(referencedName.getIdent());
boolean isClassMember = context.classScope().ownsName(name);
return isClassMember || isBackingFieldAccess;
}
}
@@ -1,13 +1,12 @@
package org.jetbrains.k2js.translate.reference; package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsInvocation;
import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.general.TranslationContext;
@@ -17,84 +16,119 @@ import org.jetbrains.k2js.translate.utils.TranslationUtils;
/** /**
* @author Talanov Pavel * @author Talanov Pavel
*/ */
//TODO: implement state
public class ReferenceTranslator extends AbstractTranslator { public class ReferenceTranslator extends AbstractTranslator {
@NotNull @NotNull
static public ReferenceTranslator newInstance(@NotNull TranslationContext context) { private final JetSimpleNameExpression simpleName;
return new ReferenceTranslator(context);
}
private ReferenceTranslator(@NotNull TranslationContext context) { @Nullable
super(context); private JsExpression result;
}
// TODO: refactor put the checks inside resolvers
@NotNull @NotNull
public JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression) { public static JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression,
JsExpression result = resolveAsAliasReference(expression); @NotNull TranslationContext context) {
if (result != null) return result; return (new ReferenceTranslator(expression, context)).translateSimpleName();
result = resolveAsPropertyAccess(expression);
if (result != null) return result;
result = resolveAsGlobalReference(expression);
if (result != null) return result;
result = resolveAsLocalReference(expression);
if (result != null) return result;
throw new AssertionError("Undefined name in this scope: " + expression.getReferencedName());
} }
@Nullable private ReferenceTranslator(@NotNull JetSimpleNameExpression expression, @NotNull TranslationContext context) {
private JsNameRef resolveAsAliasReference(@NotNull JetSimpleNameExpression expression) { super(context);
//TODO: decide if this code is meaningful this.simpleName = expression;
this.result = null;
}
@NotNull
public JsExpression translateSimpleName() {
tryResolveAsThisQualifiedExpression();
tryResolveAsAliasReference();
tryResolveAsPropertyAccess();
tryResolveAsGlobalReference();
tryResolveAsLocalReference();
if (result != null) {
return result;
}
throw new AssertionError("Undefined name in this scope: " + simpleName.getReferencedName());
}
private void tryResolveAsThisQualifiedExpression() {
if (alreadyResolved()) return;
DeclarationDescriptor referencedDescriptor = DeclarationDescriptor referencedDescriptor =
BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), expression); BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), simpleName);
if (referencedDescriptor == null) return null;
if (!context().aliaser().hasAliasForDeclaration(referencedDescriptor)) { if (referencedDescriptor == null) return;
return null; if (!context().isDeclared(referencedDescriptor)) return;
}
return context().aliaser().getAliasForDeclaration(referencedDescriptor);
}
@Nullable
private JsInvocation resolveAsPropertyAccess(@NotNull JetSimpleNameExpression expression) {
PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(context());
if (propertyAccessTranslator.canBePropertyGetterCall(expression)) {
return propertyAccessTranslator.translateAsPropertyGetterCall(expression);
}
return null;
}
@Nullable
private JsExpression resolveAsGlobalReference(@NotNull JetSimpleNameExpression expression) {
DeclarationDescriptor referencedDescriptor =
BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), expression);
if (referencedDescriptor == null) {
return null;
}
//TODO: think about the places where we should check for original descriptors
if (!context().isDeclared(referencedDescriptor)) {
return null;
}
JsName referencedName = context().getNameForDescriptor(referencedDescriptor); JsName referencedName = context().getNameForDescriptor(referencedDescriptor);
return ReferenceProvider.getReference(referencedName, context(), expression);
if (!requiresThisQualifier(simpleName, referencedName)) return;
result = TranslationUtils.getThisQualifiedNameReference(context(), referencedName);
} }
@Nullable private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression,
private JsExpression resolveAsLocalReference(@NotNull JetSimpleNameExpression expression) { @NotNull JsName referencedName) {
String name = expression.getReferencedName();
JsName name = context().enclosingScope().findExistingName(referencedName.getIdent());
boolean isClassMember = context().classScope().ownsName(name);
boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
return (isBackingFieldAccess || isClassMember);
}
private void tryResolveAsAliasReference() {
//TODO: decide if this code is meaningful
if (alreadyResolved()) return;
DeclarationDescriptor referencedDescriptor =
BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), simpleName);
if (referencedDescriptor == null) return;
if (!context().aliaser().hasAliasForDeclaration(referencedDescriptor)) return;
result = context().aliaser().getAliasForDeclaration(referencedDescriptor);
}
private boolean alreadyResolved() {
return result != null;
}
private void tryResolveAsPropertyAccess() {
if (alreadyResolved()) return;
PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(context());
if (!propertyAccessTranslator.canBePropertyGetterCall(simpleName)) return;
result = propertyAccessTranslator.translateAsPropertyGetterCall(simpleName);
}
private void tryResolveAsGlobalReference() {
if (alreadyResolved()) return;
DeclarationDescriptor referencedDescriptor =
BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), simpleName);
if (referencedDescriptor == null) return;
if (!context().isDeclared(referencedDescriptor)) return;
result = TranslationUtils.getQualifiedReference(context(), referencedDescriptor);
}
private void tryResolveAsLocalReference() {
if (alreadyResolved()) return;
String name = getReferencedName();
JsName localReferencedName = TranslationUtils.getLocalReferencedName(context(), name);
if (localReferencedName == null) return;
result = localReferencedName.makeRef();
}
@NotNull
private String getReferencedName() {
String name = simpleName.getReferencedName();
assert name != null : "SimpleNameExpression should reference a name"; assert name != null : "SimpleNameExpression should reference a name";
JsName localReferencedName = TranslationUtils.getLocalReferencedName return name;
(context(), name);
if (localReferencedName == null) {
return null;
}
return localReferencedName.makeRef();
} }
} }
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
@@ -14,7 +15,6 @@ import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.general.TranslationContext;
import org.jetbrains.k2js.translate.reference.ReferenceProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -68,20 +68,14 @@ public final class TranslationUtils {
static public JsNameRef backingFieldReference(@NotNull TranslationContext context, static public JsNameRef backingFieldReference(@NotNull TranslationContext context,
@NotNull JetProperty expression) { @NotNull JetProperty expression) {
JsName backingFieldName = getBackingFieldName(getPropertyName(expression), context); JsName backingFieldName = getBackingFieldName(getPropertyName(expression), context);
return generateReference(context, backingFieldName); return getThisQualifiedNameReference(context, backingFieldName);
} }
@NotNull @NotNull
static public JsNameRef backingFieldReference(@NotNull TranslationContext context, static public JsNameRef backingFieldReference(@NotNull TranslationContext context,
@NotNull PropertyDescriptor descriptor) { @NotNull PropertyDescriptor descriptor) {
JsName backingFieldName = getBackingFieldName(descriptor.getName(), context); JsName backingFieldName = getBackingFieldName(descriptor.getName(), context);
return generateReference(context, backingFieldName); return getThisQualifiedNameReference(context, backingFieldName);
}
@NotNull
private static JsNameRef generateReference(@NotNull TranslationContext context,
@NotNull JsName backingFieldName) {
return ReferenceProvider.getReference(backingFieldName, context, true);
} }
@NotNull @NotNull
@@ -130,4 +124,48 @@ public final class TranslationUtils {
JsNameRef backingFieldReference = backingFieldReference(context, descriptor); JsNameRef backingFieldReference = backingFieldReference(context, descriptor);
return AstUtil.newAssignmentStatement(backingFieldReference, parameter.getName().makeRef()); return AstUtil.newAssignmentStatement(backingFieldReference, parameter.getName().makeRef());
} }
public static boolean hasQualifier(@NotNull TranslationContext context, @NotNull DeclarationDescriptor descriptor) {
return context.declarations().hasQualifier(descriptor);
}
@NotNull
public static JsNameRef getQualifiedReference(@NotNull TranslationContext context,
@NotNull DeclarationDescriptor descriptor) {
JsName name = context.declarations().getName(descriptor);
JsNameRef reference = name.makeRef();
if (hasQualifier(context, descriptor)) {
JsNameRef qualifier = getQualifier(context, descriptor);
AstUtil.setQualifier(reference, qualifier);
}
return reference;
}
@NotNull
private static JsNameRef getQualifier(@NotNull TranslationContext context,
@NotNull DeclarationDescriptor descriptor) {
return context.declarations().getQualifier(descriptor);
}
@NotNull
public static JsNameRef getThisQualifiedNameReference(@NotNull TranslationContext context,
@NotNull JsName name) {
JsExpression qualifier = getThisQualifier(context);
JsNameRef reference = name.makeRef();
AstUtil.setQualifier(reference, qualifier);
return reference;
}
@NotNull
private static JsExpression getThisQualifier(@NotNull TranslationContext context) {
JsExpression qualifier;
if (context.aliaser().hasAliasForThis()) {
qualifier = context.aliaser().getAliasForThis();
} else {
qualifier = new JsThisRef();
}
return qualifier;
}
} }