|
|
|
@@ -56,11 +56,11 @@ public class StaticContext {
|
|
|
|
|
private final NamingScope rootScope;
|
|
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
|
private final Generator<JsName> names = nameGenerator();
|
|
|
|
|
private final Generator<JsName> names = new NameGenerator();
|
|
|
|
|
@NotNull
|
|
|
|
|
private final Generator<NamingScope> scopes = scopeGenerator();
|
|
|
|
|
private final Generator<NamingScope> scopes = new ScopeGenerator();
|
|
|
|
|
@NotNull
|
|
|
|
|
private final Generator<JsNameRef> qualifiers = qualifierGenerator();
|
|
|
|
|
private final Generator<JsNameRef> qualifiers = new QualifierGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: too many parameters in constructor
|
|
|
|
@@ -112,260 +112,6 @@ public class StaticContext {
|
|
|
|
|
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
|
|
|
|
|
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<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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|