Fix anonymous class naming
- Properly handle nested anonymous classes
This commit is contained in:
@ -14,7 +14,6 @@ import java.util.Map;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sourceforge.pmd.lang.ast.AbstractNode;
|
|
||||||
import net.sourceforge.pmd.lang.ast.Node;
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||||
@ -24,6 +23,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTArguments;
|
|||||||
import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
|
import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
|
import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTCastExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTCastExpression;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||||
@ -31,6 +31,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression;
|
|||||||
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTEnumBody;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTExclusiveOrExpression;
|
import net.sourceforge.pmd.lang.java.ast.ASTExclusiveOrExpression;
|
||||||
@ -149,7 +150,16 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
|
|||||||
private final PMDASMClassLoader pmdClassLoader;
|
private final PMDASMClassLoader pmdClassLoader;
|
||||||
private Map<String, String> importedClasses;
|
private Map<String, String> importedClasses;
|
||||||
private List<String> importedOnDemand;
|
private List<String> importedOnDemand;
|
||||||
private int anonymousClassCounter = 0;
|
private Map<Node, AnonymousClassMetadata> anonymousClassMetadata = new HashMap<>();
|
||||||
|
|
||||||
|
private static class AnonymousClassMetadata {
|
||||||
|
public final String name;
|
||||||
|
public int anonymousClassCounter;
|
||||||
|
|
||||||
|
AnonymousClassMetadata(final String className) {
|
||||||
|
this.name = className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ClassTypeResolver() {
|
public ClassTypeResolver() {
|
||||||
this(ClassTypeResolver.class.getClassLoader());
|
this(ClassTypeResolver.class.getClassLoader());
|
||||||
@ -227,12 +237,11 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
|
|||||||
String typeName = node.getImage();
|
String typeName = node.getImage();
|
||||||
|
|
||||||
if (node.isAnonymousClass()) {
|
if (node.isAnonymousClass()) {
|
||||||
anonymousClassCounter++;
|
final AnonymousClassMetadata parentAnonymousClassMetadata = getParentAnonymousClassMetadata(node);
|
||||||
AbstractNode parent = node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
if (parentAnonymousClassMetadata != null) {
|
||||||
if (parent == null) {
|
typeName = parentAnonymousClassMetadata.name + "$" + ++parentAnonymousClassMetadata.anonymousClassCounter;
|
||||||
parent = node.getFirstParentOfType(ASTEnumDeclaration.class);
|
anonymousClassMetadata.put(node, new AnonymousClassMetadata(typeName));
|
||||||
}
|
}
|
||||||
typeName = parent.getImage() + "$" + anonymousClassCounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
populateType(node, typeName);
|
populateType(node, typeName);
|
||||||
@ -251,6 +260,52 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AnonymousClassMetadata getParentAnonymousClassMetadata(final ASTClassOrInterfaceType node) {
|
||||||
|
Node parent = node;
|
||||||
|
do {
|
||||||
|
parent = parent.jjtGetParent();
|
||||||
|
} while (parent != null && !(parent instanceof ASTClassOrInterfaceBody) && !(parent instanceof ASTEnumBody));
|
||||||
|
|
||||||
|
// TODO : Should never happen, but add this for safety until we are sure to cover all possible scenarios in unit testing
|
||||||
|
if (parent == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.jjtGetParent();
|
||||||
|
|
||||||
|
TypeNode typedParent;
|
||||||
|
// The parent may now be an ASTEnumConstant, an ASTAllocationExpression, an ASTEnumDeclaration or an ASTClassOrInterfaceDeclaration
|
||||||
|
if (parent instanceof ASTAllocationExpression) {
|
||||||
|
typedParent = parent.getFirstChildOfType(ASTClassOrInterfaceType.class);
|
||||||
|
} else if (parent instanceof ASTClassOrInterfaceDeclaration || parent instanceof ASTEnumDeclaration) {
|
||||||
|
typedParent = (TypeNode) parent;
|
||||||
|
} else {
|
||||||
|
typedParent = parent.getFirstParentOfType(ASTEnumDeclaration.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AnonymousClassMetadata metadata = anonymousClassMetadata.get(typedParent);
|
||||||
|
if (metadata != null) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
final AnonymousClassMetadata newMetadata;
|
||||||
|
if (typedParent instanceof ASTClassOrInterfaceType) {
|
||||||
|
ASTClassOrInterfaceType parentTypeNode = (ASTClassOrInterfaceType) typedParent;
|
||||||
|
if (parentTypeNode.isAnonymousClass()) {
|
||||||
|
final AnonymousClassMetadata parentMetadata = getParentAnonymousClassMetadata(parentTypeNode);
|
||||||
|
newMetadata = new AnonymousClassMetadata(parentMetadata.name + "$" + ++parentMetadata.anonymousClassCounter);
|
||||||
|
} else {
|
||||||
|
newMetadata = new AnonymousClassMetadata(parentTypeNode.getImage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newMetadata = new AnonymousClassMetadata(typedParent.getImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
anonymousClassMetadata.put(typedParent, newMetadata);
|
||||||
|
|
||||||
|
return newMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
||||||
populateType(node, node.getImage());
|
populateType(node, node.getImage());
|
||||||
|
Reference in New Issue
Block a user