diff --git a/translator/src/org/jetbrains/k2js/config/Config.java b/translator/src/org/jetbrains/k2js/config/Config.java index 3741f587396..aa482d61202 100644 --- a/translator/src/org/jetbrains/k2js/config/Config.java +++ b/translator/src/org/jetbrains/k2js/config/Config.java @@ -21,7 +21,7 @@ public abstract class Config { @NotNull private static final String PATH_TO_JS_LIB_SRC = getPathToJsLibSrc(); - //TODO: provide some generic way to access + //TODO: provide some generic way to get the files of the project @NotNull private static final List LIB_FILE_NAMES = Arrays.asList( PATH_TO_JS_LIB_SRC + "\\core\\annotations.kt", diff --git a/translator/src/org/jetbrains/k2js/translate/context/NamingScope.java b/translator/src/org/jetbrains/k2js/translate/context/NamingScope.java index 7dc22a79794..93574d36e78 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/NamingScope.java +++ b/translator/src/org/jetbrains/k2js/translate/context/NamingScope.java @@ -3,7 +3,6 @@ package org.jetbrains.k2js.translate.context; import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsScope; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author Pavel Talanov @@ -12,29 +11,25 @@ public final class NamingScope { @NotNull public static NamingScope rootScope(@NotNull JsScope rootScope) { - return new NamingScope(rootScope, null); + return new NamingScope(rootScope); } @NotNull private final JsScope scope; - @Nullable - private final NamingScope parent; - - private NamingScope(@NotNull JsScope correspondingScope, @Nullable NamingScope parent) { + private NamingScope(@NotNull JsScope correspondingScope) { this.scope = correspondingScope; - this.parent = parent; } @NotNull public NamingScope innerScope(@NotNull String scopeName) { JsScope innerJsScope = new JsScope(jsScope(), scopeName); - return new NamingScope(innerJsScope, this); + return new NamingScope(innerJsScope); } @NotNull public NamingScope innerScope(@NotNull JsScope correspondingScope) { - return new NamingScope(correspondingScope, this); + return new NamingScope(correspondingScope); } @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index 3b3adcfb399..00ce40c17e8 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -56,11 +56,11 @@ public class StaticContext { private final NamingScope rootScope; @NotNull - private final Generator names = nameGenerator(); + private final Generator names = new NameGenerator(); @NotNull - private final Generator scopes = scopeGenerator(); + private final Generator scopes = new ScopeGenerator(); @NotNull - private final Generator qualifiers = qualifierGenerator(); + private final Generator qualifiers = new QualifierGenerator(); //TODO: too many parameters in constructor @@ -112,260 +112,6 @@ public class StaticContext { return standardClasses; } - - @NotNull - private Generator nameGenerator() { - - Rule aliasOverridesNames = new Rule() { - @Override - @Nullable - public JsName apply(@NotNull DeclarationDescriptor data) { - if (aliaser.hasAliasForDeclaration(data)) { - return aliaser.getAliasForDeclaration(data); - } - return null; - } - }; - Rule namesForStandardClasses = new Rule() { - @Override - @Nullable - public JsName apply(@NotNull DeclarationDescriptor data) { - if (!standardClasses.isStandardObject(data)) { - return null; - } - return standardClasses.getStandardObjectName(data); - } - }; - Rule namespacesShouldBeDefinedInRootScope = new Rule() { - @Override - @Nullable - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof NamespaceDescriptor)) { - return null; - } - String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor); - return getRootScope().declareUnobfuscatableName(nameForNamespace); - } - }; - Rule memberDeclarationsInsideParentsScope = new Rule() { - @Override - @Nullable - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - NamingScope namingScope = getEnclosingScope(descriptor); - return namingScope.declareObfuscatableName(descriptor.getName()); - } - }; - Rule constructorHasTheSameNameAsTheClass = new Rule() { - @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 accessorsHasNamesWithSpecialPrefixes = new Rule() { - @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 namesAnnotatedAsLibraryHasUnobfuscatableNames = new Rule() { - @Override - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - //TODO: refactor - String name = null; - AnnotationDescriptor annotation = getAnnotationByName(descriptor, LIBRARY_ANNOTATION_FQNAME); - if (annotation != null) { - name = AnnotationsUtils.getAnnotationStringParameter(descriptor, LIBRARY_ANNOTATION_FQNAME); - name = (!name.isEmpty()) ? name : descriptor.getName(); - } else { - ClassDescriptor containingClass = getContainingClass(descriptor); - if (containingClass == null) return null; - if (getAnnotationByName(containingClass, LIBRARY_ANNOTATION_FQNAME) != null) { - name = descriptor.getName(); - } - } - if (name != null) { - return getEnclosingScope(descriptor).declareUnobfuscatableName(name); - } - return null; - } - }; - Rule propertiesCorrespondToSpeciallyTreatedBackingFieldNames = new Rule() { - @Override - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof PropertyDescriptor)) { - return null; - } - NamingScope enclosingScope = getEnclosingScope(descriptor); - return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName())); - } - }; - //TODO: hack! - Rule toStringHack = new Rule() { - @Override - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof FunctionDescriptor)) { - return null; - } - if (!descriptor.getName().equals("toString")) { - return null; - } - if (((FunctionDescriptor) descriptor).getValueParameters().isEmpty()) { - return getEnclosingScope(descriptor).declareUnobfuscatableName("toString"); - } - return null; - } - - }; - Rule namesForNativeObjectsAreUnobfuscatable = new Rule() { - @Override - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - String name = null; - AnnotationDescriptor annotation = getAnnotationByName(descriptor, NATIVE_ANNOTATION_FQNAME); - if (annotation != null) { - name = AnnotationsUtils.getAnnotationStringParameter(descriptor, NATIVE_ANNOTATION_FQNAME); - name = (!name.isEmpty()) ? name : descriptor.getName(); - } else { - ClassDescriptor containingClass = getContainingClass(descriptor); - if (containingClass == null) return null; - if (getAnnotationByName(containingClass, NATIVE_ANNOTATION_FQNAME) != null) { - name = descriptor.getName(); - } - } - if (name != null) { - return getEnclosingScope(descriptor).declareUnobfuscatableName(name); - } - return null; - - } - }; - Generator nameGenerator = new Generator(); - nameGenerator.addRule(namesForStandardClasses); - nameGenerator.addRule(aliasOverridesNames); - nameGenerator.addRule(constructorHasTheSameNameAsTheClass); - nameGenerator.addRule(namesAnnotatedAsLibraryHasUnobfuscatableNames); - nameGenerator.addRule(namesForNativeObjectsAreUnobfuscatable); - nameGenerator.addRule(toStringHack); - nameGenerator.addRule(propertiesCorrespondToSpeciallyTreatedBackingFieldNames); - nameGenerator.addRule(namespacesShouldBeDefinedInRootScope); - nameGenerator.addRule(accessorsHasNamesWithSpecialPrefixes); - nameGenerator.addRule(memberDeclarationsInsideParentsScope); - return nameGenerator; - } - - private NamingScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) { - DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); - return getScopeForDescriptor(containingDeclaration.getOriginal()); - } - - @NotNull - private Generator scopeGenerator() { - Generator scopeGenerator = new Generator(); - Rule generateNewScopesForNamespaceDescriptors = new Rule() { - @Override - public NamingScope apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof NamespaceDescriptor)) { - return null; - } - return getRootScope().innerScope("Namespace " + descriptor.getName()); - } - }; - Rule generateInnerScopesForMembers = new Rule() { - @Override - public NamingScope apply(@NotNull DeclarationDescriptor descriptor) { - NamingScope enclosingScope = getEnclosingScope(descriptor); - return enclosingScope.innerScope("scope for member " + descriptor.getName()); - } - }; - scopeGenerator.addRule(generateNewScopesForNamespaceDescriptors); - scopeGenerator.addRule(generateInnerScopesForMembers); - - return scopeGenerator; - } - - - @NotNull - private Generator qualifierGenerator() { - Rule namespacesHaveNoQualifiers = new Rule() { - @Override - public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { - if (!standardClasses.isStandardObject(descriptor)) { - return null; - } - return namer.kotlinObject(); - } - }; - Rule namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule() { - @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 constructorHaveTheSameQualifierAsTheClass = new Rule() { - @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 libraryObjectsHaveKotlinQualifier = new Rule() { - - //TODO: refactor by removing one annotation - @Override - public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { - if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_ANNOTATION_FQNAME) != null) { - return namer.kotlinObject(); - } - if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_ANNOTATION_FQNAME) != null) { - return namer.kotlinObject(); - } - return null; - } - }; - Rule membersOfAnnotatedClassesHaveKotlinQualifier = new Rule() { - @Override - public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { - ClassDescriptor containingClass = getContainingClass(descriptor); - if (containingClass == null) { - return null; - } - if (getAnnotationByName(descriptor, LIBRARY_ANNOTATION_FQNAME) != null) { - return namer.kotlinObject(); - } - return null; - } - }; - Generator qualifierGenerator = new Generator(); - qualifierGenerator.addRule(libraryObjectsHaveKotlinQualifier); - qualifierGenerator.addRule(membersOfAnnotatedClassesHaveKotlinQualifier); - qualifierGenerator.addRule(constructorHaveTheSameQualifierAsTheClass); - qualifierGenerator.addRule(namespacesHaveNoQualifiers); - qualifierGenerator.addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier); - return qualifierGenerator; - } - - @NotNull public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { NamingScope namingScope = scopes.get(descriptor); @@ -390,4 +136,254 @@ public class StaticContext { return name; } + + private class NameGenerator extends Generator { + public NameGenerator() { + Rule aliasOverridesNames = new Rule() { + @Override + @Nullable + public JsName apply(@NotNull DeclarationDescriptor data) { + if (aliaser.hasAliasForDeclaration(data)) { + return aliaser.getAliasForDeclaration(data); + } + return null; + } + }; + Rule namesForStandardClasses = new Rule() { + @Override + @Nullable + public JsName apply(@NotNull DeclarationDescriptor data) { + if (!standardClasses.isStandardObject(data)) { + return null; + } + return standardClasses.getStandardObjectName(data); + } + }; + Rule namespacesShouldBeDefinedInRootScope = new Rule() { + @Override + @Nullable + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + if (!(descriptor instanceof NamespaceDescriptor)) { + return null; + } + String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor); + return getRootScope().declareUnobfuscatableName(nameForNamespace); + } + }; + Rule memberDeclarationsInsideParentsScope = new Rule() { + @Override + @Nullable + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + NamingScope namingScope = getEnclosingScope(descriptor); + return namingScope.declareObfuscatableName(descriptor.getName()); + } + }; + Rule constructorHasTheSameNameAsTheClass = new Rule() { + @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 accessorsHasNamesWithSpecialPrefixes = new Rule() { + @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 namesAnnotatedAsLibraryHasUnobfuscatableNames = new Rule() { + @Override + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + //TODO: refactor + String name = null; + AnnotationDescriptor annotation = getAnnotationByName(descriptor, LIBRARY_ANNOTATION_FQNAME); + if (annotation != null) { + name = AnnotationsUtils.getAnnotationStringParameter(descriptor, LIBRARY_ANNOTATION_FQNAME); + name = (!name.isEmpty()) ? name : descriptor.getName(); + } else { + ClassDescriptor containingClass = getContainingClass(descriptor); + if (containingClass == null) return null; + if (getAnnotationByName(containingClass, LIBRARY_ANNOTATION_FQNAME) != null) { + name = descriptor.getName(); + } + } + if (name != null) { + return getEnclosingScope(descriptor).declareUnobfuscatableName(name); + } + return null; + } + }; + Rule propertiesCorrespondToSpeciallyTreatedBackingFieldNames = new Rule() { + @Override + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + if (!(descriptor instanceof PropertyDescriptor)) { + return null; + } + NamingScope enclosingScope = getEnclosingScope(descriptor); + return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName())); + } + }; + //TODO: hack! + Rule toStringHack = new Rule() { + @Override + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + if (!(descriptor instanceof FunctionDescriptor)) { + return null; + } + if (!descriptor.getName().equals("toString")) { + return null; + } + if (((FunctionDescriptor) descriptor).getValueParameters().isEmpty()) { + return getEnclosingScope(descriptor).declareUnobfuscatableName("toString"); + } + return null; + } + + }; + Rule namesForNativeObjectsAreUnobfuscatable = new Rule() { + @Override + public JsName apply(@NotNull DeclarationDescriptor descriptor) { + String name = null; + AnnotationDescriptor annotation = getAnnotationByName(descriptor, NATIVE_ANNOTATION_FQNAME); + if (annotation != null) { + name = AnnotationsUtils.getAnnotationStringParameter(descriptor, NATIVE_ANNOTATION_FQNAME); + name = (!name.isEmpty()) ? name : descriptor.getName(); + } else { + ClassDescriptor containingClass = getContainingClass(descriptor); + if (containingClass == null) return null; + if (getAnnotationByName(containingClass, NATIVE_ANNOTATION_FQNAME) != null) { + name = descriptor.getName(); + } + } + if (name != null) { + return getEnclosingScope(descriptor).declareUnobfuscatableName(name); + } + return null; + + } + }; + addRule(namesForStandardClasses); + addRule(aliasOverridesNames); + addRule(constructorHasTheSameNameAsTheClass); + addRule(namesAnnotatedAsLibraryHasUnobfuscatableNames); + addRule(namesForNativeObjectsAreUnobfuscatable); + addRule(toStringHack); + addRule(propertiesCorrespondToSpeciallyTreatedBackingFieldNames); + addRule(namespacesShouldBeDefinedInRootScope); + addRule(accessorsHasNamesWithSpecialPrefixes); + addRule(memberDeclarationsInsideParentsScope); + } + } + + private NamingScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) { + DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); + return getScopeForDescriptor(containingDeclaration.getOriginal()); + } + + + private class ScopeGenerator extends Generator { + + public ScopeGenerator() { + Rule generateNewScopesForNamespaceDescriptors = new Rule() { + @Override + public NamingScope apply(@NotNull DeclarationDescriptor descriptor) { + if (!(descriptor instanceof NamespaceDescriptor)) { + return null; + } + return getRootScope().innerScope("Namespace " + descriptor.getName()); + } + }; + Rule generateInnerScopesForMembers = new Rule() { + @Override + public NamingScope apply(@NotNull DeclarationDescriptor descriptor) { + NamingScope enclosingScope = getEnclosingScope(descriptor); + return enclosingScope.innerScope("scope for member " + descriptor.getName()); + } + }; + addRule(generateNewScopesForNamespaceDescriptors); + addRule(generateInnerScopesForMembers); + } + + } + + + private class QualifierGenerator extends Generator { + public QualifierGenerator() { + Rule namespacesHaveNoQualifiers = new Rule() { + @Override + public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { + if (!standardClasses.isStandardObject(descriptor)) { + return null; + } + return namer.kotlinObject(); + } + }; + Rule namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule() { + @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 constructorHaveTheSameQualifierAsTheClass = new Rule() { + @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 libraryObjectsHaveKotlinQualifier = new Rule() { + + //TODO: refactor by removing one annotation + @Override + public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { + if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_ANNOTATION_FQNAME) != null) { + return namer.kotlinObject(); + } + if (getAnnotationByName(descriptor, AnnotationsUtils.LIBRARY_ANNOTATION_FQNAME) != null) { + return namer.kotlinObject(); + } + return null; + } + }; + Rule membersOfAnnotatedClassesHaveKotlinQualifier = new Rule() { + @Override + public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { + ClassDescriptor containingClass = getContainingClass(descriptor); + if (containingClass == null) { + return null; + } + if (getAnnotationByName(descriptor, LIBRARY_ANNOTATION_FQNAME) != null) { + return namer.kotlinObject(); + } + return null; + } + }; + addRule(libraryObjectsHaveKotlinQualifier); + addRule(membersOfAnnotatedClassesHaveKotlinQualifier); + addRule(constructorHaveTheSameQualifierAsTheClass); + addRule(namespacesHaveNoQualifiers); + addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier); + } + } } \ No newline at end of file diff --git a/translator/src/org/jetbrains/k2js/translate/context/generator/Generator.java b/translator/src/org/jetbrains/k2js/translate/context/generator/Generator.java index 437ae33334a..f2553435ff9 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/generator/Generator.java +++ b/translator/src/org/jetbrains/k2js/translate/context/generator/Generator.java @@ -12,7 +12,7 @@ import java.util.Map; /** * @author Pavel Talanov */ -public final class Generator { +public class Generator { @NotNull