1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.typeresolution;
5
6 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
7 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
8 import net.sourceforge.pmd.ast.ASTCompilationUnit;
9 import net.sourceforge.pmd.ast.ASTImportDeclaration;
10 import net.sourceforge.pmd.ast.ASTName;
11 import net.sourceforge.pmd.ast.ASTPackageDeclaration;
12 import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
13
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19
20 public class ClassTypeResolver extends JavaParserVisitorAdapter {
21
22 private static Map myPrimitiveTypes;
23
24 private static PMDASMClassLoader pmdClassLoader = new PMDASMClassLoader();
25
26 static {
27 Map thePrimitiveTypes = new HashMap();
28 thePrimitiveTypes.put("short", Short.TYPE);
29 thePrimitiveTypes.put("byte", Byte.TYPE);
30 thePrimitiveTypes.put("char", Character.TYPE);
31 thePrimitiveTypes.put("int", Integer.TYPE);
32 thePrimitiveTypes.put("long", Long.TYPE);
33 thePrimitiveTypes.put("float", Float.TYPE);
34 thePrimitiveTypes.put("double", Double.TYPE);
35 thePrimitiveTypes.put("boolean", Boolean.TYPE);
36 thePrimitiveTypes.put("void", Void.TYPE);
37 myPrimitiveTypes = Collections.unmodifiableMap(thePrimitiveTypes);
38 }
39
40 private Map importedClasses;
41
42 private String className;
43
44 public Object visit(ASTCompilationUnit node, Object data) {
45 try {
46 populateClassName(node);
47 } catch (ClassNotFoundException e) {
48 populateImports(node);
49 }
50 return super.visit(node, data);
51 }
52
53 /***
54 * If the outer class wasn't found then we'll get in here
55 *
56 * @param node
57 */
58 private void populateImports(ASTCompilationUnit node) {
59 List theImportDeclarations = node.findChildrenOfType(ASTImportDeclaration.class);
60 importedClasses = new HashMap();
61
62
63 for (Iterator anIterator = theImportDeclarations.iterator(); anIterator.hasNext();) {
64 ASTImportDeclaration anImportDeclaration = (ASTImportDeclaration) anIterator.next();
65 if (!anImportDeclaration.isImportOnDemand()) {
66 String strPackage = anImportDeclaration.getPackageName();
67 String strName = anImportDeclaration.getImportedName();
68 importedClasses.put(strName, strName);
69 importedClasses.put(strName.substring(strPackage.length() + 1), strName);
70 }
71 }
72
73 importedClasses.put("String", "java.lang.String");
74 importedClasses.put("Object", "java.lang.Object");
75 }
76
77 private void populateClassName(ASTCompilationUnit node) throws ClassNotFoundException {
78 ASTClassOrInterfaceDeclaration decl = (ASTClassOrInterfaceDeclaration) node
79 .getFirstChildOfType(ASTClassOrInterfaceDeclaration.class);
80 if (decl != null) {
81 ASTPackageDeclaration pkgDecl = (ASTPackageDeclaration) node
82 .getFirstChildOfType(ASTPackageDeclaration.class);
83 className = pkgDecl == null ? decl.getImage() : ((ASTName) pkgDecl.jjtGetChild(0)).getImage() + "."
84 + decl.getImage();
85 pmdClassLoader.loadClass(className);
86 importedClasses = pmdClassLoader.getImportedClasses(className);
87 }
88 }
89
90 public Object visit(ASTClassOrInterfaceType node, Object data) {
91
92 String className = node.getImage();
93 String qualifiedName = className;
94 Class myType = (Class) myPrimitiveTypes.get(className);
95 if (myType == null && importedClasses != null) {
96 if (importedClasses.containsKey(className)) {
97 qualifiedName = (String) importedClasses.get(className);
98 } else if (importedClasses.containsValue(className)) {
99 qualifiedName = className;
100 }
101 if (qualifiedName != null) {
102 try {
103
104
105
106
107
108 myType = pmdClassLoader.loadClass(qualifiedName);
109 } catch (ClassNotFoundException e) {
110
111 }
112 }
113 }
114 if (myType != null) {
115 node.setType(myType);
116 }
117 return data;
118 }
119 }