1 package org.incava.java; 2 3 import java.util.*; 4 import net.sourceforge.pmd.ast.*; 5 import org.incava.util.ReverseComparator; 6 7 8 /** 9 * Miscellaneous routines for type declarations. 10 */ 11 public class TypeDeclarationUtil extends SimpleNodeUtil 12 { getName(ASTTypeDeclaration typeDecl)13 public static Token getName(ASTTypeDeclaration typeDecl) 14 { 15 ASTClassOrInterfaceDeclaration cidecl = (ASTClassOrInterfaceDeclaration)findChild(typeDecl, ASTClassOrInterfaceDeclaration.class); 16 return cidecl == null ? null : cidecl.getFirstToken().next; 17 } 18 getType(ASTTypeDeclaration typeDecl)19 public static ASTClassOrInterfaceDeclaration getType(ASTTypeDeclaration typeDecl) 20 { 21 return (ASTClassOrInterfaceDeclaration)SimpleNodeUtil.findChild(typeDecl, ASTClassOrInterfaceDeclaration.class); 22 } 23 findTypeDeclaration(String name, ASTTypeDeclaration[] types)24 public static ASTTypeDeclaration findTypeDeclaration(String name, ASTTypeDeclaration[] types) 25 { 26 for (int i = 0; i < types.length; ++i) { 27 ASTTypeDeclaration type = types[i]; 28 Token otherName = getName(type); 29 30 if ((otherName == null && name == null) || 31 (otherName != null && otherName.image.equals(name))) { 32 return type; 33 } 34 } 35 36 return null; 37 } 38 39 /** 40 * Returns a list of all methods, fields, constructors, and inner classes 41 * and interfaces. 42 */ getDeclarations(ASTTypeDeclaration tdecl)43 public static ASTClassOrInterfaceBodyDeclaration[] getDeclarations(ASTTypeDeclaration tdecl) 44 { 45 ASTClassOrInterfaceDeclaration cidecl = (ASTClassOrInterfaceDeclaration)findChild(tdecl, ASTClassOrInterfaceDeclaration.class); 46 return getDeclarations(cidecl); 47 } 48 49 /** 50 * Returns a list of all methods, fields, constructors, and inner classes 51 * and interfaces. 52 */ getDeclarations(ASTClassOrInterfaceDeclaration coid)53 public static ASTClassOrInterfaceBodyDeclaration[] getDeclarations(ASTClassOrInterfaceDeclaration coid) 54 { 55 ASTClassOrInterfaceBody body = (ASTClassOrInterfaceBody)findChild(coid, ASTClassOrInterfaceBody.class); 56 return (ASTClassOrInterfaceBodyDeclaration[])findChildren(body, ASTClassOrInterfaceBodyDeclaration.class); 57 } 58 59 /** 60 * Returns the real declaration, which is a method, field, constructor, or 61 * inner class or interface. 62 */ getDeclaration(ASTClassOrInterfaceBodyDeclaration bdecl)63 public static SimpleNode getDeclaration(ASTClassOrInterfaceBodyDeclaration bdecl) 64 { 65 return hasChildren(bdecl) ? findChild(bdecl, null) : null; 66 } 67 matchDeclarations(ASTClassOrInterfaceBodyDeclaration[] aDecls, ASTClassOrInterfaceBodyDeclaration[] bDecls)68 public static TreeMap matchDeclarations(ASTClassOrInterfaceBodyDeclaration[] aDecls, ASTClassOrInterfaceBodyDeclaration[] bDecls) 69 { 70 // keys (scores) maintained in reversed order: 71 TreeMap byScore = new TreeMap(new ReverseComparator()); 72 73 // map b by declaration types 74 75 tr.Ace.log("aDecls", aDecls); 76 tr.Ace.log("bDecls", bDecls); 77 78 for (int ai = 0; ai < aDecls.length; ++ai) { 79 ASTClassOrInterfaceBodyDeclaration aNode = aDecls[ai]; 80 SimpleNode an = getDeclaration(aNode); 81 List scores = new ArrayList(); 82 83 for (int bi = 0; bi < bDecls.length; ++bi) { 84 ASTClassOrInterfaceBodyDeclaration bNode = bDecls[bi]; 85 86 double score = getMatchScore(aNode, bNode); 87 if (score > 0.0) { 88 Double dScore = new Double(score); 89 List atScore = (List)byScore.get(dScore); 90 if (atScore == null) { 91 atScore = new ArrayList(); 92 byScore.put(dScore, atScore); 93 } 94 atScore.add(new Object[] { aNode, bNode }); 95 } 96 } 97 } 98 99 List aSeen = new ArrayList(); 100 List bSeen = new ArrayList(); 101 Set scores = byScore.keySet(); 102 Iterator sit = scores.iterator(); 103 104 while (sit.hasNext()) { 105 Double dScore = (Double)sit.next(); 106 List atScore = (List)byScore.get(dScore); 107 Iterator vit = atScore.iterator(); 108 109 while (vit.hasNext()) { 110 Object[] values = (Object[])vit.next(); 111 SimpleNode a = (SimpleNode)values[0]; 112 SimpleNode b = (SimpleNode)values[1]; 113 114 if (aSeen.contains(a)) { 115 // a already seen 116 vit.remove(); 117 } 118 else if (bSeen.contains(b)) { 119 // b already seen 120 vit.remove(); 121 } 122 else { 123 // neither already seen 124 aSeen.add(a); 125 bSeen.add(b); 126 } 127 } 128 129 if (atScore.size() == 0) { 130 // remove the empty list 131 sit.remove(); 132 } 133 } 134 135 return byScore; 136 } 137 getMatchScore(ASTClassOrInterfaceBodyDeclaration aDecl, ASTClassOrInterfaceBodyDeclaration bDecl)138 public static double getMatchScore(ASTClassOrInterfaceBodyDeclaration aDecl, ASTClassOrInterfaceBodyDeclaration bDecl) 139 { 140 SimpleNode a = getDeclaration(aDecl); 141 SimpleNode b = getDeclaration(bDecl); 142 143 double score = 0.0; 144 if (a == null && b == null) { 145 score = 1.0; 146 } 147 else if (a == null || b == null) { 148 // not a match. 149 } 150 else if (a.getClass().equals(b.getClass())) { 151 if (a instanceof ASTMethodDeclaration) { 152 score = MethodUtil.getMatchScore((ASTMethodDeclaration)a, (ASTMethodDeclaration)b); 153 } 154 else if (a instanceof ASTFieldDeclaration) { 155 // compare by name 156 score = FieldUtil.getMatchScore((ASTFieldDeclaration)a, (ASTFieldDeclaration)b); 157 } 158 else if (a instanceof ASTConstructorDeclaration) { 159 score = CtorUtil.getMatchScore((ASTConstructorDeclaration)a, (ASTConstructorDeclaration)b); 160 } 161 else if (a instanceof ASTClassOrInterfaceDeclaration) { 162 ASTClassOrInterfaceDeclaration acoid = (ASTClassOrInterfaceDeclaration)a; 163 ASTClassOrInterfaceDeclaration bcoid = (ASTClassOrInterfaceDeclaration)b; 164 score = ClassUtil.getMatchScore(acoid, bcoid); 165 } 166 else { 167 // WTF? 168 tr.Ace.stack(tr.Ace.RED, "a", a); 169 } 170 } 171 172 return score; 173 } 174 175 } 176