refactor generators to inner classes
This commit is contained in:
@@ -21,7 +21,7 @@ public abstract class Config {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static final String PATH_TO_JS_LIB_SRC = getPathToJsLibSrc();
|
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
|
@NotNull
|
||||||
private static final List<String> LIB_FILE_NAMES = Arrays.asList(
|
private static final List<String> LIB_FILE_NAMES = Arrays.asList(
|
||||||
PATH_TO_JS_LIB_SRC + "\\core\\annotations.kt",
|
PATH_TO_JS_LIB_SRC + "\\core\\annotations.kt",
|
||||||
|
|||||||
@@ -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.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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
@@ -12,29 +11,25 @@ public final class NamingScope {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static NamingScope rootScope(@NotNull JsScope rootScope) {
|
public static NamingScope rootScope(@NotNull JsScope rootScope) {
|
||||||
return new NamingScope(rootScope, null);
|
return new NamingScope(rootScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsScope scope;
|
private final JsScope scope;
|
||||||
|
|
||||||
@Nullable
|
private NamingScope(@NotNull JsScope correspondingScope) {
|
||||||
private final NamingScope parent;
|
|
||||||
|
|
||||||
private NamingScope(@NotNull JsScope correspondingScope, @Nullable NamingScope parent) {
|
|
||||||
this.scope = correspondingScope;
|
this.scope = correspondingScope;
|
||||||
this.parent = parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NamingScope innerScope(@NotNull String scopeName) {
|
public NamingScope innerScope(@NotNull String scopeName) {
|
||||||
JsScope innerJsScope = new JsScope(jsScope(), scopeName);
|
JsScope innerJsScope = new JsScope(jsScope(), scopeName);
|
||||||
return new NamingScope(innerJsScope, this);
|
return new NamingScope(innerJsScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NamingScope innerScope(@NotNull JsScope correspondingScope) {
|
public NamingScope innerScope(@NotNull JsScope correspondingScope) {
|
||||||
return new NamingScope(correspondingScope, this);
|
return new NamingScope(correspondingScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ public class StaticContext {
|
|||||||
private final NamingScope rootScope;
|
private final NamingScope rootScope;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Generator<JsName> names = nameGenerator();
|
private final Generator<JsName> names = new NameGenerator();
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Generator<NamingScope> scopes = scopeGenerator();
|
private final Generator<NamingScope> scopes = new ScopeGenerator();
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Generator<JsNameRef> qualifiers = qualifierGenerator();
|
private final Generator<JsNameRef> qualifiers = new QualifierGenerator();
|
||||||
|
|
||||||
|
|
||||||
//TODO: too many parameters in constructor
|
//TODO: too many parameters in constructor
|
||||||
@@ -112,260 +112,6 @@ public class StaticContext {
|
|||||||
return standardClasses;
|
return standardClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Generator<JsName> nameGenerator() {
|
|
||||||
|
|
||||||
Rule<JsName> aliasOverridesNames = new Rule<JsName>() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public JsName apply(@NotNull DeclarationDescriptor data) {
|
|
||||||
if (aliaser.hasAliasForDeclaration(data)) {
|
|
||||||
return aliaser.getAliasForDeclaration(data);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Rule<JsName> namesForStandardClasses = new Rule<JsName>() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public JsName apply(@NotNull DeclarationDescriptor data) {
|
|
||||||
if (!standardClasses.isStandardObject(data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return standardClasses.getStandardObjectName(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Rule<JsName> namespacesShouldBeDefinedInRootScope = new Rule<JsName>() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
|
||||||
if (!(descriptor instanceof NamespaceDescriptor)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor);
|
|
||||||
return getRootScope().declareUnobfuscatableName(nameForNamespace);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
|
||||||
NamingScope namingScope = getEnclosingScope(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> namesAnnotatedAsLibraryHasUnobfuscatableNames = new Rule<JsName>() {
|
|
||||||
@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<JsName> propertiesCorrespondToSpeciallyTreatedBackingFieldNames = new Rule<JsName>() {
|
|
||||||
@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<JsName> toStringHack = new Rule<JsName>() {
|
|
||||||
@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<JsName> namesForNativeObjectsAreUnobfuscatable = new Rule<JsName>() {
|
|
||||||
@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<JsName> nameGenerator = new Generator<JsName>();
|
|
||||||
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<NamingScope> scopeGenerator() {
|
|
||||||
Generator<NamingScope> scopeGenerator = new Generator<NamingScope>();
|
|
||||||
Rule<NamingScope> generateNewScopesForNamespaceDescriptors = new Rule<NamingScope>() {
|
|
||||||
@Override
|
|
||||||
public NamingScope apply(@NotNull DeclarationDescriptor descriptor) {
|
|
||||||
if (!(descriptor instanceof NamespaceDescriptor)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return getRootScope().innerScope("Namespace " + descriptor.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Rule<NamingScope> generateInnerScopesForMembers = new Rule<NamingScope>() {
|
|
||||||
@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<JsNameRef> qualifierGenerator() {
|
|
||||||
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> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
|
|
||||||
|
|
||||||
//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<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_ANNOTATION_FQNAME) != null) {
|
|
||||||
return namer.kotlinObject();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Generator<JsNameRef> qualifierGenerator = new Generator<JsNameRef>();
|
|
||||||
qualifierGenerator.addRule(libraryObjectsHaveKotlinQualifier);
|
|
||||||
qualifierGenerator.addRule(membersOfAnnotatedClassesHaveKotlinQualifier);
|
|
||||||
qualifierGenerator.addRule(constructorHaveTheSameQualifierAsTheClass);
|
|
||||||
qualifierGenerator.addRule(namespacesHaveNoQualifiers);
|
|
||||||
qualifierGenerator.addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier);
|
|
||||||
return qualifierGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
NamingScope namingScope = scopes.get(descriptor);
|
NamingScope namingScope = scopes.get(descriptor);
|
||||||
@@ -390,4 +136,254 @@ public class StaticContext {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class NameGenerator extends Generator<JsName> {
|
||||||
|
public NameGenerator() {
|
||||||
|
Rule<JsName> aliasOverridesNames = new Rule<JsName>() {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor data) {
|
||||||
|
if (aliaser.hasAliasForDeclaration(data)) {
|
||||||
|
return aliaser.getAliasForDeclaration(data);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Rule<JsName> namesForStandardClasses = new Rule<JsName>() {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor data) {
|
||||||
|
if (!standardClasses.isStandardObject(data)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return standardClasses.getStandardObjectName(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Rule<JsName> namespacesShouldBeDefinedInRootScope = new Rule<JsName>() {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor);
|
||||||
|
return getRootScope().declareUnobfuscatableName(nameForNamespace);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
NamingScope namingScope = getEnclosingScope(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> namesAnnotatedAsLibraryHasUnobfuscatableNames = new Rule<JsName>() {
|
||||||
|
@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<JsName> propertiesCorrespondToSpeciallyTreatedBackingFieldNames = new Rule<JsName>() {
|
||||||
|
@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<JsName> toStringHack = new Rule<JsName>() {
|
||||||
|
@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<JsName> namesForNativeObjectsAreUnobfuscatable = new Rule<JsName>() {
|
||||||
|
@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<NamingScope> {
|
||||||
|
|
||||||
|
public ScopeGenerator() {
|
||||||
|
Rule<NamingScope> generateNewScopesForNamespaceDescriptors = new Rule<NamingScope>() {
|
||||||
|
@Override
|
||||||
|
public NamingScope apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getRootScope().innerScope("Namespace " + descriptor.getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Rule<NamingScope> generateInnerScopesForMembers = new Rule<NamingScope>() {
|
||||||
|
@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<JsNameRef> {
|
||||||
|
public QualifierGenerator() {
|
||||||
|
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> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
|
||||||
|
|
||||||
|
//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<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_ANNOTATION_FQNAME) != null) {
|
||||||
|
return namer.kotlinObject();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addRule(libraryObjectsHaveKotlinQualifier);
|
||||||
|
addRule(membersOfAnnotatedClassesHaveKotlinQualifier);
|
||||||
|
addRule(constructorHaveTheSameQualifierAsTheClass);
|
||||||
|
addRule(namespacesHaveNoQualifiers);
|
||||||
|
addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
public final class Generator<V> {
|
public class Generator<V> {
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user