1
2
3
4 package net.sourceforge.pmd.lang.java.symboltable;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader;
14
15
16
17
18 public class TypeSet {
19
20 private final PMDASMClassLoader pmdClassLoader;
21
22
23
24
25 public TypeSet() {
26 this(TypeSet.class.getClassLoader());
27 }
28
29
30
31
32
33 public TypeSet(ClassLoader classLoader) {
34 ClassLoader cl = classLoader;
35 if (cl == null) {
36 cl = TypeSet.class.getClassLoader();
37 }
38 pmdClassLoader = PMDASMClassLoader.getInstance(cl);
39 }
40
41
42
43
44
45
46
47 public interface Resolver {
48
49
50
51
52
53
54
55 Class<?> resolve(String name) throws ClassNotFoundException;
56 }
57
58
59
60
61
62 public static abstract class AbstractResolver implements Resolver {
63
64 protected final PMDASMClassLoader pmdClassLoader;
65
66
67
68
69 public AbstractResolver(PMDASMClassLoader pmdClassLoader) {
70 this.pmdClassLoader = pmdClassLoader;
71 }
72 }
73
74
75
76
77
78 public static class ExplicitImportResolver extends AbstractResolver {
79 private Set<String> importStmts;
80
81
82
83
84
85 public ExplicitImportResolver(PMDASMClassLoader pmdClassLoader, Set<String> importStmts) {
86 super(pmdClassLoader);
87 this.importStmts = importStmts;
88 }
89 @Override
90 public Class<?> resolve(String name) throws ClassNotFoundException {
91 for (String importStmt : importStmts) {
92 if (importStmt.endsWith(name)) {
93 return pmdClassLoader.loadClass(importStmt);
94 }
95 }
96 throw new ClassNotFoundException("Type " + name + " not found");
97 }
98 }
99
100
101
102
103 public static class CurrentPackageResolver extends AbstractResolver {
104 private String pkg;
105
106
107
108
109
110 public CurrentPackageResolver(PMDASMClassLoader pmdClassLoader, String pkg) {
111 super(pmdClassLoader);
112 this.pkg = pkg;
113 }
114 @Override
115 public Class<?> resolve(String name) throws ClassNotFoundException {
116 return pmdClassLoader.loadClass(pkg + '.' + name);
117 }
118 }
119
120
121
122
123
124 public static class ImplicitImportResolver extends AbstractResolver {
125
126
127
128
129 public ImplicitImportResolver(PMDASMClassLoader pmdClassLoader) {
130 super(pmdClassLoader);
131 }
132 @Override
133 public Class<?> resolve(String name) throws ClassNotFoundException {
134 return pmdClassLoader.loadClass("java.lang." + name);
135 }
136 }
137
138
139
140
141 public static class ImportOnDemandResolver extends AbstractResolver {
142 private Set<String> importStmts;
143
144
145
146
147
148 public ImportOnDemandResolver(PMDASMClassLoader pmdClassLoader, Set<String> importStmts) {
149 super(pmdClassLoader);
150 this.importStmts = importStmts;
151 }
152 @Override
153 public Class<?> resolve(String name) throws ClassNotFoundException {
154 for (String importStmt : importStmts) {
155 if (importStmt.endsWith("*")) {
156 try {
157 String importPkg = importStmt.substring(0, importStmt.indexOf('*') - 1);
158 return pmdClassLoader.loadClass(importPkg + '.' + name);
159 } catch (ClassNotFoundException cnfe) {
160 }
161 }
162 }
163 throw new ClassNotFoundException("Type " + name + " not found");
164 }
165 }
166
167
168
169
170 public static class PrimitiveTypeResolver implements Resolver {
171 private Map<String, Class<?>> primitiveTypes = new HashMap<String, Class<?>>();
172
173
174
175 @SuppressWarnings("PMD.AvoidUsingShortType")
176 public PrimitiveTypeResolver() {
177 primitiveTypes.put("int", int.class);
178 primitiveTypes.put("float", float.class);
179 primitiveTypes.put("double", double.class);
180 primitiveTypes.put("long", long.class);
181 primitiveTypes.put("boolean", boolean.class);
182 primitiveTypes.put("byte", byte.class);
183 primitiveTypes.put("short", short.class);
184 primitiveTypes.put("char", char.class);
185 }
186 @Override
187 public Class<?> resolve(String name) throws ClassNotFoundException {
188 if (!primitiveTypes.containsKey(name)) {
189 throw new ClassNotFoundException();
190 }
191 return primitiveTypes.get(name);
192 }
193 }
194
195
196
197
198 public static class VoidResolver implements Resolver {
199 @Override
200 public Class<?> resolve(String name) throws ClassNotFoundException {
201 if (name.equals("void")) {
202 return void.class;
203 }
204 throw new ClassNotFoundException();
205 }
206 }
207
208
209
210
211
212 public static class FullyQualifiedNameResolver extends AbstractResolver {
213
214
215
216
217 public FullyQualifiedNameResolver(PMDASMClassLoader pmdClassLoader) {
218 super(pmdClassLoader);
219 }
220 @Override
221 public Class<?> resolve(String name) throws ClassNotFoundException {
222 return pmdClassLoader.loadClass(name);
223 }
224 }
225
226 private String pkg;
227 private Set<String> imports = new HashSet<String>();
228 private List<Resolver> resolvers = new ArrayList<Resolver>();
229
230 public void setASTCompilationUnitPackage(String pkg) {
231 this.pkg = pkg;
232 }
233
234 public String getASTCompilationUnitPackage() {
235 return pkg;
236 }
237
238
239
240
241
242 public void addImport(String importString) {
243 imports.add(importString);
244 }
245
246 public int getImportsCount() {
247 return imports.size();
248 }
249
250
251
252
253
254
255
256 public Class<?> findClass(String name) throws ClassNotFoundException {
257
258
259 if (resolvers.isEmpty()) {
260 buildResolvers();
261 }
262
263 for (Resolver resolver : resolvers) {
264 try {
265 return resolver.resolve(name);
266 } catch (ClassNotFoundException cnfe) {
267 }
268 }
269
270 throw new ClassNotFoundException("Type " + name + " not found");
271 }
272
273 private void buildResolvers() {
274 resolvers.add(new PrimitiveTypeResolver());
275 resolvers.add(new VoidResolver());
276 resolvers.add(new ExplicitImportResolver(pmdClassLoader, imports));
277 resolvers.add(new CurrentPackageResolver(pmdClassLoader, pkg));
278 resolvers.add(new ImplicitImportResolver(pmdClassLoader));
279 resolvers.add(new ImportOnDemandResolver(pmdClassLoader, imports));
280 resolvers.add(new FullyQualifiedNameResolver(pmdClassLoader));
281 }
282 }