diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/QualifiableNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/QualifiableNode.java index fb37ba573c..cc42a753d9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/QualifiableNode.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/QualifiableNode.java @@ -7,6 +7,8 @@ package net.sourceforge.pmd.lang.java.ast; import java.util.Arrays; /** + * Nodes that can be described with a qualified name. + * * @author Clément Fournier */ public interface QualifiableNode { @@ -19,8 +21,17 @@ public interface QualifiableNode { char PARAMLIST_SEP = ','; char PACKAGE_SEP = '.'; + /** + * Returns a qualified name for this node. + * + * @return A qualified name. + */ QualifiedName getQualifiedName(); + /** + * Represents Qualified Names for use within PackageStats + * TODO make unit tests once the visitor is working to ensure new implementations won't break it + */ class QualifiedName { private String[] packages = null; // unnamed package private String[] classes = new String[1]; @@ -29,15 +40,17 @@ public interface QualifiableNode { public QualifiedName() { } + /** Builds a QName for an operation using the QName of the enclosing class */ public static QualifiedName makeOperationOf(QualifiedName parentClass, String operationName, String[] paramTypes) { QualifiedName qname = new QualifiedName(); qname.packages = parentClass.packages; qname.classes = parentClass.classes; - qname.setOperation(operationName, paramTypes); + qname.operation = getOperationName(operationName, paramTypes); return qname; } + /** Builds a nested class QName using the QName of its immediate parent */ public static QualifiedName makeClassOf(QualifiedName parent, String className) { QualifiedName qname = new QualifiedName(); qname.packages = parent.packages; @@ -51,18 +64,54 @@ public interface QualifiableNode { return qname; } + // Might be useful with type resolution + public static QualifiedName parseCanonicalName(String canon) { + throw new UnsupportedOperationException(); + } + + /** Returns a normalized method name (not Java-canonical!) */ + public static String getOperationName(String methodName, String[] paramTypes) { + StringBuilder sb = new StringBuilder(); + sb.append(methodName); + sb.append(LEFT_PARAM_SEP); + int last = paramTypes.length - 1; + for (int i = 0; i < last; i++) { + sb.append(paramTypes[i]); + sb.append(PARAMLIST_SEP); + } + + if (last > -1) { + sb.append(paramTypes[last]); + } + + sb.append(RIGHT_PARAM_SEP); + + return sb.toString(); + } + + /** Is this QName describing a class? */ + // Probably useless public boolean isClass() { return classes[0] != null && operation == null; } + /** Sets the class to the specified name, truncates the array to length of one */ public void setClass(String className) { - classes[0] = className; + if (classes.length == 1) { + classes[0] = className; + return; + } + + classes = new String[]{className}; + } + // Probably useless public boolean isNestedClass() { return classes.length > 1 && operation == null; } + // Probably useless public boolean isOperation() { return operation != null; } @@ -79,6 +128,7 @@ public interface QualifiableNode { return classes; } + // Probably useless public void setClasses(String[] classes) { this.classes = classes; } @@ -87,26 +137,6 @@ public interface QualifiableNode { return operation; } - - public void setOperation(String methodName, String[] paramTypes) { - StringBuilder sb = new StringBuilder(); - sb.append(methodName); - sb.append(LEFT_PARAM_SEP); - int last = paramTypes.length - 1; - for (int i = 0; i < last; i++) { - sb.append(paramTypes[i]); - sb.append(PARAMLIST_SEP); - } - - if (last > -1) { - sb.append(paramTypes[last]); - } - - sb.append(RIGHT_PARAM_SEP); - - this.operation = sb.toString(); - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -120,7 +150,7 @@ public interface QualifiableNode { sb.append(packages[last]); } - sb.append(LEFT_CLASS_SEP); // class delimiter is there anyway + sb.append(LEFT_CLASS_SEP); // class delimiter is there even if package null int last = classes.length - 1; for (int i = 0; i < last; i++) {