Big refactor of qname

The creation methods now mostly take the node to describe as parameter. That way, the implementation of the class is less exposed, the creation methods can be overloaded and simplified in the AST nodes' classes.

Only nested class do not do that. That is to keep the recursive call to getQualifiedName which would be much more complicated if it was called from QualifiedName rather than the AST node.
This commit is contained in:
oowekyala
2017-05-30 15:14:31 +02:00
parent 9ad46fbf88
commit c543cef8b1
5 changed files with 95 additions and 102 deletions

View File

@ -33,7 +33,7 @@ public class ASTClassOrInterfaceDeclaration extends AbstractJavaAccessTypeNode i
public boolean isNested() {
return jjtGetParent() instanceof ASTClassOrInterfaceBodyDeclaration
|| jjtGetParent() instanceof ASTAnnotationTypeMemberDeclaration;
|| jjtGetParent() instanceof ASTAnnotationTypeMemberDeclaration;
}
public boolean isInterface() {
@ -46,27 +46,17 @@ public class ASTClassOrInterfaceDeclaration extends AbstractJavaAccessTypeNode i
@Override
public QualifiedName getQualifiedName() {
if (qualifiedName != null) {
return qualifiedName;
if (qualifiedName == null) {
if (isNested()) {
ASTClassOrInterfaceDeclaration parent = this.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
QualifiedName parentQN = parent.getQualifiedName();
qualifiedName = QualifiedName.makeNestedClassOf(parentQN, this.getImage());
return qualifiedName;
}
qualifiedName = QualifiedName.makeOuterClassOf(this);
}
if (isNested()) {
ASTClassOrInterfaceDeclaration parent = this.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
QualifiedName parentQN = parent.getQualifiedName();
return QualifiedName.makeClassOf(parentQN, this.getImage());
}
QualifiedName qname = new QualifiedName();
ASTPackageDeclaration pkg = this.getFirstParentOfType(ASTCompilationUnit.class)
.getFirstChildOfType(ASTPackageDeclaration.class);
if (pkg != null) {
qname.setPackages(pkg.getPackageNameImage().split("\\."));
}
qname.setClass(this.getImage());
qualifiedName = qname;
return qualifiedName;
}
}

View File

@ -44,22 +44,9 @@ public class ASTConstructorDeclaration extends AbstractJavaAccessNode implements
@Override
public QualifiedName getQualifiedName() {
if (qualifiedName != null) {
return qualifiedName;
if (qualifiedName == null) {
qualifiedName = QualifiedName.makeOperationOf(this);
}
ASTClassOrInterfaceDeclaration parent = this.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
ASTFormalParameters params = this.getFirstDescendantOfType(ASTFormalParameters.class);
int numParams = params.jjtGetNumChildren();
String[] types = new String[numParams];
for (int i = 0; i < numParams; i++) {
types[i] = params.jjtGetChild(i).getFirstDescendantOfType(ASTType.class).getTypeImage();
}
qualifiedName = QualifiedName.makeOperationOf(parent.getQualifiedName(), parent.getImage(), types);
return qualifiedName;
}
}

View File

@ -114,22 +114,9 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
@Override
public QualifiedName getQualifiedName() {
if (qualifiedName != null) {
return qualifiedName;
if (qualifiedName == null) {
qualifiedName = QualifiedName.makeOperationOf(this);
}
QualifiedName parent = this.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class).getQualifiedName();
ASTFormalParameters params = this.getFirstDescendantOfType(ASTFormalParameters.class);
int numParams = params.jjtGetNumChildren();
String[] types = new String[numParams];
for (int i = 0; i < numParams; i++) {
types[i] = params.jjtGetChild(i).getFirstDescendantOfType(ASTType.class).getTypeImage();
}
qualifiedName = QualifiedName.makeOperationOf(parent, getMethodName(), types);
return qualifiedName;
}
}

View File

