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 }