comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java @ 10597:79041ab43660

Truffle-DSL: API-change: Renamed truffle.api.codegen to truffle.api.dsl for all projects and packages.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Jul 2013 20:58:32 +0200
parents
children efe58aa92f86
comparison
equal deleted inserted replaced
10596:f43eb2f1bbbc 10597:79041ab43660
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;
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.ast.*;
35 import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.*;
36 import com.oracle.truffle.dsl.processor.compiler.*;
37
38 /**
39 * THIS IS NOT PUBLIC API.
40 */
41 public class Utils {
42
43 public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
44 List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
45 for (ExecutableElement executableElement : elements) {
46 if (executableElement.getSimpleName().toString().equals(name)) {
47 return executableElement;
48 }
49 }
50 return null;
51 }
52
53 public static VariableElement findVariableElement(DeclaredType type, String name) {
54 List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
55 for (VariableElement variableElement : elements) {
56 if (variableElement.getSimpleName().toString().equals(name)) {
57 return variableElement;
58 }
59 }
60 return null;
61 }
62
63 public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
64 if (method instanceof CodeExecutableElement) {
65 return ((CodeExecutableElement) method).getBody();
66 } else {
67 return CompilerFactory.getCompiler(method).getMethodBody(env, method);
68 }
69 }
70
71 public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
72 TypeMirror boxedType = primitiveType;
73 if (boxedType.getKind().isPrimitive()) {
74 boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
75 }
76 return boxedType;
77 }
78
79 public static List<TypeMirror> asTypeMirrors(List<? extends Element> elements) {
80 List<TypeMirror> types = new ArrayList<>(elements.size());
81 for (Element element : elements) {
82 types.add(element.asType());
83 }
84 return types;
85 }
86
87 public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
88 return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
89 }
90
91 public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
92 Class<? extends Annotation> annotationClass) {
93 List<AnnotationMirror> result = new ArrayList<>();
94 if (markerAnnotation != null) {
95 result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
96 }
97 AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
98 if (explicit != null) {
99 result.add(explicit);
100 }
101 return result;
102 }
103
104 public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
105 if (types.length == 0) {
106 return context.getType(Object.class);
107 }
108 TypeMirror prev = types[0];
109 for (int i = 1; i < types.length; i++) {
110 prev = getCommonSuperType(context, prev, types[i]);
111 }
112 return prev;
113 }
114
115 public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
116 if (typeEquals(type1, type2)) {
117 return type1;
118 }
119 TypeElement element1 = fromTypeMirror(type1);
120 TypeElement element2 = fromTypeMirror(type2);
121 if (element1 == null || element2 == null) {
122 return context.getType(Object.class);
123 }
124
125 List<TypeElement> element1Types = getDirectSuperTypes(element1);
126 element1Types.add(0, element1);
127 List<TypeElement> element2Types = getDirectSuperTypes(element2);
128 element2Types.add(0, element2);
129
130 for (TypeElement superType1 : element1Types) {
131 for (TypeElement superType2 : element2Types) {
132 if (typeEquals(superType1.asType(), superType2.asType())) {
133 return superType2.asType();
134 }
135 }
136 }
137 return context.getType(Object.class);
138 }
139
140 public static String getReadableSignature(ExecutableElement method) {
141 // TODO toString does not guarantee a good signature
142 return method.toString();
143 }
144
145 public static boolean hasError(TypeMirror mirror) {
146 switch (mirror.getKind()) {
147 case BOOLEAN:
148 case BYTE:
149 case CHAR:
150 case DOUBLE:
151 case FLOAT:
152 case INT:
153 case SHORT:
154 case LONG:
155 case DECLARED:
156 case VOID:
157 case TYPEVAR:
158 return false;
159 case ARRAY:
160 return hasError(((ArrayType) mirror).getComponentType());
161 case ERROR:
162 return true;
163 default:
164 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
165 }
166 }
167
168 public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) {
169 if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
170 return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
171 } else {
172 return isAssignableImpl(context, from, to);
173 }
174 }
175
176 private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) {
177 // JLS 5.1.1 identity conversion
178 if (Utils.typeEquals(from, to)) {
179 return true;
180 }
181
182 // JLS 5.1.2 widening primitives
183 if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) {
184 TypeKind fromKind = from.getKind();
185 TypeKind toKind = to.getKind();
186 switch (fromKind) {
187 case BYTE:
188 switch (toKind) {
189 case SHORT:
190 case INT:
191 case LONG:
192 case FLOAT:
193 case DOUBLE:
194 return true;
195 }
196 break;
197 case SHORT:
198 switch (toKind) {
199 case INT:
200 case LONG:
201 case FLOAT:
202 case DOUBLE:
203 return true;
204 }
205 break;
206 case CHAR:
207 switch (toKind) {
208 case INT:
209 case LONG:
210 case FLOAT:
211 case DOUBLE:
212 return true;
213 }
214 break;
215 case INT:
216 switch (toKind) {
217 case LONG:
218 case FLOAT:
219 case DOUBLE:
220 return true;
221 }
222 break;
223 case LONG:
224 switch (toKind) {
225 case FLOAT:
226 case DOUBLE:
227 return true;
228 }
229 break;
230 case FLOAT:
231 switch (toKind) {
232 case DOUBLE:
233 return true;
234 }
235 break;
236
237 }
238 return false;
239 } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) {
240 return false;
241 }
242
243 if (from instanceof ArrayType && to instanceof ArrayType) {
244 return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
245 }
246
247 TypeElement fromType = Utils.fromTypeMirror(from);
248 TypeElement toType = Utils.fromTypeMirror(to);
249 if (fromType == null || toType == null) {
250 return false;
251 }
252 // JLS 5.1.6 narrowing reference conversion
253
254 List<TypeElement> superTypes = Utils.getSuperTypes(fromType);
255 for (TypeElement superType : superTypes) {
256 if (Utils.typeEquals(superType.asType(), to)) {
257 return true;
258 }
259 }
260
261 // TODO more spec
262 return false;
263 }
264
265 public static Set<Modifier> modifiers(Modifier... modifier) {
266 return new LinkedHashSet<>(Arrays.asList(modifier));
267 }
268
269 public static String getTypeId(TypeMirror mirror) {
270 switch (mirror.getKind()) {
271 case BOOLEAN:
272 return "Boolean";
273 case BYTE:
274 return "Byte";
275 case CHAR:
276 return "Char";
277 case DOUBLE:
278 return "Double";
279 case FLOAT:
280 return "Float";
281 case SHORT:
282 return "Short";
283 case INT:
284 return "Int";
285 case LONG:
286 return "Long";
287 case DECLARED:
288 return ((DeclaredType) mirror).asElement().getSimpleName().toString();
289 case ARRAY:
290 return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
291 case VOID:
292 return "Void";
293 case WILDCARD:
294 StringBuilder b = new StringBuilder();
295 WildcardType type = (WildcardType) mirror;
296 if (type.getExtendsBound() != null) {
297 b.append("Extends").append(getTypeId(type.getExtendsBound()));
298 } else if (type.getSuperBound() != null) {
299 b.append("Super").append(getTypeId(type.getExtendsBound()));
300 }
301 return b.toString();
302 case TYPEVAR:
303 return "Any";
304 case ERROR:
305 throw new CompileErrorException("Type error " + mirror);
306 default:
307 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
308 }
309 }
310
311 public static String getSimpleName(TypeElement element) {
312 return getSimpleName(element.asType());
313 }
314
315 public static String getSimpleName(TypeMirror mirror) {
316 switch (mirror.getKind()) {
317 case BOOLEAN:
318 return "boolean";
319 case BYTE:
320 return "byte";
321 case CHAR:
322 return "char";
323 case DOUBLE:
324 return "double";
325 case FLOAT:
326 return "float";
327 case SHORT:
328 return "short";
329 case INT:
330 return "int";
331 case LONG:
332 return "long";
333 case DECLARED:
334 return getDeclaredName((DeclaredType) mirror);
335 case ARRAY:
336 return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
337 case VOID:
338 return "void";
339 case WILDCARD:
340 return getWildcardName((WildcardType) mirror);
341 case TYPEVAR:
342 return "?";
343 case ERROR:
344 throw new CompileErrorException("Type error " + mirror);
345 default:
346 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
347 }
348 }
349
350 private static String getWildcardName(WildcardType type) {
351 StringBuilder b = new StringBuilder();
352 if (type.getExtendsBound() != null) {
353 b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
354 } else if (type.getSuperBound() != null) {
355 b.append("? super ").append(getSimpleName(type.getExtendsBound()));
356 }
357 return b.toString();
358 }
359
360 private static String getDeclaredName(DeclaredType element) {
361 String simpleName = element.asElement().getSimpleName().toString();
362
363 if (element.getTypeArguments().size() == 0) {
364 return simpleName;
365 }
366
367 StringBuilder b = new StringBuilder(simpleName);
368 b.append("<");
369 if (element.getTypeArguments().size() > 0) {
370 for (int i = 0; i < element.getTypeArguments().size(); i++) {
371 b.append(getSimpleName(element.getTypeArguments().get(i)));
372 if (i < element.getTypeArguments().size() - 1) {
373 b.append(", ");
374 }
375 }
376 }
377 b.append(">");
378 return b.toString();
379 }
380
381 public static String getQualifiedName(TypeElement element) {
382 return element.getQualifiedName().toString();
383 }
384
385 public static String getQualifiedName(TypeMirror mirror) {
386 switch (mirror.getKind()) {
387 case BOOLEAN:
388 return "boolean";
389 case BYTE:
390 return "byte";
391 case CHAR:
392 return "char";
393 case DOUBLE:
394 return "double";
395 case SHORT:
396 return "short";
397 case FLOAT:
398 return "float";
399 case INT:
400 return "int";
401 case LONG:
402 return "long";
403 case DECLARED:
404 return getQualifiedName(fromTypeMirror(mirror));
405 case ARRAY:
406 return getQualifiedName(((ArrayType) mirror).getComponentType());
407 case VOID:
408 return "void";
409 case TYPEVAR:
410 return getSimpleName(mirror);
411 case ERROR:
412 throw new CompileErrorException("Type error " + mirror);
413 case NONE:
414 return "$none";
415 default:
416 throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
417 }
418 }
419
420 public static boolean isVoid(TypeMirror mirror) {
421 return mirror.getKind() == TypeKind.VOID;
422 }
423
424 public static boolean isPrimitive(TypeMirror mirror) {
425 return mirror.getKind().isPrimitive();
426 }
427
428 public static boolean isPrimitiveOrVoid(TypeMirror mirror) {
429 return isPrimitive(mirror) || isVoid(mirror);
430 }
431
432 public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
433 List<TypeElement> types = getSuperTypes(element);
434 List<String> qualifiedNames = new ArrayList<>();
435 for (TypeElement type : types) {
436 qualifiedNames.add(getQualifiedName(type));
437 }
438 return qualifiedNames;
439 }
440
441 public static List<TypeElement> getDeclaredTypes(TypeElement element) {
442 return ElementFilter.typesIn(element.getEnclosedElements());
443 }
444
445 public static VariableElement findDeclaredField(TypeMirror type, String singletonName) {
446 List<VariableElement> elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements());
447 for (VariableElement var : elements) {
448 if (var.getSimpleName().toString().equals(singletonName)) {
449 return var;
450 }
451 }
452 return null;
453 }
454
455 public static TypeElement findRootEnclosingType(Element element) {
456 List<Element> elements = getElementHierarchy(element);
457
458 for (int i = elements.size() - 1; i >= 0; i--) {
459 if (elements.get(i).getKind().isClass()) {
460 return (TypeElement) elements.get(i);
461 }
462 }
463
464 return null;
465 }
466
467 public static List<Element> getElementHierarchy(Element e) {
468 List<Element> elements = new ArrayList<>();
469 elements.add(e);
470
471 Element enclosing = e.getEnclosingElement();
472 while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
473 elements.add(enclosing);
474 enclosing = enclosing.getEnclosingElement();
475 }
476 if (enclosing != null) {
477 elements.add(enclosing);
478 }
479 return elements;
480 }
481
482 public static TypeElement findNearestEnclosingType(Element element) {
483 List<Element> elements = getElementHierarchy(element);
484 for (Element e : elements) {
485 if (e.getKind().isClass()) {
486 return (TypeElement) e;
487 }
488 }
489 return null;
490 }
491
492 public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
493 List<TypeElement> types = new ArrayList<>();
494 if (element.getSuperclass() != null) {
495 TypeElement superElement = fromTypeMirror(element.getSuperclass());
496 if (superElement != null) {
497 types.add(superElement);
498 types.addAll(getDirectSuperTypes(superElement));
499 }
500 }
501
502 return types;
503 }
504
505 public static List<TypeElement> getSuperTypes(TypeElement element) {
506 List<TypeElement> types = new ArrayList<>();
507 List<TypeElement> superTypes = null;
508 List<TypeElement> superInterfaces = null;
509 if (element.getSuperclass() != null) {
510 TypeElement superElement = fromTypeMirror(element.getSuperclass());
511 if (superElement != null) {
512 types.add(superElement);
513 superTypes = getSuperTypes(superElement);
514 }
515 }
516 for (TypeMirror interfaceMirror : element.getInterfaces()) {
517 TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
518 if (interfaceElement != null) {
519 types.add(interfaceElement);
520 superInterfaces = getSuperTypes(interfaceElement);
521 }
522 }
523
524 if (superTypes != null) {
525 types.addAll(superTypes);
526 }
527
528 if (superInterfaces != null) {
529 types.addAll(superInterfaces);
530 }
531
532 return types;
533 }
534
535 public static String getPackageName(TypeElement element) {
536 return findPackageElement(element).getQualifiedName().toString();
537 }
538
539 public static String getPackageName(TypeMirror mirror) {
540 switch (mirror.getKind()) {
541 case BOOLEAN:
542 case BYTE:
543 case CHAR:
544 case DOUBLE:
545 case FLOAT:
546 case SHORT:
547 case INT:
548 case LONG:
549 case VOID:
550 case TYPEVAR:
551 return null;
552 case DECLARED:
553 PackageElement pack = findPackageElement(fromTypeMirror(mirror));
554 if (pack == null) {
555 throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
556 }
557 return pack.getQualifiedName().toString();
558 case ARRAY:
559 return getSimpleName(((ArrayType) mirror).getComponentType());
560 default:
561 throw new RuntimeException("Unknown type specified " + mirror.getKind());
562 }
563 }
564
565 public static String createConstantName(String simpleName) {
566 // TODO use camel case to produce underscores.
567 return simpleName.toString().toUpperCase();
568 }
569
570 public static TypeElement fromTypeMirror(TypeMirror mirror) {
571 switch (mirror.getKind()) {
572 case DECLARED:
573 return (TypeElement) ((DeclaredType) mirror).asElement();
574 case ARRAY:
575 return fromTypeMirror(((ArrayType) mirror).getComponentType());
576 default:
577 return null;
578 }
579 }
580
581 @SuppressWarnings("unchecked")
582 public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
583 List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
584 List<T> result = new ArrayList<>();
585
586 if (values != null) {
587 for (AnnotationValue value : values) {
588 T annotationValue = resolveAnnotationValue(expectedListType, value);
589 if (annotationValue != null) {
590 result.add(annotationValue);
591 }
592 }
593 }
594 return result;
595 }
596
597 public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
598 return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
599 }
600
601 @SuppressWarnings({"unchecked"})
602 private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
603 if (value == null) {
604 return null;
605 }
606
607 Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
608 if (unboxedValue != null) {
609 if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
610 return null;
611 }
612 if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
613 throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
614 }
615 }
616 return (T) unboxedValue;
617 }
618
619 public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
620 ExecutableElement valueMethod = null;
621 for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
622 if (method.getSimpleName().toString().equals(name)) {
623 valueMethod = method;
624 break;
625 }
626 }
627
628 if (valueMethod == null) {
629 return null;
630 }
631
632 AnnotationValue value = mirror.getElementValues().get(valueMethod);
633 if (value == null) {
634 value = valueMethod.getDefaultValue();
635 }
636
637 return value;
638 }
639
640 private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
641
642 @Override
643 public Object visitBoolean(boolean b, Void p) {
644 return Boolean.valueOf(b);
645 }
646
647 @Override
648 public Object visitByte(byte b, Void p) {
649 return Byte.valueOf(b);
650 }
651
652 @Override
653 public Object visitChar(char c, Void p) {
654 return c;
655 }
656
657 @Override
658 public Object visitDouble(double d, Void p) {
659 return d;
660 }
661
662 @Override
663 public Object visitFloat(float f, Void p) {
664 return f;
665 }
666
667 @Override
668 public Object visitInt(int i, Void p) {
669 return i;
670 }
671
672 @Override
673 public Object visitLong(long i, Void p) {
674 return i;
675 }
676
677 @Override
678 public Object visitShort(short s, Void p) {
679 return s;
680 }
681
682 @Override
683 public Object visitString(String s, Void p) {
684 return s;
685 }
686
687 @Override
688 public Object visitType(TypeMirror t, Void p) {
689 return t;
690 }
691
692 @Override
693 public Object visitEnumConstant(VariableElement c, Void p) {
694 return c;
695 }
696
697 @Override
698 public Object visitAnnotation(AnnotationMirror a, Void p) {
699 return a;
700 }
701
702 @Override
703 public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
704 return vals;
705 }
706
707 }
708
709 public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) {
710 return (Boolean) getAnnotationValue(mirror, name).getValue();
711 }
712
713 public static String printException(Throwable e) {
714 StringWriter string = new StringWriter();
715 PrintWriter writer = new PrintWriter(string);
716 e.printStackTrace(writer);
717 writer.flush();
718 return e.getMessage() + "\r\n" + string.toString();
719 }
720
721 public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
722 return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
723 }
724
725 public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
726 TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
727 for (AnnotationMirror mirror : mirrors) {
728 DeclaredType annotationType = mirror.getAnnotationType();
729 TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
730 if (actualAnnotationType.equals(expectedAnnotationType)) {
731 return mirror;
732 }
733 }
734 return null;
735 }
736
737 private static PackageElement findPackageElement(Element type) {
738 List<Element> hierarchy = getElementHierarchy(type);
739 for (Element element : hierarchy) {
740 if (element.getKind() == ElementKind.PACKAGE) {
741 return (PackageElement) element;
742 }
743 }
744 return null;
745 }
746
747 public static String firstLetterUpperCase(String name) {
748 if (name == null || name.isEmpty()) {
749 return name;
750 }
751 return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
752 }
753
754 public static String firstLetterLowerCase(String name) {
755 if (name == null || name.isEmpty()) {
756 return name;
757 }
758 return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
759 }
760
761 private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
762 List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
763 method: for (ExecutableElement method : methods) {
764 if (!method.getSimpleName().toString().equals(name)) {
765 continue;
766 }
767 if (method.getParameters().size() != params.length) {
768 continue;
769 }
770 for (int i = 0; i < params.length; i++) {
771 TypeMirror param1 = params[i];
772 TypeMirror param2 = method.getParameters().get(i).asType();
773 if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
774 if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
775 continue method;
776 }
777 }
778 }
779 return method;
780 }
781 return null;
782 }
783
784 private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
785 return getDeclaredMethod(element, name, params) != null;
786 }
787
788 public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
789 List<TypeElement> superElements = getSuperTypes(element);
790
791 for (TypeElement typeElement : superElements) {
792 if (isDeclaredMethod(typeElement, name, params)) {
793 return true;
794 }
795 }
796 return false;
797 }
798
799 private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
800 List<TypeElement> superElements = getSuperTypes(element);
801
802 for (TypeElement typeElement : superElements) {
803 ExecutableElement declared = getDeclaredMethod(typeElement, name, params);
804 if (declared != null) {
805 return declared;
806 }
807 }
808 return null;
809 }
810
811 public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) {
812 ExecutableElement declared = getDeclaredMethod(element, name, params);
813 if (declared != null) {
814 return declared;
815 }
816 return getDeclaredMethodInSuperType(element, name, params);
817 }
818
819 public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
820 if (type1 == null && type2 == null) {
821 return true;
822 } else if (type1 == null || type2 == null) {
823 return false;
824 }
825 String qualified1 = getQualifiedName(type1);
826 String qualified2 = getQualifiedName(type2);
827
828 if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
829 if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
830 return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
831 } else {
832 return false;
833 }
834 }
835 return qualified1.equals(qualified2);
836 }
837
838 public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
839 if (typeEquals(t1, t2)) {
840 return 0;
841 }
842 Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
843 if (t1SuperSet.contains(getQualifiedName(t2))) {
844 return -1;
845 }
846
847 Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
848 if (t2SuperSet.contains(getQualifiedName(t1))) {
849 return 1;
850 }
851 return 0;
852 }
853
854 public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
855 if (Utils.containsType(thrownTypes, exceptionType)) {
856 return true;
857 }
858
859 if (isRuntimeException(exceptionType)) {
860 return true;
861 }
862
863 // search for any super types
864 TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
865 List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
866 for (TypeElement typeElement : superTypes) {
867 if (Utils.containsType(thrownTypes, typeElement.asType())) {
868 return true;
869 }
870 }
871
872 return false;
873 }
874
875 public static Modifier getVisibility(Set<Modifier> modifier) {
876 for (Modifier mod : modifier) {
877 if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) {
878 return mod;
879 }
880 }
881 return null;
882 }
883
884 private static boolean isRuntimeException(TypeMirror type) {
885 Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
886 String typeName = getQualifiedName(type);
887 if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
888 throw new IllegalArgumentException("Given type does not extend Throwable.");
889 }
890 return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
891 }
892
893 private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
894 for (TypeMirror otherTypeMirror : collection) {
895 if (typeEquals(otherTypeMirror, type)) {
896 return true;
897 }
898 }
899 return false;
900 }
901
902 public static boolean isTopLevelClass(TypeMirror importType) {
903 TypeElement type = fromTypeMirror(importType);
904 if (type != null && type.getEnclosingElement() != null) {
905 return !type.getEnclosingElement().getKind().isClass();
906 }
907 return true;
908 }
909
910 public static boolean isObject(TypeMirror actualType) {
911 return getQualifiedName(actualType).equals("java.lang.Object");
912 }
913
914 public static boolean isFieldAccessible(Element element, VariableElement variable) {
915 TypeElement type = Utils.findNearestEnclosingType(element);
916 TypeElement varType = Utils.findNearestEnclosingType(variable);
917
918 while (type != null) {
919 if (typeEquals(type.asType(), varType.asType())) {
920 return true;
921 }
922 if (type.getSuperclass() != null) {
923 type = Utils.fromTypeMirror(type.getSuperclass());
924 } else {
925 type = null;
926 }
927 }
928 return false;
929 }
930 }