author | aefimov |
Fri, 10 Apr 2015 14:54:20 +0300 | |
changeset 29839 | 6d5d546e953b |
parent 25871 | b80b84e87032 |
permissions | -rw-r--r-- |
12009 | 1 |
/* |
29839
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
2 |
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
12009 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package com.sun.tools.internal.jxc.model.nav; |
|
27 |
||
28 |
import com.sun.source.tree.CompilationUnitTree; |
|
29 |
import com.sun.source.util.TreePath; |
|
30 |
import com.sun.source.util.Trees; |
|
31 |
import com.sun.xml.internal.bind.v2.model.nav.Navigator; |
|
32 |
import com.sun.xml.internal.bind.v2.runtime.Location; |
|
29839
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
33 |
import java.lang.annotation.Annotation; |
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
34 |
import java.util.ArrayList; |
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
35 |
import java.util.Collection; |
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
36 |
import java.util.HashMap; |
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
37 |
import java.util.List; |
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
38 |
import java.util.Map; |
12009 | 39 |
import javax.annotation.processing.ProcessingEnvironment; |
16541
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
40 |
import javax.lang.model.element.AnnotationMirror; |
12009 | 41 |
import javax.lang.model.element.Element; |
42 |
import javax.lang.model.element.ElementKind; |
|
43 |
import javax.lang.model.element.ExecutableElement; |
|
44 |
import javax.lang.model.element.Modifier; |
|
45 |
import javax.lang.model.element.TypeElement; |
|
46 |
import javax.lang.model.element.TypeParameterElement; |
|
47 |
import javax.lang.model.element.VariableElement; |
|
48 |
import javax.lang.model.type.ArrayType; |
|
49 |
import javax.lang.model.type.DeclaredType; |
|
50 |
import javax.lang.model.type.PrimitiveType; |
|
51 |
import javax.lang.model.type.TypeKind; |
|
52 |
import javax.lang.model.type.TypeMirror; |
|
53 |
import javax.lang.model.type.TypeVariable; |
|
54 |
import javax.lang.model.type.TypeVisitor; |
|
55 |
import javax.lang.model.type.WildcardType; |
|
56 |
import javax.lang.model.util.ElementFilter; |
|
57 |
import javax.lang.model.util.Elements; |
|
58 |
import javax.lang.model.util.SimpleTypeVisitor6; |
|
59 |
import javax.lang.model.util.Types; |
|
60 |
||
61 |
/** |
|
62 |
* {@link Navigator} implementation for annotation processing. |
|
63 |
* TODO: check the spec on how generics are supposed to be handled |
|
64 |
* |
|
65 |
* @author Kohsuke Kawaguchi (kk@kohsuke.org) |
|
66 |
*/ |
|
22427 | 67 |
public final class ApNavigator implements Navigator<TypeMirror, TypeElement, VariableElement, ExecutableElement> { |
12009 | 68 |
|
69 |
private final ProcessingEnvironment env; |
|
70 |
||
71 |
private final PrimitiveType primitiveByte; |
|
72 |
||
73 |
public ApNavigator(ProcessingEnvironment env) { |
|
74 |
this.env = env; |
|
75 |
this.primitiveByte = env.getTypeUtils().getPrimitiveType(TypeKind.BYTE); |
|
76 |
} |
|
77 |
||
78 |
public TypeElement getSuperClass(TypeElement typeElement) { |
|
79 |
if (typeElement.getKind().equals(ElementKind.CLASS)) { |
|
80 |
TypeMirror sup = typeElement.getSuperclass(); |
|
81 |
if (!sup.getKind().equals(TypeKind.NONE)) |
|
82 |
return (TypeElement) ((DeclaredType) sup).asElement(); |
|
83 |
else |
|
84 |
return null; |
|
85 |
} |
|
86 |
return env.getElementUtils().getTypeElement(Object.class.getName()); |
|
87 |
} |
|
88 |
||
89 |
public TypeMirror getBaseClass(TypeMirror type, TypeElement sup) { |
|
90 |
return baseClassFinder.visit(type, sup); |
|
91 |
} |
|
92 |
||
93 |
public String getClassName(TypeElement t) { |
|
94 |
return t.getQualifiedName().toString(); |
|
95 |
} |
|
96 |
||
97 |
public String getTypeName(TypeMirror typeMirror) { |
|
98 |
return typeMirror.toString(); |
|
99 |
} |
|
100 |
||
101 |
public String getClassShortName(TypeElement t) { |
|
102 |
return t.getSimpleName().toString(); |
|
103 |
} |
|
104 |
||
105 |
public Collection<VariableElement> getDeclaredFields(TypeElement typeElement) { |
|
106 |
return ElementFilter.fieldsIn(typeElement.getEnclosedElements()); |
|
107 |
} |
|
108 |
||
109 |
public VariableElement getDeclaredField(TypeElement clazz, String fieldName) { |
|
110 |
for (VariableElement fd : ElementFilter.fieldsIn(clazz.getEnclosedElements())) { |
|
111 |
if (fd.getSimpleName().toString().equals(fieldName)) |
|
112 |
return fd; |
|
113 |
} |
|
114 |
return null; |
|
115 |
} |
|
116 |
||
117 |
public Collection<ExecutableElement> getDeclaredMethods(TypeElement typeElement) { |
|
118 |
return ElementFilter.methodsIn(typeElement.getEnclosedElements()); |
|
119 |
} |
|
120 |
||
121 |
public TypeElement getDeclaringClassForField(VariableElement f) { |
|
122 |
return (TypeElement) f.getEnclosingElement(); |
|
123 |
} |
|
124 |
||
125 |
public TypeElement getDeclaringClassForMethod(ExecutableElement m) { |
|
126 |
return (TypeElement) m.getEnclosingElement(); |
|
127 |
} |
|
128 |
||
129 |
public TypeMirror getFieldType(VariableElement f) { |
|
130 |
return f.asType(); |
|
131 |
} |
|
132 |
||
133 |
public String getFieldName(VariableElement f) { |
|
134 |
return f.getSimpleName().toString(); |
|
135 |
} |
|
136 |
||
137 |
public String getMethodName(ExecutableElement m) { |
|
138 |
return m.getSimpleName().toString(); |
|
139 |
} |
|
140 |
||
141 |
public TypeMirror getReturnType(ExecutableElement m) { |
|
142 |
return m.getReturnType(); |
|
143 |
} |
|
144 |
||
145 |
public TypeMirror[] getMethodParameters(ExecutableElement m) { |
|
146 |
Collection<? extends VariableElement> ps = m.getParameters(); |
|
147 |
TypeMirror[] r = new TypeMirror[ps.size()]; |
|
148 |
int i=0; |
|
149 |
for (VariableElement p : ps) |
|
150 |
r[i++] = p.asType(); |
|
151 |
return r; |
|
152 |
} |
|
153 |
||
154 |
public boolean isStaticMethod(ExecutableElement m) { |
|
155 |
return hasModifier(m, Modifier.STATIC); |
|
156 |
} |
|
157 |
||
158 |
public boolean isFinalMethod(ExecutableElement m) { |
|
159 |
return hasModifier(m, Modifier.FINAL); |
|
160 |
} |
|
161 |
||
162 |
private boolean hasModifier(Element d, Modifier mod) { |
|
163 |
return d.getModifiers().contains(mod); |
|
164 |
} |
|
165 |
||
166 |
public boolean isSubClassOf(TypeMirror sub, TypeMirror sup) { |
|
167 |
if(sup==DUMMY) |
|
168 |
// see ref(). if the sub type is known to Annotation Processing, |
|
169 |
// its base class must be known. Thus if the sup is DUMMY, |
|
170 |
// it cannot possibly be the super type. |
|
171 |
return false; |
|
172 |
return env.getTypeUtils().isSubtype(sub,sup); |
|
173 |
} |
|
174 |
||
175 |
private String getSourceClassName(Class clazz) { |
|
176 |
Class<?> d = clazz.getDeclaringClass(); |
|
177 |
if(d==null) |
|
178 |
return clazz.getName(); |
|
179 |
else { |
|
180 |
String shortName = clazz.getName().substring(d.getName().length()+1/*for $*/); |
|
181 |
return getSourceClassName(d)+'.'+shortName; |
|
182 |
} |
|
183 |
} |
|
184 |
||
185 |
public TypeMirror ref(Class c) { |
|
186 |
if(c.isArray()) |
|
187 |
return env.getTypeUtils().getArrayType( ref(c.getComponentType()) ); |
|
188 |
if(c.isPrimitive()) |
|
189 |
return getPrimitive(c); |
|
190 |
TypeElement t = env.getElementUtils().getTypeElement(getSourceClassName(c)); |
|
191 |
// Annotation Processing only operates on a set of classes used in the compilation, |
|
192 |
// and it won't recognize additional classes (even if they are visible from javac) |
|
193 |
// and return null. |
|
194 |
// |
|
195 |
// this is causing a problem where we check if a type is collection. |
|
196 |
// so until the problem is fixed in Annotation Processing, work around the issue |
|
197 |
// by returning a dummy token |
|
198 |
// TODO: check if this is still valid |
|
199 |
if(t==null) |
|
200 |
return DUMMY; |
|
201 |
return env.getTypeUtils().getDeclaredType(t); |
|
202 |
} |
|
203 |
||
204 |
public TypeMirror use(TypeElement t) { |
|
205 |
assert t != null; |
|
206 |
return env.getTypeUtils().getDeclaredType(t); |
|
207 |
} |
|
208 |
||
209 |
public TypeElement asDecl(TypeMirror m) { |
|
210 |
m = env.getTypeUtils().erasure(m); |
|
211 |
if (m.getKind().equals(TypeKind.DECLARED)) { |
|
212 |
DeclaredType d = (DeclaredType) m; |
|
213 |
return (TypeElement) d.asElement(); |
|
214 |
} else |
|
215 |
return null; |
|
216 |
} |
|
217 |
||
218 |
public TypeElement asDecl(Class c) { |
|
219 |
return env.getElementUtils().getTypeElement(getSourceClassName(c)); |
|
220 |
} |
|
221 |
||
222 |
public TypeMirror erasure(TypeMirror t) { |
|
223 |
Types tu = env.getTypeUtils(); |
|
224 |
t = tu.erasure(t); |
|
225 |
if (t.getKind().equals(TypeKind.DECLARED)) { |
|
226 |
DeclaredType dt = (DeclaredType)t; |
|
227 |
if (!dt.getTypeArguments().isEmpty()) |
|
228 |
return tu.getDeclaredType((TypeElement) dt.asElement()); |
|
229 |
} |
|
230 |
return t; |
|
231 |
} |
|
232 |
||
233 |
public boolean isAbstract(TypeElement clazz) { |
|
234 |
return hasModifier(clazz,Modifier.ABSTRACT); |
|
235 |
} |
|
236 |
||
237 |
public boolean isFinal(TypeElement clazz) { |
|
22427 | 238 |
return hasModifier(clazz, Modifier.FINAL); |
12009 | 239 |
} |
240 |
||
241 |
public VariableElement[] getEnumConstants(TypeElement clazz) { |
|
242 |
List<? extends Element> elements = env.getElementUtils().getAllMembers(clazz); |
|
29839
6d5d546e953b
8076549: Update JAX-WS RI integration to latest version (2.2.11-b150402.1412)
aefimov
parents:
25871
diff
changeset
|
243 |
Collection<VariableElement> constants = new ArrayList<VariableElement>(); |
12009 | 244 |
for (Element element : elements) { |
245 |
if (element.getKind().equals(ElementKind.ENUM_CONSTANT)) { |
|
246 |
constants.add((VariableElement) element); |
|
247 |
} |
|
248 |
} |
|
249 |
return constants.toArray(new VariableElement[constants.size()]); |
|
250 |
} |
|
251 |
||
252 |
public TypeMirror getVoidType() { |
|
253 |
return env.getTypeUtils().getNoType(TypeKind.VOID); |
|
254 |
} |
|
255 |
||
256 |
public String getPackageName(TypeElement clazz) { |
|
257 |
return env.getElementUtils().getPackageOf(clazz).getQualifiedName().toString(); |
|
258 |
} |
|
259 |
||
22427 | 260 |
@Override |
261 |
public TypeElement loadObjectFactory(TypeElement referencePoint, String packageName) { |
|
262 |
return env.getElementUtils().getTypeElement(packageName + ".ObjectFactory"); |
|
12009 | 263 |
} |
264 |
||
265 |
public boolean isBridgeMethod(ExecutableElement method) { |
|
266 |
return method.getModifiers().contains(Modifier.VOLATILE); |
|
267 |
} |
|
268 |
||
269 |
public boolean isOverriding(ExecutableElement method, TypeElement base) { |
|
270 |
Elements elements = env.getElementUtils(); |
|
271 |
||
272 |
while (true) { |
|
273 |
for (ExecutableElement m : ElementFilter.methodsIn(elements.getAllMembers(base))) { |
|
274 |
if (elements.overrides(method, m, base)) |
|
275 |
return true; |
|
276 |
} |
|
277 |
||
278 |
if (base.getSuperclass().getKind().equals(TypeKind.NONE)) |
|
279 |
return false; |
|
280 |
base = (TypeElement) env.getTypeUtils().asElement(base.getSuperclass()); |
|
281 |
} |
|
282 |
} |
|
283 |
||
284 |
public boolean isInterface(TypeElement clazz) { |
|
285 |
return clazz.getKind().isInterface(); |
|
286 |
} |
|
287 |
||
288 |
public boolean isTransient(VariableElement f) { |
|
289 |
return f.getModifiers().contains(Modifier.TRANSIENT); |
|
290 |
} |
|
291 |
||
292 |
public boolean isInnerClass(TypeElement clazz) { |
|
293 |
return clazz.getEnclosingElement() != null && !clazz.getModifiers().contains(Modifier.STATIC); |
|
294 |
} |
|
295 |
||
296 |
@Override |
|
297 |
public boolean isSameType(TypeMirror t1, TypeMirror t2) { |
|
298 |
return env.getTypeUtils().isSameType(t1, t2); |
|
299 |
} |
|
300 |
||
301 |
public boolean isArray(TypeMirror type) { |
|
302 |
return type != null && type.getKind().equals(TypeKind.ARRAY); |
|
303 |
} |
|
304 |
||
305 |
public boolean isArrayButNotByteArray(TypeMirror t) { |
|
306 |
if(!isArray(t)) |
|
307 |
return false; |
|
308 |
||
309 |
ArrayType at = (ArrayType) t; |
|
310 |
TypeMirror ct = at.getComponentType(); |
|
311 |
||
312 |
return !ct.equals(primitiveByte); |
|
313 |
} |
|
314 |
||
315 |
public TypeMirror getComponentType(TypeMirror t) { |
|
316 |
if (isArray(t)) { |
|
317 |
ArrayType at = (ArrayType) t; |
|
318 |
return at.getComponentType(); |
|
319 |
} |
|
320 |
||
321 |
throw new IllegalArgumentException(); |
|
322 |
} |
|
323 |
||
324 |
public TypeMirror getTypeArgument(TypeMirror typeMirror, int i) { |
|
325 |
if (typeMirror != null && typeMirror.getKind().equals(TypeKind.DECLARED)) { |
|
326 |
DeclaredType declaredType = (DeclaredType) typeMirror; |
|
327 |
TypeMirror[] args = declaredType.getTypeArguments().toArray(new TypeMirror[declaredType.getTypeArguments().size()]); |
|
328 |
return args[i]; |
|
329 |
} else throw new IllegalArgumentException(); |
|
330 |
} |
|
331 |
||
332 |
public boolean isParameterizedType(TypeMirror typeMirror) { |
|
333 |
if (typeMirror != null && typeMirror.getKind().equals(TypeKind.DECLARED)) { |
|
334 |
DeclaredType d = (DeclaredType) typeMirror; |
|
335 |
return !d.getTypeArguments().isEmpty(); |
|
336 |
} |
|
337 |
return false; |
|
338 |
} |
|
339 |
||
340 |
public boolean isPrimitive(TypeMirror t) { |
|
341 |
return t.getKind().isPrimitive(); |
|
342 |
} |
|
343 |
||
344 |
private static final Map<Class, TypeKind> primitives = new HashMap<Class, TypeKind>(); |
|
345 |
||
346 |
static { |
|
347 |
primitives.put(Integer.TYPE, TypeKind.INT); |
|
348 |
primitives.put(Byte.TYPE, TypeKind.BYTE); |
|
349 |
primitives.put(Float.TYPE, TypeKind.FLOAT); |
|
350 |
primitives.put(Boolean.TYPE, TypeKind.BOOLEAN); |
|
351 |
primitives.put(Short.TYPE, TypeKind.SHORT); |
|
352 |
primitives.put(Long.TYPE, TypeKind.LONG); |
|
353 |
primitives.put(Double.TYPE, TypeKind.DOUBLE); |
|
354 |
primitives.put(Character.TYPE, TypeKind.CHAR); |
|
355 |
} |
|
356 |
||
357 |
public TypeMirror getPrimitive(Class primitiveType) { |
|
358 |
assert primitiveType.isPrimitive(); |
|
359 |
if(primitiveType==void.class) |
|
360 |
return getVoidType(); |
|
361 |
return env.getTypeUtils().getPrimitiveType(primitives.get(primitiveType)); |
|
362 |
} |
|
363 |
||
364 |
/** |
|
365 |
* see {@link #ref(Class)}. |
|
366 |
*/ |
|
367 |
private static final TypeMirror DUMMY = new TypeMirror() { |
|
368 |
@Override |
|
369 |
public <R, P> R accept(TypeVisitor<R, P> v, P p) { |
|
370 |
throw new IllegalStateException(); |
|
371 |
} |
|
372 |
||
373 |
@Override |
|
374 |
public TypeKind getKind() { |
|
375 |
throw new IllegalStateException(); |
|
376 |
} |
|
16541
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
377 |
|
16791 | 378 |
// @Override |
16541
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
379 |
public List<? extends AnnotationMirror> getAnnotationMirrors() { |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
380 |
throw new IllegalStateException(); |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
381 |
} |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
382 |
|
16791 | 383 |
// @Override |
16541
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
384 |
public <A extends Annotation> A getAnnotation(Class<A> annotationType) { |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
385 |
throw new IllegalStateException(); |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
386 |
} |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
387 |
|
16791 | 388 |
// @Override |
16541
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
389 |
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
390 |
throw new IllegalStateException(); |
d44e3250034c
8007803: Implement javax.lang.model API for Type Annotations
jjg
parents:
12009
diff
changeset
|
391 |
} |
12009 | 392 |
}; |
393 |
||
394 |
public Location getClassLocation(TypeElement typeElement) { |
|
395 |
Trees trees = Trees.instance(env); |
|
396 |
return getLocation(typeElement.getQualifiedName().toString(), trees.getPath(typeElement)); |
|
397 |
} |
|
398 |
||
399 |
public Location getFieldLocation(VariableElement variableElement) { |
|
400 |
return getLocation(variableElement); |
|
401 |
} |
|
402 |
||
403 |
public Location getMethodLocation(ExecutableElement executableElement) { |
|
404 |
return getLocation(executableElement); |
|
405 |
} |
|
406 |
||
407 |
public boolean hasDefaultConstructor(TypeElement t) { |
|
408 |
if (t == null || !t.getKind().equals(ElementKind.CLASS)) |
|
409 |
return false; |
|
410 |
||
411 |
for (ExecutableElement init : ElementFilter.constructorsIn(env.getElementUtils().getAllMembers(t))) { |
|
412 |
if (init.getParameters().isEmpty()) |
|
413 |
return true; |
|
414 |
} |
|
415 |
return false; |
|
416 |
} |
|
417 |
||
418 |
public boolean isStaticField(VariableElement f) { |
|
419 |
return hasModifier(f,Modifier.STATIC); |
|
420 |
} |
|
421 |
||
422 |
public boolean isPublicMethod(ExecutableElement m) { |
|
423 |
return hasModifier(m,Modifier.PUBLIC); |
|
424 |
} |
|
425 |
||
426 |
public boolean isPublicField(VariableElement f) { |
|
427 |
return hasModifier(f,Modifier.PUBLIC); |
|
428 |
} |
|
429 |
||
430 |
public boolean isEnum(TypeElement t) { |
|
431 |
return t != null && t.getKind().equals(ElementKind.ENUM); |
|
432 |
} |
|
433 |
||
434 |
private Location getLocation(Element element) { |
|
435 |
Trees trees = Trees.instance(env); |
|
436 |
return getLocation( |
|
437 |
((TypeElement) element.getEnclosingElement()).getQualifiedName() + "." + element.getSimpleName(), |
|
438 |
trees.getPath(element) |
|
439 |
); |
|
440 |
} |
|
441 |
||
442 |
private Location getLocation(final String name, final TreePath treePath) { |
|
443 |
return new Location() { |
|
444 |
public String toString() { |
|
445 |
if (treePath == null) |
|
446 |
return name + " (Unknown Source)"; |
|
447 |
// just like stack trace, we just print the file name and |
|
448 |
// not the whole path. The idea is that the package name should |
|
449 |
// provide enough clue on which directory it lives. |
|
450 |
CompilationUnitTree compilationUnit = treePath.getCompilationUnit(); |
|
451 |
Trees trees = Trees.instance(env); |
|
452 |
long startPosition = trees.getSourcePositions().getStartPosition(compilationUnit, treePath.getLeaf()); |
|
453 |
return name + "(" + |
|
454 |
compilationUnit.getSourceFile().getName() + ":" + compilationUnit.getLineMap().getLineNumber(startPosition) + |
|
455 |
")"; |
|
456 |
} |
|
457 |
}; |
|
458 |
} |
|
459 |
||
460 |
/** |
|
461 |
* Implements {@link #getBaseClass}. |
|
462 |
*/ |
|
463 |
private final SimpleTypeVisitor6<TypeMirror, TypeElement> baseClassFinder = new SimpleTypeVisitor6<TypeMirror, TypeElement>() { |
|
464 |
@Override |
|
465 |
public TypeMirror visitDeclared(DeclaredType t, TypeElement sup) { |
|
466 |
if (t.asElement().equals(sup)) |
|
467 |
return t; |
|
468 |
||
469 |
for (TypeMirror i : env.getTypeUtils().directSupertypes(t)) { |
|
470 |
TypeMirror r = visitDeclared((DeclaredType) i, sup); |
|
471 |
if (r != null) |
|
472 |
return r; |
|
473 |
} |
|
474 |
||
475 |
// otherwise recursively apply super class and base types |
|
476 |
TypeMirror superclass = ((TypeElement) t.asElement()).getSuperclass(); |
|
477 |
if (!superclass.getKind().equals(TypeKind.NONE)) { |
|
478 |
TypeMirror r = visitDeclared((DeclaredType) superclass, sup); |
|
479 |
if (r != null) |
|
480 |
return r; |
|
481 |
} |
|
482 |
return null; |
|
483 |
} |
|
484 |
||
485 |
@Override |
|
486 |
public TypeMirror visitTypeVariable(TypeVariable t, TypeElement typeElement) { |
|
487 |
// we are checking if T (declared as T extends A&B&C) is assignable to sup. |
|
488 |
// so apply bounds recursively. |
|
489 |
for (TypeMirror typeMirror : ((TypeParameterElement) t.asElement()).getBounds()) { |
|
490 |
TypeMirror m = visit(typeMirror, typeElement); |
|
491 |
if (m != null) |
|
492 |
return m; |
|
493 |
} |
|
494 |
return null; |
|
495 |
} |
|
496 |
||
497 |
@Override |
|
498 |
public TypeMirror visitArray(ArrayType t, TypeElement typeElement) { |
|
499 |
// we are checking if t=T[] is assignable to sup. |
|
500 |
// the only case this is allowed is sup=Object, |
|
501 |
// and Object isn't parameterized. |
|
502 |
return null; |
|
503 |
} |
|
504 |
||
505 |
@Override |
|
506 |
public TypeMirror visitWildcard(WildcardType t, TypeElement typeElement) { |
|
507 |
// we are checking if T (= ? extends A&B&C) is assignable to sup. |
|
508 |
// so apply bounds recursively. |
|
509 |
return visit(t.getExtendsBound(), typeElement); |
|
510 |
} |
|
511 |
||
512 |
@Override |
|
513 |
protected TypeMirror defaultAction(TypeMirror e, TypeElement typeElement) { |
|
514 |
return e; |
|
515 |
} |
|
516 |
}; |
|
517 |
} |