Mercurial > hg > truffle
comparison truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java @ 21951:9c8c0937da41
Moving all sources into truffle subdirectory
author | Jaroslav Tulach <jaroslav.tulach@oracle.com> |
---|---|
date | Wed, 17 Jun 2015 10:58:08 +0200 |
parents | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java@8e5f9310f3aa |
children | dc83cc1f94f2 |
comparison
equal
deleted
inserted
replaced
21950:2a5011c7e641 | 21951:9c8c0937da41 |
---|---|
1 /* | |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. | |
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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.dsl.processor.java; | |
24 | |
25 import java.io.*; | |
26 import java.lang.annotation.*; | |
27 import java.util.*; | |
28 | |
29 import javax.annotation.processing.*; | |
30 import javax.lang.model.element.*; | |
31 import javax.lang.model.type.*; | |
32 import javax.lang.model.util.*; | |
33 | |
34 import com.oracle.truffle.dsl.processor.*; | |
35 import com.oracle.truffle.dsl.processor.java.model.*; | |
36 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror; | |
37 | |
38 /** | |
39 * THIS IS NOT PUBLIC API. | |
40 */ | |
41 public class ElementUtils { | |
42 | |
43 public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) { | |
44 if (element.isArray()) { | |
45 return processingEnv.getTypeUtils().getArrayType(getType(processingEnv, element.getComponentType())); | |
46 } | |
47 if (element.isPrimitive()) { | |
48 if (element == void.class) { | |
49 return processingEnv.getTypeUtils().getNoType(TypeKind.VOID); | |
50 } | |
51 TypeKind typeKind; | |
52 if (element == boolean.class) { | |
53 typeKind = TypeKind.BOOLEAN; | |
54 } else if (element == byte.class) { | |
55 typeKind = TypeKind.BYTE; | |
56 } else if (element == short.class) { | |
57 typeKind = TypeKind.SHORT; | |
58 } else if (element == char.class) { | |
59 typeKind = TypeKind.CHAR; | |
60 } else if (element == int.class) { | |
61 typeKind = TypeKind.INT; | |
62 } else if (element == long.class) { | |
63 typeKind = TypeKind.LONG; | |
64 } else if (element == float.class) { | |
65 typeKind = TypeKind.FLOAT; | |
66 } else if (element == double.class) { | |
67 typeKind = TypeKind.DOUBLE; | |
68 } else { | |
69 assert false; | |
70 return null; | |
71 } | |
72 return processingEnv.getTypeUtils().getPrimitiveType(typeKind); | |
73 } else { | |
74 TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(element.getCanonicalName()); | |
75 if (typeElement == null) { | |
76 return null; | |
77 } | |
78 return typeElement.asType(); | |
79 } | |
80 } | |
81 | |
82 public static ExecutableElement findExecutableElement(DeclaredType type, String name) { | |
83 List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); | |
84 for (ExecutableElement executableElement : elements) { | |
85 if (executableElement.getSimpleName().toString().equals(name)) { | |
86 return executableElement; | |
87 } | |
88 } | |
89 return null; | |
90 } | |
91 | |
92 public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) { | |
93 if (typeEquals(sourceType, targetType)) { | |
94 return false; | |
95 } else if (isObject(targetType)) { | |
96 return false; | |
97 } else if (isVoid(targetType)) { | |
98 return false; | |
99 } else if (isAssignable(sourceType, targetType)) { | |
100 return false; | |
101 } | |
102 return true; | |
103 } | |
104 | |
105 public static String createReferenceName(ExecutableElement method) { | |
106 StringBuilder b = new StringBuilder(); | |
107 | |
108 b.append(method.getSimpleName().toString()); | |
109 b.append("("); | |
110 | |
111 String sep = ""; | |
112 for (VariableElement parameter : method.getParameters()) { | |
113 b.append(sep); | |
114 b.append(ElementUtils.getSimpleName(parameter.asType())); | |
115 sep = ", "; | |
116 } | |
117 | |
118 b.append(")"); | |
119 return b.toString(); | |
120 } | |
121 | |
122 public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { | |
123 if (primitiveType == null) { | |
124 return null; | |
125 } | |
126 TypeMirror boxedType = primitiveType; | |
127 if (boxedType.getKind().isPrimitive()) { | |
128 boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); | |
129 } | |
130 return boxedType; | |
131 } | |
132 | |
133 public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { | |
134 return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); | |
135 } | |
136 | |
137 public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, | |
138 Class<? extends Annotation> annotationClass) { | |
139 List<AnnotationMirror> result = new ArrayList<>(); | |
140 if (markerAnnotation != null) { | |
141 result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); | |
142 } | |
143 AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); | |
144 if (explicit != null) { | |
145 result.add(explicit); | |
146 } | |
147 return result; | |
148 } | |
149 | |
150 public static TypeMirror getCommonSuperType(ProcessorContext context, Collection<TypeMirror> types) { | |
151 if (types.isEmpty()) { | |
152 return context.getType(Object.class); | |
153 } | |
154 Iterator<TypeMirror> typesIterator = types.iterator(); | |
155 TypeMirror prev = typesIterator.next(); | |
156 while (typesIterator.hasNext()) { | |
157 prev = getCommonSuperType(context, prev, typesIterator.next()); | |
158 } | |
159 return prev; | |
160 } | |
161 | |
162 private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { | |
163 if (typeEquals(type1, type2)) { | |
164 return type1; | |
165 } | |
166 if (isVoid(type1)) { | |
167 return type2; | |
168 } else if (isVoid(type2)) { | |
169 return type1; | |
170 } | |
171 if (isObject(type1)) { | |
172 return type1; | |
173 } else if (isObject(type2)) { | |
174 return type2; | |
175 } | |
176 | |
177 if (isPrimitive(type1) || isPrimitive(type2)) { | |
178 return context.getType(Object.class); | |
179 } | |
180 | |
181 if (isSubtype(type1, type2)) { | |
182 return type2; | |
183 } else if (isSubtype(type2, type1)) { | |
184 return type1; | |
185 } | |
186 | |
187 TypeElement element1 = fromTypeMirror(type1); | |
188 TypeElement element2 = fromTypeMirror(type2); | |
189 | |
190 if (element1 == null || element2 == null) { | |
191 return context.getType(Object.class); | |
192 } | |
193 | |
194 List<TypeElement> element1Types = getSuperTypes(element1); | |
195 List<TypeElement> element2Types = getSuperTypes(element2); | |
196 | |
197 for (TypeElement superType1 : element1Types) { | |
198 for (TypeElement superType2 : element2Types) { | |
199 if (typeEquals(superType1.asType(), superType2.asType())) { | |
200 return superType2.asType(); | |
201 } | |
202 } | |
203 } | |
204 | |
205 return context.getType(Object.class); | |
206 } | |
207 | |
208 public static String getReadableSignature(ExecutableElement method) { | |
209 StringBuilder builder = new StringBuilder(); | |
210 builder.append(method.getSimpleName().toString()); | |
211 builder.append("("); | |
212 String sep = ""; | |
213 for (VariableElement var : method.getParameters()) { | |
214 builder.append(sep); | |
215 builder.append(getSimpleName(var.asType())); | |
216 sep = ", "; | |
217 } | |
218 builder.append(")"); | |
219 return builder.toString(); | |
220 } | |
221 | |
222 public static boolean hasError(TypeMirror mirror) { | |
223 switch (mirror.getKind()) { | |
224 case BOOLEAN: | |
225 case BYTE: | |
226 case CHAR: | |
227 case DOUBLE: | |
228 case FLOAT: | |
229 case INT: | |
230 case SHORT: | |
231 case LONG: | |
232 case DECLARED: | |
233 case VOID: | |
234 case TYPEVAR: | |
235 return false; | |
236 case ARRAY: | |
237 return hasError(((ArrayType) mirror).getComponentType()); | |
238 case ERROR: | |
239 return true; | |
240 default: | |
241 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); | |
242 } | |
243 } | |
244 | |
245 public static boolean isSubtypeBoxed(ProcessorContext context, TypeMirror from, TypeMirror to) { | |
246 return isSubtype(boxType(context, from), boxType(context, to)); | |
247 } | |
248 | |
249 public static boolean isSubtype(TypeMirror type1, TypeMirror type2) { | |
250 if (type1 instanceof CodeTypeMirror || type2 instanceof CodeTypeMirror) { | |
251 throw new UnsupportedOperationException(); | |
252 } | |
253 return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2); | |
254 } | |
255 | |
256 public static boolean isAssignable(TypeMirror from, TypeMirror to) { | |
257 if (typeEquals(from, to)) { | |
258 return true; | |
259 } else if (isVoid(to)) { | |
260 return true; | |
261 } else if (isObject(to)) { | |
262 return true; | |
263 } | |
264 ProcessorContext context = ProcessorContext.getInstance(); | |
265 if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { | |
266 return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); | |
267 } else { | |
268 return isAssignableImpl(from, to); | |
269 } | |
270 } | |
271 | |
272 private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) { | |
273 // JLS 5.1.1 identity conversion | |
274 if (ElementUtils.typeEquals(from, to)) { | |
275 return true; | |
276 } | |
277 | |
278 if (isObject(to)) { | |
279 return true; | |
280 } | |
281 | |
282 // JLS 5.1.2 widening primitives | |
283 if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) { | |
284 TypeKind fromKind = from.getKind(); | |
285 TypeKind toKind = to.getKind(); | |
286 switch (fromKind) { | |
287 case BYTE: | |
288 switch (toKind) { | |
289 case SHORT: | |
290 case INT: | |
291 case LONG: | |
292 case FLOAT: | |
293 case DOUBLE: | |
294 return true; | |
295 } | |
296 break; | |
297 case SHORT: | |
298 switch (toKind) { | |
299 case INT: | |
300 case LONG: | |
301 case FLOAT: | |
302 case DOUBLE: | |
303 return true; | |
304 } | |
305 break; | |
306 case CHAR: | |
307 switch (toKind) { | |
308 case INT: | |
309 case LONG: | |
310 case FLOAT: | |
311 case DOUBLE: | |
312 return true; | |
313 } | |
314 break; | |
315 case INT: | |
316 switch (toKind) { | |
317 case LONG: | |
318 case FLOAT: | |
319 case DOUBLE: | |
320 return true; | |
321 } | |
322 break; | |
323 case LONG: | |
324 switch (toKind) { | |
325 case FLOAT: | |
326 case DOUBLE: | |
327 return true; | |
328 } | |
329 break; | |
330 case FLOAT: | |
331 switch (toKind) { | |
332 case DOUBLE: | |
333 return true; | |
334 } | |
335 break; | |
336 | |
337 } | |
338 return false; | |
339 } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) { | |
340 return false; | |
341 } | |
342 | |
343 if (from instanceof ArrayType && to instanceof ArrayType) { | |
344 return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); | |
345 } | |
346 | |
347 if (from instanceof ArrayType || to instanceof ArrayType) { | |
348 return false; | |
349 } | |
350 | |
351 TypeElement fromType = ElementUtils.fromTypeMirror(from); | |
352 TypeElement toType = ElementUtils.fromTypeMirror(to); | |
353 if (fromType == null || toType == null) { | |
354 return false; | |
355 } | |
356 // JLS 5.1.6 narrowing reference conversion | |
357 | |
358 List<TypeElement> superTypes = ElementUtils.getSuperTypes(fromType); | |
359 for (TypeElement superType : superTypes) { | |
360 if (ElementUtils.typeEquals(superType.asType(), to)) { | |
361 return true; | |
362 } | |
363 } | |
364 | |
365 // TODO more spec | |
366 return false; | |
367 } | |
368 | |
369 public static Set<Modifier> modifiers(Modifier... modifier) { | |
370 return new LinkedHashSet<>(Arrays.asList(modifier)); | |
371 } | |
372 | |
373 public static String getTypeId(TypeMirror mirror) { | |
374 switch (mirror.getKind()) { | |
375 case BOOLEAN: | |
376 return "Boolean"; | |
377 case BYTE: | |
378 return "Byte"; | |
379 case CHAR: | |
380 return "Char"; | |
381 case DOUBLE: | |
382 return "Double"; | |
383 case FLOAT: | |
384 return "Float"; | |
385 case SHORT: | |
386 return "Short"; | |
387 case INT: | |
388 return "Int"; | |
389 case LONG: | |
390 return "Long"; | |
391 case DECLARED: | |
392 return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString()); | |
393 case ARRAY: | |
394 return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; | |
395 case VOID: | |
396 return "Void"; | |
397 case NULL: | |
398 return "Null"; | |
399 case WILDCARD: | |
400 StringBuilder b = new StringBuilder(); | |
401 WildcardType type = (WildcardType) mirror; | |
402 if (type.getExtendsBound() != null) { | |
403 b.append("Extends").append(getTypeId(type.getExtendsBound())); | |
404 } else if (type.getSuperBound() != null) { | |
405 b.append("Super").append(getTypeId(type.getExtendsBound())); | |
406 } | |
407 return b.toString(); | |
408 case TYPEVAR: | |
409 return "Any"; | |
410 case ERROR: | |
411 throw new CompileErrorException("Type error " + mirror); | |
412 default: | |
413 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); | |
414 } | |
415 } | |
416 | |
417 public static String getSimpleName(TypeElement element) { | |
418 return getSimpleName(element.asType()); | |
419 } | |
420 | |
421 public static String getSimpleName(TypeMirror mirror) { | |
422 switch (mirror.getKind()) { | |
423 case BOOLEAN: | |
424 return "boolean"; | |
425 case BYTE: | |
426 return "byte"; | |
427 case CHAR: | |
428 return "char"; | |
429 case DOUBLE: | |
430 return "double"; | |
431 case FLOAT: | |
432 return "float"; | |
433 case SHORT: | |
434 return "short"; | |
435 case INT: | |
436 return "int"; | |
437 case LONG: | |
438 return "long"; | |
439 case DECLARED: | |
440 return getDeclaredName((DeclaredType) mirror, true); | |
441 case ARRAY: | |
442 return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; | |
443 case VOID: | |
444 return "void"; | |
445 case NULL: | |
446 return "null"; | |
447 case WILDCARD: | |
448 return getWildcardName((WildcardType) mirror); | |
449 case TYPEVAR: | |
450 return "?"; | |
451 case ERROR: | |
452 throw new CompileErrorException("Type error " + mirror); | |
453 default: | |
454 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); | |
455 } | |
456 } | |
457 | |
458 private static String getWildcardName(WildcardType type) { | |
459 StringBuilder b = new StringBuilder(); | |
460 if (type.getExtendsBound() != null) { | |
461 b.append("? extends ").append(getSimpleName(type.getExtendsBound())); | |
462 } else if (type.getSuperBound() != null) { | |
463 b.append("? super ").append(getSimpleName(type.getExtendsBound())); | |
464 } | |
465 return b.toString(); | |
466 } | |
467 | |
468 public static String getDeclaredName(DeclaredType element, boolean includeTypeVariables) { | |
469 String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString()); | |
470 | |
471 if (!includeTypeVariables || element.getTypeArguments().size() == 0) { | |
472 return simpleName; | |
473 } | |
474 | |
475 StringBuilder b = new StringBuilder(simpleName); | |
476 b.append("<"); | |
477 if (element.getTypeArguments().size() > 0) { | |
478 for (int i = 0; i < element.getTypeArguments().size(); i++) { | |
479 b.append(getSimpleName(element.getTypeArguments().get(i))); | |
480 if (i < element.getTypeArguments().size() - 1) { | |
481 b.append(", "); | |
482 } | |
483 } | |
484 } | |
485 b.append(">"); | |
486 return b.toString(); | |
487 } | |
488 | |
489 public static String fixECJBinaryNameIssue(String name) { | |
490 if (name.contains("$")) { | |
491 int lastIndex = name.lastIndexOf('$'); | |
492 return name.substring(lastIndex + 1, name.length()); | |
493 } | |
494 return name; | |
495 } | |
496 | |
497 public static String getQualifiedName(TypeElement element) { | |
498 String qualifiedName = element.getQualifiedName().toString(); | |
499 if (qualifiedName.contains("$")) { | |
500 /* | |
501 * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the | |
502 * proper canonical class name. It leaves the $ in the qualified name of the class. So | |
503 * one instance of a TypeElement may be loaded in binary and one in source form. The | |
504 * current type comparison in #typeEquals compares by the qualified name so the | |
505 * qualified name must match. This is basically a hack to fix the returned qualified | |
506 * name of eclipse. | |
507 */ | |
508 qualifiedName = qualifiedName.replace('$', '.'); | |
509 } | |
510 return qualifiedName; | |
511 } | |
512 | |
513 public static String getQualifiedName(TypeMirror mirror) { | |
514 switch (mirror.getKind()) { | |
515 case BOOLEAN: | |
516 return "boolean"; | |
517 case BYTE: | |
518 return "byte"; | |
519 case CHAR: | |
520 return "char"; | |
521 case DOUBLE: | |
522 return "double"; | |
523 case SHORT: | |
524 return "short"; | |
525 case FLOAT: | |
526 return "float"; | |
527 case INT: | |
528 return "int"; | |
529 case LONG: | |
530 return "long"; | |
531 case DECLARED: | |
532 return getQualifiedName(fromTypeMirror(mirror)); | |
533 case ARRAY: | |
534 return getQualifiedName(((ArrayType) mirror).getComponentType()); | |
535 case VOID: | |
536 return "void"; | |
537 case NULL: | |
538 return "null"; | |
539 case TYPEVAR: | |
540 return getSimpleName(mirror); | |
541 case ERROR: | |
542 throw new CompileErrorException("Type error " + mirror); | |
543 case EXECUTABLE: | |
544 return ((ExecutableType) mirror).toString(); | |
545 case NONE: | |
546 return "$none"; | |
547 default: | |
548 throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); | |
549 } | |
550 } | |
551 | |
552 public static boolean isVoid(TypeMirror mirror) { | |
553 return mirror != null && mirror.getKind() == TypeKind.VOID; | |
554 } | |
555 | |
556 public static boolean isPrimitive(TypeMirror mirror) { | |
557 return mirror != null && mirror.getKind().isPrimitive(); | |
558 } | |
559 | |
560 public static List<String> getQualifiedSuperTypeNames(TypeElement element) { | |
561 List<TypeElement> types = getSuperTypes(element); | |
562 List<String> qualifiedNames = new ArrayList<>(); | |
563 for (TypeElement type : types) { | |
564 qualifiedNames.add(getQualifiedName(type)); | |
565 } | |
566 return qualifiedNames; | |
567 } | |
568 | |
569 public static List<TypeElement> getDeclaredTypes(TypeElement element) { | |
570 return ElementFilter.typesIn(element.getEnclosedElements()); | |
571 } | |
572 | |
573 public static boolean isEnclosedIn(Element enclosedIn, Element element) { | |
574 if (element == null) { | |
575 return false; | |
576 } else if (typeEquals(enclosedIn.asType(), element.asType())) { | |
577 return true; | |
578 } else { | |
579 return isEnclosedIn(enclosedIn, element.getEnclosingElement()); | |
580 } | |
581 } | |
582 | |
583 public static TypeElement findRootEnclosingType(Element element) { | |
584 List<Element> elements = getElementHierarchy(element); | |
585 | |
586 for (int i = elements.size() - 1; i >= 0; i--) { | |
587 if (elements.get(i).getKind().isClass()) { | |
588 return (TypeElement) elements.get(i); | |
589 } | |
590 } | |
591 | |
592 return null; | |
593 } | |
594 | |
595 public static List<Element> getElementHierarchy(Element e) { | |
596 List<Element> elements = new ArrayList<>(); | |
597 elements.add(e); | |
598 | |
599 Element enclosing = e.getEnclosingElement(); | |
600 while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { | |
601 elements.add(enclosing); | |
602 enclosing = enclosing.getEnclosingElement(); | |
603 } | |
604 if (enclosing != null) { | |
605 elements.add(enclosing); | |
606 } | |
607 return elements; | |
608 } | |
609 | |
610 public static TypeElement findNearestEnclosingType(Element element) { | |
611 List<Element> elements = getElementHierarchy(element); | |
612 for (Element e : elements) { | |
613 if (e.getKind().isClass() || e.getKind().isInterface()) { | |
614 return (TypeElement) e; | |
615 } | |
616 } | |
617 return null; | |
618 } | |
619 | |
620 public static List<TypeElement> getDirectSuperTypes(TypeElement element) { | |
621 List<TypeElement> types = new ArrayList<>(); | |
622 TypeElement superElement = getSuperType(element); | |
623 if (superElement != null) { | |
624 types.add(superElement); | |
625 types.addAll(getDirectSuperTypes(superElement)); | |
626 } | |
627 | |
628 return types; | |
629 } | |
630 | |
631 /** | |
632 * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a | |
633 * given type element. | |
634 */ | |
635 public static TypeElement getSuperType(TypeElement element) { | |
636 if (element.getSuperclass() != null) { | |
637 return fromTypeMirror(element.getSuperclass()); | |
638 } | |
639 return null; | |
640 } | |
641 | |
642 public static List<TypeElement> getSuperTypes(TypeElement element) { | |
643 List<TypeElement> types = new ArrayList<>(); | |
644 List<TypeElement> superTypes = null; | |
645 List<TypeElement> superInterfaces = null; | |
646 TypeElement superElement = getSuperType(element); | |
647 if (superElement != null) { | |
648 types.add(superElement); | |
649 superTypes = getSuperTypes(superElement); | |
650 } | |
651 for (TypeMirror interfaceMirror : element.getInterfaces()) { | |
652 TypeElement interfaceElement = fromTypeMirror(interfaceMirror); | |
653 if (interfaceElement != null) { | |
654 types.add(interfaceElement); | |
655 if (superInterfaces == null) { | |
656 superInterfaces = getSuperTypes(interfaceElement); | |
657 } else { | |
658 superInterfaces.addAll(getSuperTypes(interfaceElement)); | |
659 } | |
660 } | |
661 } | |
662 | |
663 if (superTypes != null) { | |
664 types.addAll(superTypes); | |
665 } | |
666 | |
667 if (superInterfaces != null) { | |
668 types.addAll(superInterfaces); | |
669 } | |
670 | |
671 return types; | |
672 } | |
673 | |
674 public static String getPackageName(TypeElement element) { | |
675 return findPackageElement(element).getQualifiedName().toString(); | |
676 } | |
677 | |
678 public static String getEnclosedQualifiedName(DeclaredType mirror) { | |
679 Element e = ((TypeElement) mirror.asElement()).getEnclosingElement(); | |
680 if (e.getKind() == ElementKind.PACKAGE) { | |
681 return ((PackageElement) e).getQualifiedName().toString(); | |
682 } else if (e.getKind().isInterface() || e.getKind().isClass()) { | |
683 return getQualifiedName((TypeElement) e); | |
684 } else { | |
685 return null; | |
686 } | |
687 } | |
688 | |
689 public static String getPackageName(TypeMirror mirror) { | |
690 switch (mirror.getKind()) { | |
691 case BOOLEAN: | |
692 case BYTE: | |
693 case CHAR: | |
694 case DOUBLE: | |
695 case FLOAT: | |
696 case SHORT: | |
697 case INT: | |
698 case LONG: | |
699 case VOID: | |
700 case NULL: | |
701 case TYPEVAR: | |
702 return null; | |
703 case DECLARED: | |
704 PackageElement pack = findPackageElement(fromTypeMirror(mirror)); | |
705 if (pack == null) { | |
706 throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); | |
707 } | |
708 return pack.getQualifiedName().toString(); | |
709 case ARRAY: | |
710 return getSimpleName(((ArrayType) mirror).getComponentType()); | |
711 case EXECUTABLE: | |
712 return null; | |
713 default: | |
714 throw new RuntimeException("Unknown type specified " + mirror.getKind()); | |
715 } | |
716 } | |
717 | |
718 public static String createConstantName(String simpleName) { | |
719 // TODO use camel case to produce underscores. | |
720 return simpleName.toString().toUpperCase(); | |
721 } | |
722 | |
723 public static TypeElement fromTypeMirror(TypeMirror mirror) { | |
724 switch (mirror.getKind()) { | |
725 case DECLARED: | |
726 return (TypeElement) ((DeclaredType) mirror).asElement(); | |
727 case ARRAY: | |
728 return fromTypeMirror(((ArrayType) mirror).getComponentType()); | |
729 default: | |
730 return null; | |
731 } | |
732 } | |
733 | |
734 @SuppressWarnings("unchecked") | |
735 public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) { | |
736 List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name); | |
737 List<T> result = new ArrayList<>(); | |
738 | |
739 if (values != null) { | |
740 for (AnnotationValue value : values) { | |
741 T annotationValue = resolveAnnotationValue(expectedListType, value); | |
742 if (annotationValue != null) { | |
743 result.add(annotationValue); | |
744 } | |
745 } | |
746 } | |
747 return result; | |
748 } | |
749 | |
750 public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) { | |
751 return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); | |
752 } | |
753 | |
754 @SuppressWarnings({"unchecked"}) | |
755 private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) { | |
756 if (value == null) { | |
757 return null; | |
758 } | |
759 | |
760 Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); | |
761 if (unboxedValue != null) { | |
762 if (expectedType == TypeMirror.class && unboxedValue instanceof String) { | |
763 return null; | |
764 } | |
765 if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { | |
766 throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); | |
767 } | |
768 } | |
769 return (T) unboxedValue; | |
770 } | |
771 | |
772 public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { | |
773 ExecutableElement valueMethod = null; | |
774 for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { | |
775 if (method.getSimpleName().toString().equals(name)) { | |
776 valueMethod = method; | |
777 break; | |
778 } | |
779 } | |
780 | |
781 if (valueMethod == null) { | |
782 return null; | |
783 } | |
784 | |
785 AnnotationValue value = mirror.getElementValues().get(valueMethod); | |
786 if (value == null) { | |
787 value = valueMethod.getDefaultValue(); | |
788 } | |
789 | |
790 return value; | |
791 } | |
792 | |
793 private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> { | |
794 | |
795 @Override | |
796 public Object visitBoolean(boolean b, Void p) { | |
797 return Boolean.valueOf(b); | |
798 } | |
799 | |
800 @Override | |
801 public Object visitByte(byte b, Void p) { | |
802 return Byte.valueOf(b); | |
803 } | |
804 | |
805 @Override | |
806 public Object visitChar(char c, Void p) { | |
807 return c; | |
808 } | |
809 | |
810 @Override | |
811 public Object visitDouble(double d, Void p) { | |
812 return d; | |
813 } | |
814 | |
815 @Override | |
816 public Object visitFloat(float f, Void p) { | |
817 return f; | |
818 } | |
819 | |
820 @Override | |
821 public Object visitInt(int i, Void p) { | |
822 return i; | |
823 } | |
824 | |
825 @Override | |
826 public Object visitLong(long i, Void p) { | |
827 return i; | |
828 } | |
829 | |
830 @Override | |
831 public Object visitShort(short s, Void p) { | |
832 return s; | |
833 } | |
834 | |
835 @Override | |
836 public Object visitString(String s, Void p) { | |
837 return s; | |
838 } | |
839 | |
840 @Override | |
841 public Object visitType(TypeMirror t, Void p) { | |
842 return t; | |
843 } | |
844 | |
845 @Override | |
846 public Object visitEnumConstant(VariableElement c, Void p) { | |
847 return c; | |
848 } | |
849 | |
850 @Override | |
851 public Object visitAnnotation(AnnotationMirror a, Void p) { | |
852 return a; | |
853 } | |
854 | |
855 @Override | |
856 public Object visitArray(List<? extends AnnotationValue> vals, Void p) { | |
857 return vals; | |
858 } | |
859 | |
860 } | |
861 | |
862 public static String printException(Throwable e) { | |
863 StringWriter string = new StringWriter(); | |
864 PrintWriter writer = new PrintWriter(string); | |
865 e.printStackTrace(writer); | |
866 writer.flush(); | |
867 string.flush(); | |
868 return e.getMessage() + "\r\n" + string.toString(); | |
869 } | |
870 | |
871 public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) { | |
872 return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); | |
873 } | |
874 | |
875 public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) { | |
876 TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); | |
877 return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); | |
878 } | |
879 | |
880 public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) { | |
881 return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); | |
882 } | |
883 | |
884 public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeMirror expectedAnnotationType) { | |
885 for (AnnotationMirror mirror : mirrors) { | |
886 if (typeEquals(mirror.getAnnotationType(), expectedAnnotationType)) { | |
887 return mirror; | |
888 } | |
889 } | |
890 return null; | |
891 } | |
892 | |
893 public static PackageElement findPackageElement(Element type) { | |
894 List<Element> hierarchy = getElementHierarchy(type); | |
895 for (Element element : hierarchy) { | |
896 if (element.getKind() == ElementKind.PACKAGE) { | |
897 return (PackageElement) element; | |
898 } | |
899 } | |
900 return null; | |
901 } | |
902 | |
903 public static String firstLetterUpperCase(String name) { | |
904 if (name == null || name.isEmpty()) { | |
905 return name; | |
906 } | |
907 return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); | |
908 } | |
909 | |
910 public static String firstLetterLowerCase(String name) { | |
911 if (name == null || name.isEmpty()) { | |
912 return name; | |
913 } | |
914 return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); | |
915 } | |
916 | |
917 private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { | |
918 List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements()); | |
919 method: for (ExecutableElement method : methods) { | |
920 if (!method.getSimpleName().toString().equals(name)) { | |
921 continue; | |
922 } | |
923 if (method.getParameters().size() != params.length) { | |
924 continue; | |
925 } | |
926 for (int i = 0; i < params.length; i++) { | |
927 TypeMirror param1 = params[i]; | |
928 TypeMirror param2 = method.getParameters().get(i).asType(); | |
929 if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { | |
930 if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { | |
931 continue method; | |
932 } | |
933 } | |
934 } | |
935 return method; | |
936 } | |
937 return null; | |
938 } | |
939 | |
940 public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { | |
941 return !getDeclaredMethodsInSuperTypes(element, name, params).isEmpty(); | |
942 } | |
943 | |
944 /** | |
945 * Gets the methods in the super type hierarchy (excluding interfaces) that are overridden by a | |
946 * method in a subtype. | |
947 * | |
948 * @param declaringElement the subtype element declaring the method | |
949 * @param name the name of the method | |
950 * @param params the signature of the method | |
951 */ | |
952 public static List<ExecutableElement> getDeclaredMethodsInSuperTypes(TypeElement declaringElement, String name, TypeMirror... params) { | |
953 List<ExecutableElement> superMethods = new ArrayList<>(); | |
954 List<TypeElement> superElements = getSuperTypes(declaringElement); | |
955 | |
956 for (TypeElement superElement : superElements) { | |
957 ExecutableElement superMethod = getDeclaredMethod(superElement, name, params); | |
958 if (superMethod != null) { | |
959 superMethods.add(superMethod); | |
960 } | |
961 } | |
962 return superMethods; | |
963 } | |
964 | |
965 public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { | |
966 if (type1 == type2) { | |
967 return true; | |
968 } else if (type1 == null || type2 == null) { | |
969 return false; | |
970 } else { | |
971 if (type1.getKind() == type2.getKind()) { | |
972 return getUniqueIdentifier(type1).equals(getUniqueIdentifier(type2)); | |
973 } else { | |
974 return false; | |
975 } | |
976 } | |
977 } | |
978 | |
979 public static boolean areTypesCompatible(TypeMirror type1, TypeMirror type2) { | |
980 if (typeEquals(type1, type2)) { | |
981 return true; | |
982 } else if (kindIsIntegral(type1.getKind())) { | |
983 return kindIsIntegral(type2.getKind()); | |
984 } else if (type1.getKind() == TypeKind.NULL) { | |
985 if (type2.getKind() == TypeKind.NULL) { | |
986 return false; | |
987 } | |
988 return true; | |
989 } else if (type2.getKind() == TypeKind.NULL) { | |
990 return true; | |
991 } else { | |
992 return false; | |
993 } | |
994 } | |
995 | |
996 private static boolean kindIsIntegral(TypeKind kind) { | |
997 return kind == TypeKind.BYTE || kind == TypeKind.SHORT || kind == TypeKind.INT || kind == TypeKind.LONG; | |
998 } | |
999 | |
1000 public static List<String> getUniqueIdentifiers(List<TypeMirror> typeMirror) { | |
1001 List<String> ids = new ArrayList<>(); | |
1002 for (TypeMirror type : typeMirror) { | |
1003 ids.add(getUniqueIdentifier(type)); | |
1004 } | |
1005 return ids; | |
1006 } | |
1007 | |
1008 public static String getUniqueIdentifier(TypeMirror typeMirror) { | |
1009 if (typeMirror.getKind() == TypeKind.ARRAY) { | |
1010 return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]"; | |
1011 } else { | |
1012 return getQualifiedName(typeMirror); | |
1013 } | |
1014 } | |
1015 | |
1016 public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { | |
1017 if (typeEquals(t1, t2)) { | |
1018 return 0; | |
1019 } | |
1020 Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); | |
1021 if (t1SuperSet.contains(getQualifiedName(t2))) { | |
1022 return -1; | |
1023 } | |
1024 | |
1025 Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); | |
1026 if (t2SuperSet.contains(getQualifiedName(t1))) { | |
1027 return 1; | |
1028 } | |
1029 return 0; | |
1030 } | |
1031 | |
1032 public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) { | |
1033 if (ElementUtils.containsType(thrownTypes, exceptionType)) { | |
1034 return true; | |
1035 } | |
1036 | |
1037 if (isRuntimeException(exceptionType)) { | |
1038 return true; | |
1039 } | |
1040 | |
1041 // search for any super types | |
1042 for (TypeElement typeElement : getSuperTypes(fromTypeMirror(exceptionType))) { | |
1043 if (ElementUtils.containsType(thrownTypes, typeElement.asType())) { | |
1044 return true; | |
1045 } | |
1046 } | |
1047 | |
1048 return false; | |
1049 } | |
1050 | |
1051 public static void setVisibility(Set<Modifier> modifiers, Modifier visibility) { | |
1052 Modifier current = getVisibility(modifiers); | |
1053 if (current != visibility) { | |
1054 if (current != null) { | |
1055 modifiers.remove(current); | |
1056 } | |
1057 if (visibility != null) { | |
1058 modifiers.add(visibility); | |
1059 } | |
1060 } | |
1061 } | |
1062 | |
1063 public static Modifier getVisibility(Set<Modifier> modifier) { | |
1064 for (Modifier mod : modifier) { | |
1065 if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { | |
1066 return mod; | |
1067 } | |
1068 } | |
1069 return null; | |
1070 } | |
1071 | |
1072 private static boolean isRuntimeException(TypeMirror type) { | |
1073 Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); | |
1074 return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || getQualifiedName(type).equals(RuntimeException.class.getCanonicalName()); | |
1075 } | |
1076 | |
1077 private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) { | |
1078 for (TypeMirror otherTypeMirror : collection) { | |
1079 if (typeEquals(otherTypeMirror, type)) { | |
1080 return true; | |
1081 } | |
1082 } | |
1083 return false; | |
1084 } | |
1085 | |
1086 public static boolean isTopLevelClass(TypeMirror importType) { | |
1087 TypeElement type = fromTypeMirror(importType); | |
1088 if (type != null && type.getEnclosingElement() != null) { | |
1089 return !type.getEnclosingElement().getKind().isClass(); | |
1090 } | |
1091 return true; | |
1092 } | |
1093 | |
1094 public static boolean isObject(TypeMirror actualType) { | |
1095 return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object"); | |
1096 } | |
1097 | |
1098 public static TypeMirror fillInGenericWildcards(TypeMirror type) { | |
1099 if (type.getKind() != TypeKind.DECLARED) { | |
1100 return type; | |
1101 } | |
1102 DeclaredType declaredType = (DeclaredType) type; | |
1103 TypeElement element = (TypeElement) declaredType.asElement(); | |
1104 if (element == null) { | |
1105 return type; | |
1106 } | |
1107 int typeParameters = element.getTypeParameters().size(); | |
1108 if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) { | |
1109 return ProcessorContext.getInstance().getEnvironment().getTypeUtils().erasure(type); | |
1110 } | |
1111 return type; | |
1112 } | |
1113 | |
1114 public static TypeMirror eraseGenericTypes(TypeMirror type) { | |
1115 if (type.getKind() != TypeKind.DECLARED) { | |
1116 return type; | |
1117 } | |
1118 DeclaredType declaredType = (DeclaredType) type; | |
1119 if (declaredType.getTypeArguments().size() == 0) { | |
1120 return type; | |
1121 } | |
1122 return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement()); | |
1123 } | |
1124 | |
1125 public static boolean variableEquals(VariableElement var1, VariableElement var2) { | |
1126 if (!var1.getSimpleName().equals(var2.getSimpleName())) { | |
1127 return false; | |
1128 } | |
1129 if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) { | |
1130 return false; | |
1131 } | |
1132 if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) { | |
1133 return false; | |
1134 } | |
1135 return true; | |
1136 } | |
1137 | |
1138 public static boolean executableEquals(ExecutableElement var1, ExecutableElement var2) { | |
1139 if (!var1.getSimpleName().equals(var2.getSimpleName())) { | |
1140 return false; | |
1141 } | |
1142 if (var1.getParameters().size() != var2.getParameters().size()) { | |
1143 return false; | |
1144 } | |
1145 if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) { | |
1146 return false; | |
1147 } | |
1148 if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) { | |
1149 return false; | |
1150 } | |
1151 for (int i = 0; i < var1.getParameters().size(); i++) { | |
1152 if (!typeEquals(var1.getParameters().get(i).asType(), var2.getParameters().get(i).asType())) { | |
1153 return false; | |
1154 } | |
1155 } | |
1156 return true; | |
1157 } | |
1158 | |
1159 public static boolean elementEquals(Element element1, Element element2) { | |
1160 if (element1.getKind() != element2.getKind()) { | |
1161 return false; | |
1162 } else if (element1 instanceof VariableElement) { | |
1163 return variableEquals((VariableElement) element1, (VariableElement) element2); | |
1164 } else if (element1 instanceof ExecutableElement) { | |
1165 return executableEquals((ExecutableElement) element1, (ExecutableElement) element2); | |
1166 } else if (element1 instanceof TypeElement) { | |
1167 return typeEquals(element1.asType(), element2.asType()); | |
1168 } else if (element1 instanceof PackageElement) { | |
1169 return element1.getSimpleName().equals(element2.getSimpleName()); | |
1170 } else { | |
1171 throw new AssertionError("unsupported element type"); | |
1172 } | |
1173 } | |
1174 | |
1175 public static List<TypeMirror> sortTypes(List<TypeMirror> list, final boolean reverse) { | |
1176 Collections.sort(list, new Comparator<TypeMirror>() { | |
1177 public int compare(TypeMirror o1, TypeMirror o2) { | |
1178 if (reverse) { | |
1179 return compareType(o2, o1); | |
1180 } else { | |
1181 return compareType(o1, o2); | |
1182 } | |
1183 } | |
1184 }); | |
1185 return list; | |
1186 } | |
1187 | |
1188 public static int compareType(TypeMirror signature1, TypeMirror signature2) { | |
1189 if (signature1 == null) { | |
1190 return 1; | |
1191 } else if (signature2 == null) { | |
1192 return -1; | |
1193 } | |
1194 | |
1195 if (ElementUtils.typeEquals(signature1, signature2)) { | |
1196 return 0; | |
1197 } | |
1198 | |
1199 if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) { | |
1200 TypeElement element1 = ElementUtils.fromTypeMirror(signature1); | |
1201 TypeElement element2 = ElementUtils.fromTypeMirror(signature2); | |
1202 | |
1203 if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) { | |
1204 return -1; | |
1205 } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) { | |
1206 return 1; | |
1207 } | |
1208 } | |
1209 return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2)); | |
1210 } | |
1211 | |
1212 public static List<TypeMirror> uniqueSortedTypes(Collection<TypeMirror> types, boolean reverse) { | |
1213 if (types.isEmpty()) { | |
1214 return new ArrayList<>(0); | |
1215 } else if (types.size() <= 1) { | |
1216 if (types instanceof List) { | |
1217 return (List<TypeMirror>) types; | |
1218 } else { | |
1219 return new ArrayList<>(types); | |
1220 } | |
1221 } | |
1222 Map<String, TypeMirror> sourceTypes = new HashMap<>(); | |
1223 for (TypeMirror type : types) { | |
1224 sourceTypes.put(ElementUtils.getTypeId(type), type); | |
1225 } | |
1226 return sortTypes(new ArrayList<>(sourceTypes.values()), reverse); | |
1227 } | |
1228 | |
1229 public static int compareMethod(ExecutableElement method1, ExecutableElement method2) { | |
1230 List<? extends VariableElement> parameters1 = method1.getParameters(); | |
1231 List<? extends VariableElement> parameters2 = method2.getParameters(); | |
1232 if (parameters1.size() != parameters2.size()) { | |
1233 return Integer.compare(parameters1.size(), parameters2.size()); | |
1234 } | |
1235 | |
1236 int result = 0; | |
1237 for (int i = 0; i < parameters1.size(); i++) { | |
1238 VariableElement var1 = parameters1.get(i); | |
1239 VariableElement var2 = parameters2.get(i); | |
1240 result = compareType(var1.asType(), var2.asType()); | |
1241 if (result != 0) { | |
1242 return result; | |
1243 } | |
1244 } | |
1245 | |
1246 result = method1.getSimpleName().toString().compareTo(method2.getSimpleName().toString()); | |
1247 if (result == 0) { | |
1248 // if still no difference sort by enclosing type name | |
1249 TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(method1); | |
1250 TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(method2); | |
1251 result = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); | |
1252 } | |
1253 return result; | |
1254 } | |
1255 | |
1256 } |