@ -15,21 +15,56 @@ public class QualifiedName {
private String[] classes = new String[1];
private String operation = null;
public QualifiedName() {
private QualifiedName() {
}
/** Builds a QName for an operation using the QName of the enclosing class */
public static QualifiedName makeOperationOf(QualifiedName parentClass, String operationName, String[] paramTypes) {
/**
* Builds the qualified name of a method declaration
*
* @param node The method declaration node
*
* @return The qualified name of the node
*/
public static QualifiedName makeOperationOf(ASTMethodDeclaration node) {
QualifiedName parentQname = node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class).getQualifiedName();
QualifiedName qname = new QualifiedName();
qname.packages = parentClass.packages;
qname.classes = parentClass.classes;
qname.operation = getOperationName(operationName, paramTypes);
qname.packages = parentQname.packages;
qname.classes = parentQname.classes;
qname.operation = getOperationName(node.getMethodName(), node.getFirstDescendantOfType(ASTFormalParameters.class));
return qname;
}
/** Builds a nested class QName using the QName of its immediate parent */
public static QualifiedName makeClassOf(QualifiedName parent, String className) {
/**
* Builds the qualified name of a constructor declaration
*
* @param node The constructor declaration node
*
* @return The qualified name of the node
*/
public static QualifiedName makeOperationOf(ASTConstructorDeclaration node) {
ASTClassOrInterfaceDeclaration parent = node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
QualifiedName qname = new QualifiedName();
QualifiedName parentQName = parent.getQualifiedName();
qname.packages = parentQName.packages;
qname.classes = parentQName.classes;
qname.operation = getOperationName(parent.getImage(), node.getFirstDescendantOfType(ASTFormalParameters.class));
return qname;
}
/**
* Builds a nested class QName using the QName of its immediate parent
*
* @param parent The qname of the immediate parent
* @param className The name of the class
*
* @return The qualified name of the nested class
*/
public static QualifiedName makeNestedClassOf(QualifiedName parent, String className) {
QualifiedName qname = new QualifiedName();
qname.packages = parent.packages;
if (parent.classes[0] != null) {
@ -42,24 +77,46 @@ public class QualifiedName {
return qname;
}
/**
* Builds the QName of an outer (not nested) class.
*
* @param node The class node
*
* @return The qualified name of the node
*/
public static QualifiedName makeOuterClassOf(ASTClassOrInterfaceDeclaration node) {
ASTPackageDeclaration pkg = node.getFirstParentOfType(ASTCompilationUnit.class)
.getFirstChildOfType(ASTPackageDeclaration.class);
QualifiedName qname = new QualifiedName();
qname.packages = pkg == null ? null : pkg.getPackageNameImage().split("\\.");
qname.classes[0] = node.getImage();
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!) */
private static String getOperationName(String methodName, String[] paramTypes) {
private static String getOperationName(String methodName, ASTFormalParameters params) {
StringBuilder sb = new StringBuilder();
sb.append(methodName);
sb.append('(');
int last = paramTypes.length - 1;
int last = params.getParameterCount() - 1;
for (int i = 0; i < last; i++) {
sb.append(paramTypes[i]);
// append type image of param
sb.append(params.jjtGetChild(i).getFirstDescendantOfType(ASTType.class).getTypeImage());
sb.append(',');
}
if (last > -1) {
sb.append(paramTypes[last]);
sb.append(params.jjtGetChild(last).getFirstDescendantOfType(ASTType.class).getTypeImage());
}
sb.append(')');
@ -67,30 +124,15 @@ public class QualifiedName {
return sb.toString();
}
/** Sets the class to the specified name, truncates the array to length of one */
public void setClass(String className) {
if (classes.length == 1) {
classes[0] = className;
return;
}
classes = new String[]{className};
}
public String[] getPackages() {
return packages;
}
public void setPackages(String[] packs) {
packages = packs;
}
public String[] getClasses() {
return classes;
}
public String getOperation() {
return operation;
}

View File

@ -25,7 +25,7 @@ public class QualifiedNameTest extends ParserTst {
public void testEmptyPackage() {
final String TEST = "class Foo {}";
Set<ASTClassOrInterfaceDeclaration> nodes = getNodes(ASTClassOrInterfaceDeclaration.class,
TEST);
TEST);
for (ASTClassOrInterfaceDeclaration coid : nodes) {
QualifiedName qname = coid.getQualifiedName();
assertEquals(".Foo", qname.toString());
@ -40,7 +40,7 @@ public class QualifiedNameTest extends ParserTst {
final String TEST = "package foo.bar; class Bzaz{}";
Set<ASTClassOrInterfaceDeclaration> nodes = getNodes(ASTClassOrInterfaceDeclaration.class,
TEST);
TEST);
for (ASTClassOrInterfaceDeclaration coid : nodes) {
QualifiedName qname = coid.getQualifiedName();
assertEquals("foo.bar.Bzaz", qname.toString());
@ -56,14 +56,14 @@ public class QualifiedNameTest extends ParserTst {
Set<ASTClassOrInterfaceDeclaration> nodes = getNodes(ASTClassOrInterfaceDeclaration.class,
TEST);
TEST);
for (ASTClassOrInterfaceDeclaration coid : nodes) {
QualifiedName qname = coid.getQualifiedName();
switch (coid.getImage()) {
case "Foo":
assertEquals("foo.bar.Bzaz$Bor$Foo",
qname.toString());
qname.toString());
assertEquals(3, qname.getClasses().length);
break;
default:
@ -78,14 +78,14 @@ public class QualifiedNameTest extends ParserTst {
Set<ASTClassOrInterfaceDeclaration> nodes = getNodes(ASTClassOrInterfaceDeclaration.class,
TEST);
TEST);
for (ASTClassOrInterfaceDeclaration coid : nodes) {
QualifiedName qname = coid.getQualifiedName();
switch (coid.getImage()) {
case "Foo":
assertEquals(".Bzaz$Bor$Foo",
qname.toString());
qname.toString());
assertNull(qname.getPackages());
assertEquals(3, qname.getClasses().length);
break;
@ -101,7 +101,7 @@ public class QualifiedNameTest extends ParserTst {
Set<ASTMethodDeclaration> nodes = getNodes(ASTMethodDeclaration.class,
TEST);
TEST);
for (ASTMethodDeclaration declaration : nodes) {
QualifiedName qname = declaration.getQualifiedName();
@ -118,12 +118,12 @@ public class QualifiedNameTest extends ParserTst {
Set<ASTConstructorDeclaration> nodes = getNodes(ASTConstructorDeclaration.class,
TEST);
TEST);
for (ASTConstructorDeclaration declaration : nodes) {
QualifiedName qname = declaration.getQualifiedName();
assertEquals("bar.Bzaz#Bzaz()",
qname.toString());
qname.toString());
assertNotNull(qname.getOperation());
assertEquals("Bzaz()", qname.getOperation());
@ -136,7 +136,7 @@ public class QualifiedNameTest extends ParserTst {
Set<ASTConstructorDeclaration> nodes = getNodes(ASTConstructorDeclaration.class,
TEST);
TEST);
for (ASTConstructorDeclaration declaration : nodes) {
QualifiedName qname = declaration.getQualifiedName();
@ -147,25 +147,12 @@ public class QualifiedNameTest extends ParserTst {
}
}
@Test
public void testEquals() {
final String TEST = "package bar; class Bzaz{ public foo() {} public Bzaz(int j, String k){}}";
Set<ASTConstructorDeclaration> nodes = getNodes(ASTConstructorDeclaration.class,
TEST);
for (ASTConstructorDeclaration declaration : nodes) {
QualifiedName qname = declaration.getQualifiedName();
assertEquals(qname, qname.toString());
}
}
@Test
public void testConstructorOverload() {
final String TEST = "package bar; class Bzaz{ public Bzaz(int j) {} public Bzaz(int j, String k){}}";
Set<ASTConstructorDeclaration> nodes = getNodes(ASTConstructorDeclaration.class,
TEST);
TEST);
ASTConstructorDeclaration[] arr = nodes.toArray(new ASTConstructorDeclaration[2]);
assertNotEquals(arr[0].getQualifiedName(), arr[1].getQualifiedName());
@ -174,7 +161,7 @@ public class QualifiedNameTest extends ParserTst {
@Test
public void testMethodOverload() {
final String TEST = "package bar; class Bzaz{ public void foo(String j) {} "
+ "public void foo(int j){} public void foo(double k){}}";
+ "public void foo(int j){} public void foo(double k){}}";
Set<ASTMethodDeclaration> nodes = getNodes(ASTMethodDeclaration.class, TEST);