1 4 package net.sourceforge.pmd.rules; 5 6 import net.sourceforge.pmd.AbstractRule; 7 import net.sourceforge.pmd.ast.ASTAllocationExpression; 8 import net.sourceforge.pmd.ast.ASTArguments; 9 import net.sourceforge.pmd.ast.ASTArrayDimsAndInits; 10 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; 11 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType; 12 import net.sourceforge.pmd.ast.ASTCompilationUnit; 13 import net.sourceforge.pmd.ast.ASTConstructorDeclaration; 14 import net.sourceforge.pmd.ast.ASTEnumDeclaration; 15 16 import java.util.ArrayList ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.ListIterator ; 20 21 35 public class AccessorClassGeneration extends AbstractRule { 36 37 private List classDataList = new ArrayList (); 38 private int classID = -1; 39 private String packageName; 40 41 public Object visit(ASTEnumDeclaration node, Object data) { 42 return data; } 44 45 public Object visit(ASTCompilationUnit node, Object data) { 46 classDataList.clear(); 47 packageName = node.getScope().getEnclosingSourceFileScope().getPackageName(); 48 return super.visit(node, data); 49 } 50 51 private static class ClassData { 52 private String m_ClassName; 53 private List m_PrivateConstructors; 54 private List m_Instantiations; 55 58 private List m_ClassQualifyingNames; 59 60 public ClassData(String className) { 61 m_ClassName = className; 62 m_PrivateConstructors = new ArrayList (); 63 m_Instantiations = new ArrayList (); 64 m_ClassQualifyingNames = new ArrayList (); 65 } 66 67 public void addInstantiation(AllocData ad) { 68 m_Instantiations.add(ad); 69 } 70 71 public Iterator getInstantiationIterator() { 72 return m_Instantiations.iterator(); 73 } 74 75 public void addConstructor(ASTConstructorDeclaration cd) { 76 m_PrivateConstructors.add(cd); 77 } 78 79 public Iterator getPrivateConstructorIterator() { 80 return m_PrivateConstructors.iterator(); 81 } 82 83 public String getClassName() { 84 return m_ClassName; 85 } 86 87 public void addClassQualifyingName(String name) { 88 m_ClassQualifyingNames.add(name); 89 } 90 91 public List getClassQualifyingNamesList() { 92 return m_ClassQualifyingNames; 93 } 94 } 95 96 private static class AllocData { 97 private String m_Name; 98 private int m_ArgumentCount; 99 private ASTAllocationExpression m_ASTAllocationExpression; 100 private boolean isArray; 101 102 public AllocData(ASTAllocationExpression node, String aPackageName, List classQualifyingNames) { 103 if (node.jjtGetChild(1) instanceof ASTArguments) { 104 ASTArguments aa = (ASTArguments) node.jjtGetChild(1); 105 m_ArgumentCount = aa.getArgumentCount(); 106 if (!(node.jjtGetChild(0) instanceof ASTClassOrInterfaceType)) { 109 throw new RuntimeException ("BUG: Expected a ASTClassOrInterfaceType, got a " + node.jjtGetChild(0).getClass()); 110 } 111 ASTClassOrInterfaceType an = (ASTClassOrInterfaceType) node.jjtGetChild(0); 112 m_Name = stripString(aPackageName + ".", an.getImage()); 113 114 String findName = ""; 117 for (ListIterator li = classQualifyingNames.listIterator(classQualifyingNames.size()); li.hasPrevious();) { 118 String aName = (String ) li.previous(); 119 findName = aName + "." + findName; 120 if (m_Name.startsWith(findName)) { 121 m_Name = m_Name.substring(findName.length()); 123 break; 124 } 125 } 126 } else if (node.jjtGetChild(1) instanceof ASTArrayDimsAndInits) { 127 isArray = true; 130 } 131 m_ASTAllocationExpression = node; 132 } 133 134 public String getName() { 135 return m_Name; 136 } 137 138 public int getArgumentCount() { 139 return m_ArgumentCount; 140 } 141 142 public ASTAllocationExpression getASTAllocationExpression() { 143 return m_ASTAllocationExpression; 144 } 145 146 public boolean isArray() { 147 return isArray; 148 } 149 } 150 151 154 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { 155 if (node.isInterface()) { 156 if (!(node.jjtGetParent().jjtGetParent() instanceof ASTCompilationUnit)) { 157 String interfaceName = node.getImage(); 159 int formerID = getClassID(); 160 setClassID(classDataList.size()); 161 ClassData newClassData = new ClassData(interfaceName); 162 ClassData formerClassData = (ClassData) classDataList.get(formerID); 164 newClassData.addClassQualifyingName(formerClassData.getClassName()); 165 classDataList.add(getClassID(), newClassData); 166 Object o = super.visit(node, data); 167 setClassID(formerID); 168 return o; 169 } else { 170 String interfaceName = node.getImage(); 171 classDataList.clear(); 172 setClassID(0); 173 classDataList.add(getClassID(), new ClassData(interfaceName)); 174 Object o = super.visit(node, data); 175 if (o != null) { 176 processRule(o); 177 } else { 178 processRule(data); 179 } 180 setClassID(-1); 181 return o; 182 } 183 } else if (!(node.jjtGetParent().jjtGetParent() instanceof ASTCompilationUnit)) { 184 String className = node.getImage(); 186 int formerID = getClassID(); 187 setClassID(classDataList.size()); 188 ClassData newClassData = new ClassData(className); 189 if (formerID == -1 || formerID >= classDataList.size()) { 194 return null; 195 } 196 ClassData formerClassData = (ClassData) classDataList.get(formerID); 198 newClassData.addClassQualifyingName(formerClassData.getClassName()); 199 classDataList.add(getClassID(), newClassData); 200 Object o = super.visit(node, data); 201 setClassID(formerID); 202 return o; 203 } 204 String className = node.getImage(); 206 classDataList.clear(); 207 setClassID(0); classDataList.add(getClassID(), new ClassData(className)); 209 Object o = super.visit(node, data); 210 if (o != null) { 211 processRule(o); 212 } else { 213 processRule(data); 214 } 215 setClassID(-1); 216 return o; 217 } 218 219 222 public Object visit(ASTConstructorDeclaration node, Object data) { 223 if (node.isPrivate()) { 224 getCurrentClassData().addConstructor(node); 225 } 226 return super.visit(node, data); 227 } 228 229 public Object visit(ASTAllocationExpression node, Object data) { 230 if (classID == -1 || getCurrentClassData() == null) { 235 return data; 236 } 237 AllocData ad = new AllocData(node, packageName, getCurrentClassData().getClassQualifyingNamesList()); 238 if (!ad.isArray()) { 239 getCurrentClassData().addInstantiation(ad); 240 } 241 return super.visit(node, data); 242 } 243 244 private void processRule(Object ctx) { 245 for (Iterator outerIterator = classDataList.iterator(); outerIterator.hasNext();) { 247 ClassData outerDataSet = (ClassData) outerIterator.next(); 248 for (Iterator constructors = outerDataSet.getPrivateConstructorIterator(); constructors.hasNext();) { 249 ASTConstructorDeclaration cd = (ASTConstructorDeclaration) constructors.next(); 250 251 for (Iterator innerIterator = classDataList.iterator(); innerIterator.hasNext();) { 252 ClassData innerDataSet = (ClassData) innerIterator.next(); 253 if (outerDataSet == innerDataSet) { 254 continue; 255 } 256 for (Iterator allocations = innerDataSet.getInstantiationIterator(); allocations.hasNext();) { 257 AllocData ad = (AllocData) allocations.next(); 258 if (outerDataSet.getClassName().equals(ad.getName()) && (cd.getParameterCount() == ad.getArgumentCount())) { 261 addViolation(ctx, ad.getASTAllocationExpression()); 262 } 263 } 264 } 265 } 266 } 267 } 268 269 private ClassData getCurrentClassData() { 270 if (classID >= classDataList.size()) { 275 return null; 276 } 277 return (ClassData) classDataList.get(classID); 278 } 279 280 private void setClassID(int ID) { 281 classID = ID; 282 } 283 284 private int getClassID() { 285 return classID; 286 } 287 288 private static String stripString(String remove, String value) { 297 String returnValue; 298 int index = value.indexOf(remove); 299 if (index != -1) { returnValue = value.substring(0, index) + value.substring(index + remove.length()); 301 } else { 302 returnValue = value; 303 } 304 return returnValue; 305 } 306 307 } 308 | Popular Tags |