implementing lazy initialization. working version (3 test fail)

This commit is contained in:
Pavel Talanov
2012-02-03 14:13:48 +04:00
parent 1b986b6d2b
commit 9fe011bf43
22 changed files with 233 additions and 589 deletions
@@ -3,7 +3,6 @@ package org.jetbrains.k2js.translate.context;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
public class DynamicContext { public class DynamicContext {
@@ -40,17 +39,6 @@ public class DynamicContext {
return new DynamicContext(currentScope, currentScope, block); return new DynamicContext(currentScope, currentScope, block);
} }
@NotNull
public JsName getLocalName(@NotNull DeclarationDescriptor descriptor) {
JsName name = currentScope.getName(descriptor);
assert name != null : descriptor.getName() + " is not declared. Use isDeclared to check.";
return name;
}
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) {
return currentScope.isDeclared(descriptor);
}
@NotNull @NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) { public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
JsName temporaryName = blockScope.declareTemporary(); JsName temporaryName = blockScope.declareTemporary();
@@ -59,11 +47,6 @@ public class DynamicContext {
return new TemporaryVariable(temporaryName, initExpression); return new TemporaryVariable(temporaryName, initExpression);
} }
@NotNull
public JsName declareLocalVariable(@NotNull DeclarationDescriptor descriptor) {
return currentScope.declareVariable(descriptor, descriptor.getName());
}
@NotNull @NotNull
public JsScope jsScope() { public JsScope jsScope() {
return currentScope.jsScope(); return currentScope.jsScope();
@@ -4,10 +4,6 @@ import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsScope; import com.google.dart.compiler.backend.js.ast.JsScope;
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 java.util.HashMap;
import java.util.Map;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -25,11 +21,6 @@ public final class NamingScope {
@Nullable @Nullable
private final NamingScope parent; private final NamingScope parent;
@NotNull
private final Map<DeclarationDescriptor, JsName> descriptorToNameMap =
new HashMap<DeclarationDescriptor, JsName>();
private NamingScope(@NotNull JsScope correspondingScope, @Nullable NamingScope parent) { private NamingScope(@NotNull JsScope correspondingScope, @Nullable NamingScope parent) {
this.scope = correspondingScope; this.scope = correspondingScope;
this.parent = parent; this.parent = parent;
@@ -46,29 +37,10 @@ public final class NamingScope {
return new NamingScope(correspondingScope, this); return new NamingScope(correspondingScope, this);
} }
@Nullable
public JsName getName(@NotNull DeclarationDescriptor descriptor) {
JsName name = descriptorToNameMap.get(descriptor);
if (name != null) return name;
if (parent != null) return parent.getName(descriptor);
return null;
}
@NotNull @NotNull
public JsName declareVariable(@NotNull DeclarationDescriptor descriptor, /*package*/ JsName declareUnobfuscatableName(@NotNull String name) {
@NotNull String name) { JsName declaredName = scope.declareName(name);
JsName declaredName = scope.declareName(mayBeObfuscateName(name, false)); declaredName.setObfuscatable(false);
descriptorToNameMap.put(descriptor, declaredName);
return declaredName;
}
@NotNull
public JsName declareVariable(@NotNull DeclarationDescriptor descriptor,
@NotNull String name, boolean obfuscateIfNotUnique) {
JsName declaredName = scope.declareName(mayBeObfuscateName(name, obfuscateIfNotUnique));
descriptorToNameMap.put(descriptor, declaredName);
return declaredName; return declaredName;
} }
@@ -98,12 +70,8 @@ public final class NamingScope {
} }
@NotNull @NotNull
public JsName declareVariable(@NotNull DeclarationDescriptor descriptor) { /*package*/ JsName declareObfuscatableName(@NotNull String name) {
return declareVariable(descriptor, descriptor.getName()); return scope.declareName(mayBeObfuscateName(name, true));
}
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) {
return (getName(descriptor.getOriginal()) != null);
} }
public JsName declareTemporary() { public JsName declareTemporary() {
@@ -1,15 +1,10 @@
package org.jetbrains.k2js.translate.context; package org.jetbrains.k2js.translate.context;
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.JsRootScope; import com.google.dart.compiler.backend.js.ast.JsRootScope;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.k2js.translate.context.declaration.DeclarationFacade;
import org.jetbrains.k2js.translate.context.declaration.Declarations;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
public class StaticContext { public class StaticContext {
@@ -21,11 +16,10 @@ public class StaticContext {
Namer namer = Namer.newInstance(jsRootScope); Namer namer = Namer.newInstance(jsRootScope);
Aliaser aliaser = Aliaser.newInstance(); Aliaser aliaser = Aliaser.newInstance();
NamingScope scope = NamingScope.rootScope(jsRootScope); NamingScope scope = NamingScope.rootScope(jsRootScope);
DeclarationFacade declarations = DeclarationFacade.createFacade(scope);
Intrinsics intrinsics = Intrinsics.standardLibraryIntrinsics(library); Intrinsics intrinsics = Intrinsics.standardLibraryIntrinsics(library);
StandardClasses standardClasses = StandardClasses standardClasses =
StandardClasses.bindImplementations(namer.getKotlinScope()); StandardClasses.bindImplementations(namer.getKotlinScope());
return new StaticContext(program, bindingContext, declarations, aliaser, return new StaticContext(program, bindingContext, aliaser,
namer, intrinsics, standardClasses, scope); namer, intrinsics, standardClasses, scope);
} }
@@ -35,9 +29,6 @@ public class StaticContext {
@NotNull @NotNull
private final BindingContext bindingContext; private final BindingContext bindingContext;
@NotNull
private final DeclarationFacade declarationFacade;
@NotNull @NotNull
private final Aliaser aliaser; private final Aliaser aliaser;
@@ -56,12 +47,11 @@ public class StaticContext {
//TODO: too many parameters in constructor //TODO: too many parameters in constructor
private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext, private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext,
@NotNull DeclarationFacade declarations, @NotNull Aliaser aliaser, @NotNull Aliaser aliaser,
@NotNull Namer namer, @NotNull Intrinsics intrinsics, @NotNull Namer namer, @NotNull Intrinsics intrinsics,
@NotNull StandardClasses standardClasses, @NotNull NamingScope rootScope) { @NotNull StandardClasses standardClasses, @NotNull NamingScope rootScope) {
this.program = program; this.program = program;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.declarationFacade = declarations;
this.aliaser = aliaser; this.aliaser = aliaser;
this.namer = namer; this.namer = namer;
this.intrinsics = intrinsics; this.intrinsics = intrinsics;
@@ -79,11 +69,6 @@ public class StaticContext {
return bindingContext; return bindingContext;
} }
@NotNull
public DeclarationFacade getDeclarationFacade() {
return declarationFacade;
}
@NotNull @NotNull
public Aliaser getAliaser() { public Aliaser getAliaser() {
return aliaser; return aliaser;
@@ -108,43 +93,4 @@ public class StaticContext {
public StandardClasses getStandardClasses() { public StandardClasses getStandardClasses() {
return standardClasses; return standardClasses;
} }
//TODO: consider using nullable return value instead
@NotNull
public JsName getGlobalName(@NotNull DeclarationDescriptor descriptor) {
for (Declarations declarations : declarationFacade.getAllDeclarations()) {
if (declarations.hasDeclaredName(descriptor)) {
return declarations.getName(descriptor);
}
}
throw new AssertionError("Use is declared method to check.");
}
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) {
for (Declarations declarations : declarationFacade.getAllDeclarations()) {
if (declarations.hasDeclaredName(descriptor)) {
return true;
}
}
return false;
}
@NotNull
public JsNameRef getQualifier(@NotNull DeclarationDescriptor descriptor) {
for (Declarations declarations : declarationFacade.getAllDeclarations()) {
if (declarations.hasQualifier(descriptor)) {
return declarations.getQualifier(descriptor);
}
}
throw new AssertionError("Use hasQualifier method to check.");
}
public boolean hasQualifier(@NotNull DeclarationDescriptor descriptor) {
for (Declarations declarations : declarationFacade.getAllDeclarations()) {
if (declarations.hasQualifier(descriptor)) {
return true;
}
}
return false;
}
} }
@@ -3,21 +3,21 @@ package org.jetbrains.k2js.translate.context;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
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.*;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor; import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.translate.context.declaration.DeclarationFacade; import org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils;
import org.jetbrains.k2js.translate.context.generator.Generator; import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.BindingUtils;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getContainingDeclaration; import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.*;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -32,7 +32,8 @@ public final class TranslationContext {
private final Generator<JsName> names = nameGenerator(); private final Generator<JsName> names = nameGenerator();
@NotNull @NotNull
private final Generator<NamingScope> scopes = scopeGenerator(); private final Generator<NamingScope> scopes = scopeGenerator();
@NotNull
private final Generator<JsNameRef> qualifiers = qualifierGenerator();
@NotNull @NotNull
public static TranslationContext rootContext(@NotNull StaticContext staticContext) { public static TranslationContext rootContext(@NotNull StaticContext staticContext) {
@@ -70,9 +71,7 @@ public final class TranslationContext {
@NotNull @NotNull
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) { public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) {
//TODO: chained call on static context suspicious return contextWithScope(getScopeForDescriptor(descriptor));
NamingScope declarationScope = staticContext.getDeclarationFacade().getKotlinDeclarations().getScope(descriptor);
return contextWithScope(declarationScope);
} }
@NotNull @NotNull
@@ -103,7 +102,9 @@ public final class TranslationContext {
@NotNull @NotNull
public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
return scopes.get(descriptor); NamingScope namingScope = scopes.get(descriptor);
assert namingScope != null : "Must have a scope for descriptor";
return namingScope;
} }
@NotNull @NotNull
@@ -112,20 +113,6 @@ public final class TranslationContext {
return getScopeForDescriptor(descriptorForElement); return getScopeForDescriptor(descriptorForElement);
} }
@NotNull
public JsNameRef getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) {
if (standardClasses().isStandardObject(descriptor)) {
return namer().kotlinObject();
}
return staticContext.getQualifier(descriptor);
}
public boolean hasQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) {
return (staticContext.hasQualifier(descriptor) ||
standardClasses().isStandardObject(descriptor));
}
@NotNull @NotNull
public JsName getNameForElement(@NotNull JetElement element) { public JsName getNameForElement(@NotNull JetElement element) {
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForElement(bindingContext(), element); DeclarationDescriptor descriptor = BindingUtils.getDescriptorForElement(bindingContext(), element);
@@ -137,18 +124,6 @@ public final class TranslationContext {
return dynamicContext.declareTemporary(initExpression); return dynamicContext.declareTemporary(initExpression);
} }
@NotNull
public JsName declareLocalVariable(@NotNull DeclarationDescriptor descriptor) {
return dynamicContext.declareLocalVariable(descriptor);
}
@NotNull
public JsName declareLocalVariable(@NotNull JetElement element) {
DeclarationDescriptor declarationDescriptor =
BindingUtils.getDescriptorForElement(bindingContext(), element);
return dynamicContext.declareLocalVariable(declarationDescriptor);
}
@NotNull @NotNull
public Aliaser aliaser() { public Aliaser aliaser() {
return staticContext.getAliaser(); return staticContext.getAliaser();
@@ -184,20 +159,17 @@ public final class TranslationContext {
return dynamicContext.jsBlock(); return dynamicContext.jsBlock();
} }
@NotNull
public DeclarationFacade declarationFacade() {
return staticContext.getDeclarationFacade();
}
@NotNull @NotNull
public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
return names.get(descriptor); JsName name = names.get(descriptor.getOriginal());
assert name != null : "Must have name for descriptor";
return name;
} }
@NotNull @NotNull
private Generator<JsName> nameGenerator() { private Generator<JsName> nameGenerator() {
Generator<JsName> nameGenerator = new Generator<JsName>();
nameGenerator.addRule(new Rule<JsName>() { Rule<JsName> aliasOverridesNames = new Rule<JsName>() {
@Override @Override
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor data) { public JsName apply(@NotNull DeclarationDescriptor data) {
@@ -206,8 +178,8 @@ public final class TranslationContext {
} }
return null; return null;
} }
}); };
nameGenerator.addRule(new Rule<JsName>() { Rule<JsName> namesForStandardClasses = new Rule<JsName>() {
@Override @Override
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor data) { public JsName apply(@NotNull DeclarationDescriptor data) {
@@ -216,30 +188,89 @@ public final class TranslationContext {
} }
return standardClasses().getStandardObjectName(data); return standardClasses().getStandardObjectName(data);
} }
}); };
nameGenerator.addRule(new Rule<JsName>() { Rule<JsName> namespacesShouldBeDefinedInRootScope = new Rule<JsName>() {
@Override @Override
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) { public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (dynamicContext.isDeclared(descriptor)) { if (!(descriptor instanceof NamespaceDescriptor)) {
return dynamicContext.getLocalName(descriptor); return null;
} }
return null; String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor);
return staticContext.getRootScope().declareUnobfuscatableName(nameForNamespace);
} }
}); };
nameGenerator.addRule(new Rule<JsName>() { Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
@Override @Override
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) { public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (staticContext.isDeclared(descriptor)) { NamingScope namingScope = getEnclosingScope(descriptor);
return staticContext.getGlobalName(descriptor); return namingScope.declareObfuscatableName(descriptor.getName());
}
};
Rule<JsName> constructorHasTheSameNameAsTheClass = new Rule<JsName>() {
@Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ConstructorDescriptor)) {
return null;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
assert containingClass != null : "Can't have constructor without a class";
return getNameForDescriptor(containingClass);
}
};
Rule<JsName> accessorsHasNamesWithSpecialPrefixes = new Rule<JsName>() {
@Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof PropertyAccessorDescriptor)) {
return null;
}
boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
String propertyName = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty().getName();
String accessorName = Namer.getNameForAccessor(propertyName, isGetter);
NamingScope enclosingScope = getEnclosingScope(descriptor);
return enclosingScope.declareObfuscatableName(accessorName);
}
};
Rule<JsName> namesAnnotatedAsStandard = new Rule<JsName>() {
@Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
//TODO: refactor
String name = null;
AnnotationDescriptor annotation = getAnnotationByName(descriptor, LIBRARY_FUNCTION_ANNOTATION_FQNAME);
if (annotation != null) {
name = AnnotationsUtils.annotationStringParameter(descriptor, LIBRARY_FUNCTION_ANNOTATION_FQNAME);
name = (!name.isEmpty()) ? name : descriptor.getName();
} else {
ClassDescriptor containingClass = getContainingClass(descriptor);
if (containingClass == null) return null;
if (getAnnotationByName(containingClass, LIBRARY_CLASS_ANNOTATION_FQNAME) != null) {
name = descriptor.getName();
}
}
if (name != null) {
return getEnclosingScope(descriptor).declareUnobfuscatableName(name);
} }
return null; return null;
} }
}); };
Generator<JsName> nameGenerator = new Generator<JsName>();
nameGenerator.addRule(namesForStandardClasses);
nameGenerator.addRule(aliasOverridesNames);
nameGenerator.addRule(constructorHasTheSameNameAsTheClass);
nameGenerator.addRule(namesAnnotatedAsStandard);
nameGenerator.addRule(namespacesShouldBeDefinedInRootScope);
nameGenerator.addRule(accessorsHasNamesWithSpecialPrefixes);
nameGenerator.addRule(memberDeclarationsInsideParentsScope);
return nameGenerator; return nameGenerator;
} }
private NamingScope getEnclosingScope(DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
return getScopeForDescriptor(containingDeclaration.getOriginal());
}
@NotNull @NotNull
private Generator<NamingScope> scopeGenerator() { private Generator<NamingScope> scopeGenerator() {
Generator<NamingScope> scopeGenerator = new Generator<NamingScope>(); Generator<NamingScope> scopeGenerator = new Generator<NamingScope>();
@@ -252,21 +283,91 @@ public final class TranslationContext {
return staticContext.getRootScope().innerScope("Namespace " + descriptor.getName()); return staticContext.getRootScope().innerScope("Namespace " + descriptor.getName());
} }
}; };
Rule<NamingScope> generateInnerScopesForFunctions = new Rule<NamingScope>() { Rule<NamingScope> generateInnerScopesForMembers = new Rule<NamingScope>() {
@Override @Override
public NamingScope apply(@NotNull DeclarationDescriptor descriptor) { public NamingScope apply(@NotNull DeclarationDescriptor descriptor) {
// if (!(descriptor instanceof FunctionDescriptor)) { NamingScope enclosingScope = getEnclosingScope(descriptor);
// return null;
// }
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
NamingScope enclosingScope = getScopeForDescriptor(containingDeclaration);
return enclosingScope.innerScope("scope for member " + descriptor.getName()); return enclosingScope.innerScope("scope for member " + descriptor.getName());
} }
}; };
scopeGenerator.addRule(generateNewScopesForNamespaceDescriptors); scopeGenerator.addRule(generateNewScopesForNamespaceDescriptors);
scopeGenerator.addRule(generateInnerScopesForFunctions); scopeGenerator.addRule(generateInnerScopesForMembers);
return scopeGenerator; return scopeGenerator;
} }
@Nullable
public JsNameRef getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) {
return qualifiers.get(descriptor.getOriginal());
}
@NotNull
private Generator<JsNameRef> qualifierGenerator() {
Generator<JsNameRef> qualifierGenerator = new Generator<JsNameRef>();
Rule<JsNameRef> namespacesHaveNoQualifiers = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (!standardClasses().isStandardObject(descriptor)) {
return null;
}
return namer().kotlinObject();
}
};
Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
if (!(containingDeclaration instanceof NamespaceDescriptor)) {
return null;
}
JsName containingDeclarationName = getNameForDescriptor(containingDeclaration);
return containingDeclarationName.makeRef();
}
};
Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ConstructorDescriptor)) {
return null;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
assert containingClass != null : "Can't have constructor without a class";
return getQualifierForDescriptor(containingClass);
}
};
Rule<JsNameRef> annonatedObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
//TODO: refactor by removing one annotation
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_FUNCTION_ANNOTATION_FQNAME) != null) {
return namer().kotlinObject();
}
if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_CLASS_ANNOTATION_FQNAME) != null) {
return namer().kotlinObject();
}
return null;
}
};
Rule<JsNameRef> membersOfAnnotatedClassesHaveKotlinQualifier = new Rule<JsNameRef>() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
ClassDescriptor containingClass = getContainingClass(descriptor);
if (containingClass == null) {
return null;
}
if (getAnnotationByName(descriptor, LIBRARY_CLASS_ANNOTATION_FQNAME) != null) {
return namer().kotlinObject();
}
return null;
}
};
qualifierGenerator.addRule(annonatedObjectsHaveKotlinQualifier);
qualifierGenerator.addRule(membersOfAnnotatedClassesHaveKotlinQualifier);
qualifierGenerator.addRule(constructorHaveTheSameQualifierAsTheClass);
qualifierGenerator.addRule(namespacesHaveNoQualifiers);
qualifierGenerator.addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier);
return qualifierGenerator;
}
} }
@@ -4,12 +4,10 @@ import com.google.dart.compiler.backend.js.ast.JsName;
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.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.NamingScope; import org.jetbrains.k2js.translate.context.NamingScope;
import java.util.Set; import java.util.Set;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getNameForNamespace;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getOwnDeclarations; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getOwnDeclarations;
/** /**
@@ -133,49 +131,5 @@ public abstract class AbstractDeclarationVisitor extends DeclarationDescriptorVi
return false; return false;
} }
@Override
public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull DeclarationContext context) {
String propertyName = descriptor.getName();
String backingFieldName = Namer.getKotlinBackingFieldName(propertyName);
declareName(descriptor, context, backingFieldName);
extractAccessor(descriptor.getGetter(), true, propertyName, context);
if (descriptor.isVar()) {
extractAccessor(descriptor.getSetter(), false, propertyName, context);
}
return null;
}
public void extractAccessor(@Nullable PropertyAccessorDescriptor descriptor, boolean isGetter,
@NotNull String propertyName, @NotNull DeclarationContext context) {
if (descriptor == null) return;
String accessorName = Namer.getNameForAccessor(propertyName, isGetter);
declareName(descriptor, context, accessorName);
declareScope(descriptor, context, (isGetter ? "getter " : "setter ") + propertyName);
}
@Override
public Void visitNamespaceDescriptor(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
//TODO: traverse
/* do not traverse inner namespaces */
return null;
}
@NotNull
protected DeclarationContext extractNamespaceDeclaration(@NotNull NamespaceDescriptor descriptor,
@NotNull DeclarationContext context) {
String nameForNamespace = getNameForNamespace(descriptor);
JsName namespaceName = doDeclareName(descriptor, context, nameForNamespace);
NamingScope namespaceScope = doDeclareScope(descriptor, context, "namespace " + namespaceName.getIdent());
return context.innerDeclaration(namespaceScope, namespaceName);
}
protected void declareMembers(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
for (DeclarationDescriptor memberDescriptor :
descriptor.getMemberScope().getAllDescriptors()) {
memberDescriptor.accept(this, context);
}
}
} }
@@ -1,120 +0,0 @@
package org.jetbrains.k2js.translate.context.declaration;
import com.google.dart.compiler.backend.js.ast.JsName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.k2js.translate.context.NamingScope;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.annotationStringParameter;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.getAnnotationByName;
/**
* @author Pavel Talanov
*/
public class AnnotatedDeclarationVisitor extends AbstractDeclarationVisitor {
@NotNull
private final String classAnnotationFQName;
@NotNull
private final String memberAnnotationFQName;
/*package*/ AnnotatedDeclarationVisitor(@NotNull Declarations declarations,
@NotNull String classAnnotationFQName,
@NotNull String memberAnnotationFQName) {
super(declarations);
this.classAnnotationFQName = classAnnotationFQName;
this.memberAnnotationFQName = memberAnnotationFQName;
}
@NotNull
@Override
protected NamingScope doDeclareScope(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context,
@NotNull String recommendedName) {
//TODO: probably need to keep track
if (!(descriptor instanceof ClassDescriptor)) {
return context.getScope();
}
NamingScope innerScope = context.getScope().innerScope(recommendedName);
declarations().putScope(descriptor, innerScope);
return innerScope;
}
@NotNull
@Override
protected JsName doDeclareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context,
@NotNull String recommendedName) {
String nativeName = getName(descriptor);
JsName jsName = context.getScope().
declareVariable(descriptor, nativeName, false);
jsName.setObfuscatable(false);
declarations().putName(descriptor, jsName);
declarations().putQualifier(descriptor, context.getQualifier());
return jsName;
}
@Override
protected boolean accept(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof NamespaceDescriptor) {
return true;
}
if (descriptor instanceof ClassDescriptor) {
return isAnnotatedClass((ClassDescriptor) descriptor);
}
return isAnnotatedMember(descriptor);
}
@Override
public void traverseNamespace(@NotNull NamespaceDescriptor namespace, @NotNull DeclarationContext context) {
declareMembers(namespace, context);
}
//TODO: refactor
@NotNull
public String getName(@NotNull DeclarationDescriptor descriptor) {
if (hasMemberAnnotation(descriptor)) {
String name = annotationStringParameter(descriptor, memberAnnotationFQName);
if (!(name.isEmpty())) {
return name;
}
return descriptor.getName();
}
if (declaredInAnnotatedClass(descriptor)) {
return descriptor.getName();
}
if (hasClassAnnotation(descriptor)) {
return descriptor.getName();
}
throw new AssertionError("Use isAnnotatedFunction to check");
}
public boolean isAnnotatedMember(@NotNull DeclarationDescriptor descriptor) {
return hasMemberAnnotation(descriptor) || declaredInAnnotatedClass(descriptor);
}
public boolean isAnnotatedClass(@NotNull ClassDescriptor classDescriptor) {
return hasClassAnnotation(classDescriptor);
}
private boolean declaredInAnnotatedClass(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof ClassDescriptor)) return false;
return hasClassAnnotation(containingDeclaration);
}
private boolean hasMemberAnnotation(@NotNull DeclarationDescriptor descriptor) {
return (getAnnotationByName(descriptor, memberAnnotationFQName) != null);
}
private boolean hasClassAnnotation(@NotNull DeclarationDescriptor descriptor) {
return (getAnnotationByName(descriptor, classAnnotationFQName) != null);
}
}
@@ -1,6 +1,5 @@
package org.jetbrains.k2js.translate.context.declaration; package org.jetbrains.k2js.translate.context.declaration;
import com.google.common.collect.Sets;
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;
@@ -8,8 +7,6 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import java.util.Set;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
@@ -21,23 +18,10 @@ public final class AnnotationsUtils {
public static final String LIBRARY_FUNCTION_ANNOTATION_FQNAME = "js.annotations.LibraryFun"; public static final String LIBRARY_FUNCTION_ANNOTATION_FQNAME = "js.annotations.LibraryFun";
@NotNull @NotNull
public static final String LIBRARY_CLASS_ANNOTATION_FQNAME = "js.annotations.LibraryClass"; public static final String LIBRARY_CLASS_ANNOTATION_FQNAME = "js.annotations.LibraryClass";
@NotNull
public static Set<String> INTERNAL_ANNOTATIONS_FQNAMES = Sets.newHashSet(
NATIVE_ANNOTATION_FQNAME,
LIBRARY_CLASS_ANNOTATION_FQNAME, LIBRARY_FUNCTION_ANNOTATION_FQNAME);
private AnnotationsUtils() { private AnnotationsUtils() {
} }
public static boolean doesNotHaveInternalAnnotations(@NotNull DeclarationDescriptor descriptor) {
for (String annotationFQNAme : INTERNAL_ANNOTATIONS_FQNAMES) {
if (hasAnnotation(descriptor, annotationFQNAme)) {
return false;
}
}
return true;
}
private static boolean hasAnnotation(@NotNull DeclarationDescriptor descriptor, private static boolean hasAnnotation(@NotNull DeclarationDescriptor descriptor,
@NotNull String annotationFQNAme) { @NotNull String annotationFQNAme) {
return getAnnotationByName(descriptor, annotationFQNAme) != null; return getAnnotationByName(descriptor, annotationFQNAme) != null;
@@ -1,116 +0,0 @@
package org.jetbrains.k2js.translate.context.declaration;
import com.google.common.collect.Sets;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.NamingScope;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.List;
import java.util.Set;
/**
* @author Pavel Talanov
*/
//TODO: decide to maybe not to use different declaration objects
//TODO: methods receiver too many parameters and also unneccessary information like rootScope is stored inside
public final class DeclarationFacade {
@NotNull
public static DeclarationFacade createFacade(@NotNull NamingScope scope) {
return new DeclarationFacade(scope);
}
@NotNull
private final Declarations jetLibraryDeclarations;
@NotNull
private final Declarations kotlinDeclarations;
@NotNull
private final Declarations nativeDeclarations;
@NotNull
private final Declarations jsLibraryDeclarations;
@NotNull
private final NamingScope rootScope;
private DeclarationFacade(@NotNull NamingScope rootScope) {
this.rootScope = rootScope;
this.jetLibraryDeclarations = Declarations.newInstance();
this.kotlinDeclarations = Declarations.newInstance();
this.nativeDeclarations = Declarations.newInstance();
this.jsLibraryDeclarations = Declarations.newInstance();
}
@NotNull
public Declarations getJetLibraryDeclarations() {
return jetLibraryDeclarations;
}
@NotNull
public Declarations getKotlinDeclarations() {
return kotlinDeclarations;
}
@NotNull
public Declarations getNativeDeclarations() {
return nativeDeclarations;
}
@NotNull
public Set<Declarations> getAllDeclarations() {
return Sets.newHashSet(jetLibraryDeclarations, kotlinDeclarations, nativeDeclarations, jsLibraryDeclarations);
}
@NotNull
public DeclarationFacade extractStandardLibrary(@NotNull JetStandardLibrary standardLibrary,
@NotNull JsNameRef standardLibraryObjectName) {
KotlinDeclarationVisitor visitor = new KotlinDeclarationVisitor(jetLibraryDeclarations, false);
for (DeclarationDescriptor descriptor :
standardLibrary.getLibraryScope().getAllDescriptors()) {
descriptor.accept(visitor, DeclarationContext.rootContext(rootScope, standardLibraryObjectName));
}
return this;
}
//TODO: decide if is public
public void extractDeclarationsFromNamespace(@NotNull NamespaceDescriptor descriptor,
@NotNull Namer namer) {
KotlinDeclarationVisitor kotlinDeclarationVisitor = new KotlinDeclarationVisitor(kotlinDeclarations, true);
kotlinDeclarationVisitor.traverseNamespace
(descriptor, DeclarationContext.rootContext(rootScope, null));
NativeDeclarationVisitor nativeDeclarationVisitor = new NativeDeclarationVisitor(nativeDeclarations);
nativeDeclarationVisitor.traverseNamespace
(descriptor, DeclarationContext.rootContext(rootScope, null));
LibraryDeclarationVisitor libraryDeclarationVisitor = new LibraryDeclarationVisitor(jsLibraryDeclarations);
libraryDeclarationVisitor.traverseNamespace
(descriptor, DeclarationContext.rootContext(rootScope, namer.kotlinObject()));
}
public void extractDeclarationsFromFiles(@NotNull List<JetFile> files,
@NotNull BindingContext context,
@NotNull Namer namer) {
for (NamespaceDescriptor namespace : getAllNamespaces(files, context)) {
extractDeclarationsFromNamespace(namespace, namer);
}
}
//TODO: util method
@NotNull
private Set<NamespaceDescriptor> getAllNamespaces(@NotNull List<JetFile> files, @NotNull BindingContext context) {
Set<NamespaceDescriptor> namespaces = Sets.newHashSet();
for (JetFile file : files) {
namespaces.add(BindingUtils.getNamespaceDescriptor(context, file));
}
return namespaces;
}
}
@@ -6,7 +6,6 @@ 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.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.k2js.translate.context.NamingScope;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -21,8 +20,6 @@ public final class Declarations {
return new Declarations(); return new Declarations();
} }
@NotNull
private final Map<DeclarationDescriptor, NamingScope> descriptorToScopeMap = new HashMap<DeclarationDescriptor, NamingScope>();
@NotNull @NotNull
private final Map<DeclarationDescriptor, JsName> descriptorToNameMap = new HashMap<DeclarationDescriptor, JsName>(); private final Map<DeclarationDescriptor, JsName> descriptorToNameMap = new HashMap<DeclarationDescriptor, JsName>();
@NotNull @NotNull
@@ -31,12 +28,6 @@ public final class Declarations {
private Declarations() { private Declarations() {
} }
@NotNull
public NamingScope getScope(@NotNull DeclarationDescriptor descriptor) {
NamingScope scope = descriptorToScopeMap.get(descriptor.getOriginal());
assert scope != null : "Unknown declaration";
return scope;
}
@NotNull @NotNull
public JsName getName(@NotNull DeclarationDescriptor descriptor) { public JsName getName(@NotNull DeclarationDescriptor descriptor) {
@@ -60,12 +51,6 @@ public final class Declarations {
return qualifier; return qualifier;
} }
/*package*/ void putScope(@NotNull DeclarationDescriptor descriptor, @NotNull NamingScope scope) {
assert !descriptorToScopeMap.containsKey(descriptor)
: "Already contains that key!\n" + descriptor;
descriptorToScopeMap.put(descriptor, scope);
}
/*package*/ void putName(@NotNull DeclarationDescriptor descriptor, @NotNull JsName name) { /*package*/ void putName(@NotNull DeclarationDescriptor descriptor, @NotNull JsName name) {
assert !descriptorToNameMap.containsKey(descriptor) assert !descriptorToNameMap.containsKey(descriptor)
: "Already contains that key!\n" + descriptor; : "Already contains that key!\n" + descriptor;
@@ -1,52 +1,44 @@
package org.jetbrains.k2js.translate.context.declaration; //package org.jetbrains.k2js.translate.context.declaration;
//
import com.google.dart.compiler.backend.js.ast.JsName; //import com.google.dart.compiler.backend.js.ast.JsName;
import org.jetbrains.annotations.NotNull; //import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; //import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; //import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.k2js.translate.context.NamingScope; //import org.jetbrains.k2js.translate.context.NamingScope;
//
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.doesNotHaveInternalAnnotations; //import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.doesNotHaveInternalAnnotations;
//
/** ///**
* @author Pavel Talanov // * @author Pavel Talanov
*/ // */
public final class KotlinDeclarationVisitor extends AbstractDeclarationVisitor { //public final class KotlinDeclarationVisitor extends AbstractDeclarationVisitor {
//
private final boolean shouldObfuscate; // private final boolean shouldObfuscate;
//
/*package*/ KotlinDeclarationVisitor(@NotNull Declarations declarations, boolean obfuscateNames) { // /*package*/ KotlinDeclarationVisitor(@NotNull Declarations declarations, boolean obfuscateNames) {
super(declarations); // super(declarations);
this.shouldObfuscate = obfuscateNames; // this.shouldObfuscate = obfuscateNames;
} // }
//
@Override // @Override
protected NamingScope doDeclareScope(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context, // @NotNull
@NotNull String recommendedName) { // protected JsName doDeclareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context,
NamingScope innerScope = context.getScope().innerScope(recommendedName); // @NotNull String recommendedName) {
declarations().putScope(descriptor, innerScope); // JsName jsName = context.getScope().declareVariable(descriptor, recommendedName, shouldObfuscate);
return innerScope; // jsName.setObfuscatable(false);
} // declarations().putName(descriptor, jsName);
// declarations().putQualifier(descriptor, context.getQualifier());
@Override // return jsName;
@NotNull // }
protected JsName doDeclareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context, //
@NotNull String recommendedName) { // @Override
JsName jsName = context.getScope().declareVariable(descriptor, recommendedName, shouldObfuscate); // protected boolean accept(@NotNull DeclarationDescriptor descriptor) {
jsName.setObfuscatable(false); // return (doesNotHaveInternalAnnotations(descriptor));
declarations().putName(descriptor, jsName); // }
declarations().putQualifier(descriptor, context.getQualifier()); //
return jsName; // @Override
} // public void traverseNamespace(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
// DeclarationContext namespaceContext = extractNamespaceDeclaration(descriptor, context);
@Override // declareMembers(descriptor, namespaceContext);
protected boolean accept(@NotNull DeclarationDescriptor descriptor) { // }
return (doesNotHaveInternalAnnotations(descriptor)); //}
}
@Override
public void traverseNamespace(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) {
DeclarationContext namespaceContext = extractNamespaceDeclaration(descriptor, context);
declareMembers(descriptor, namespaceContext);
}
}
@@ -1,16 +0,0 @@
package org.jetbrains.k2js.translate.context.declaration;
import org.jetbrains.annotations.NotNull;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.LIBRARY_CLASS_ANNOTATION_FQNAME;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.LIBRARY_FUNCTION_ANNOTATION_FQNAME;
/**
* @author Pavel Talanov
*/
public final class LibraryDeclarationVisitor extends AnnotatedDeclarationVisitor {
/*package*/ LibraryDeclarationVisitor(@NotNull Declarations nativeDeclarations) {
super(nativeDeclarations, LIBRARY_CLASS_ANNOTATION_FQNAME, LIBRARY_FUNCTION_ANNOTATION_FQNAME);
}
}
@@ -1,15 +0,0 @@
package org.jetbrains.k2js.translate.context.declaration;
import org.jetbrains.annotations.NotNull;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.NATIVE_ANNOTATION_FQNAME;
/**
* @author Pavel Talanov
*/
public final class NativeDeclarationVisitor extends AnnotatedDeclarationVisitor {
/*package*/ NativeDeclarationVisitor(@NotNull Declarations nativeDeclarations) {
super(nativeDeclarations, NATIVE_ANNOTATION_FQNAME, NATIVE_ANNOTATION_FQNAME);
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.k2js.translate.context.generator;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import java.util.List; import java.util.List;
@@ -23,7 +24,7 @@ public final class Generator<V> {
rules.add(rule); rules.add(rule);
} }
@NotNull @Nullable
public V get(@NotNull DeclarationDescriptor descriptor) { public V get(@NotNull DeclarationDescriptor descriptor) {
V result = values.get(descriptor); V result = values.get(descriptor);
if (result != null) { if (result != null) {
@@ -32,7 +33,7 @@ public final class Generator<V> {
return generate(descriptor); return generate(descriptor);
} }
@NotNull @Nullable
private V generate(@NotNull DeclarationDescriptor descriptor) { private V generate(@NotNull DeclarationDescriptor descriptor) {
V result = null; V result = null;
for (Rule<V> rule : rules) { for (Rule<V> rule : rules) {
@@ -41,6 +42,6 @@ public final class Generator<V> {
return result; return result;
} }
} }
throw new AssertionError("No rule applicable to generate result for " + descriptor.toString()); return result;
} }
} }
@@ -24,8 +24,7 @@ import org.jetbrains.k2js.translate.utils.TranslationUtils;
import java.util.List; import java.util.List;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getCompileTimeValue; import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateInitializerForProperty; import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateInitializerForProperty;
/** /**
@@ -117,7 +116,8 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull @NotNull
// assume it is a local variable declaration // assume it is a local variable declaration
public JsNode visitProperty(@NotNull JetProperty expression, @NotNull TranslationContext context) { public JsNode visitProperty(@NotNull JetProperty expression, @NotNull TranslationContext context) {
JsName jsPropertyName = context.declareLocalVariable(expression); DeclarationDescriptor descriptor = getDescriptorForElement(context.bindingContext(), expression);
JsName jsPropertyName = context.getNameForDescriptor(descriptor);
JsExpression jsInitExpression = translateInitializerForProperty(expression, context); JsExpression jsInitExpression = translateInitializerForProperty(expression, context);
return AstUtil.newVar(jsPropertyName, jsInitExpression); return AstUtil.newVar(jsPropertyName, jsInitExpression);
} }
@@ -49,7 +49,7 @@ public final class ForTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsName declareParameter() { private JsName declareParameter() {
JetParameter loopParameter = getLoopParameter(expression); JetParameter loopParameter = getLoopParameter(expression);
return context().declareLocalVariable(loopParameter); return context().getNameForElement(loopParameter);
} }
@NotNull @NotNull
@@ -181,7 +181,7 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsName declareParameter(@NotNull ValueParameterDescriptor valueParameter) { private JsName declareParameter(@NotNull ValueParameterDescriptor valueParameter) {
return context().declareLocalVariable(valueParameter); return context().getNameForDescriptor(valueParameter);
} }
private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) { private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) {
@@ -74,7 +74,7 @@ public final class TryTranslator extends AbstractTranslator {
JetParameter catchParameter = catchClause.getCatchParameter(); JetParameter catchParameter = catchClause.getCatchParameter();
assert catchParameter != null : "Valid catch must have a parameter."; assert catchParameter != null : "Valid catch must have a parameter.";
JsName parameterName = context().declareLocalVariable(catchParameter); JsName parameterName = context().getNameForElement(catchParameter);
JsCatch result = new JsCatch(context().jsScope(), parameterName.getIdent()); JsCatch result = new JsCatch(context().jsScope(), parameterName.getIdent());
result.setBody(translateCatchBody(catchClause)); result.setBody(translateCatchBody(catchClause));
return result; return result;
@@ -97,10 +97,6 @@ public final class Translation {
//TODO: move some of the code somewhere //TODO: move some of the code somewhere
JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext); StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext);
staticContext.getDeclarationFacade().
extractStandardLibrary(standardLibrary, staticContext.getNamer().kotlinObject());
staticContext.getDeclarationFacade().
extractDeclarationsFromFiles(files, bindingContext, staticContext.getNamer());
JsBlock block = staticContext.getProgram().getFragmentBlock(0); JsBlock block = staticContext.getProgram().getFragmentBlock(0);
TranslationContext context = TranslationContext.rootContext(staticContext); TranslationContext context = TranslationContext.rootContext(staticContext);
block.addStatement(Translation.translateNamespace(namespaceToTranslate, context)); block.addStatement(Translation.translateNamespace(namespaceToTranslate, context));
@@ -102,7 +102,7 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla
private JsParameter translateParameter(@NotNull JetParameter jetParameter) { private JsParameter translateParameter(@NotNull JetParameter jetParameter) {
DeclarationDescriptor parameterDescriptor = DeclarationDescriptor parameterDescriptor =
getDescriptorForElement(context().bindingContext(), jetParameter); getDescriptorForElement(context().bindingContext(), jetParameter);
JsName parameterName = initializerMethodScope.declareVariable(parameterDescriptor); JsName parameterName = context().getNameForDescriptor(parameterDescriptor);
JsParameter jsParameter = new JsParameter(parameterName); JsParameter jsParameter = new JsParameter(parameterName);
mayBeAddInitializerStatementForProperty(jsParameter, jetParameter); mayBeAddInitializerStatementForProperty(jsParameter, jetParameter);
return jsParameter; return jsParameter;
@@ -10,7 +10,9 @@ import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils;
import static org.jetbrains.k2js.translate.context.declaration.AnnotationsUtils.getAnnotationByName;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression; import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName; import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName;
@@ -109,7 +111,7 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
private static boolean isNativeProperty(@NotNull PropertyDescriptor propertyDescriptor, private static boolean isNativeProperty(@NotNull PropertyDescriptor propertyDescriptor,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return context.declarationFacade().getNativeDeclarations().hasDeclaredName(propertyDescriptor); return getAnnotationByName(propertyDescriptor, AnnotationsUtils.NATIVE_ANNOTATION_FQNAME) != null;
} }
protected PropertyAccessTranslator(@NotNull TranslationContext context) { protected PropertyAccessTranslator(@NotNull TranslationContext context) {
@@ -29,18 +29,17 @@ public final class ReferenceTranslator {
@NotNull @NotNull
public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor, public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
if (!context.hasQualifierForDescriptor(referencedDescriptor)) { JsExpression qualifier = context.getQualifierForDescriptor(referencedDescriptor);
if (qualifier == null) {
return translateAsLocalNameReference(referencedDescriptor, context); return translateAsLocalNameReference(referencedDescriptor, context);
} }
JsName referencedName = context.getNameForDescriptor(referencedDescriptor); JsName referencedName = context.getNameForDescriptor(referencedDescriptor);
JsExpression qualifier = context.getQualifierForDescriptor(referencedDescriptor);
return AstUtil.qualified(referencedName, qualifier); return AstUtil.qualified(referencedName, qualifier);
} }
@NotNull @NotNull
public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor referencedDescriptor, public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor referencedDescriptor,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
//TODO: prove correctness
JsName referencedName = context.getNameForDescriptor(referencedDescriptor); JsName referencedName = context.getNameForDescriptor(referencedDescriptor);
return referencedName.makeRef(); return referencedName.makeRef();
} }
@@ -98,8 +98,8 @@ public final class TranslationUtils {
@NotNull DeclarationDescriptor descriptor) { @NotNull DeclarationDescriptor descriptor) {
JsName name = context.getNameForDescriptor(descriptor); JsName name = context.getNameForDescriptor(descriptor);
JsNameRef reference = name.makeRef(); JsNameRef reference = name.makeRef();
if (context.hasQualifierForDescriptor(descriptor)) { JsNameRef qualifier = context.getQualifierForDescriptor(descriptor);
JsNameRef qualifier = context.getQualifierForDescriptor(descriptor); if (qualifier != null) {
AstUtil.setQualifier(reference, qualifier); AstUtil.setQualifier(reference, qualifier);
} }
return reference; return reference;