| /******************************************************************************* |
| * Copyright (c) 2007 BEA Systems, Inc. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * wharley@bea.com - initial API and implementation |
| * |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.compiler.apt.tests.processors.elements; |
| |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Map.Entry; |
| |
| import javax.annotation.processing.RoundEnvironment; |
| import javax.annotation.processing.SupportedAnnotationTypes; |
| import javax.annotation.processing.SupportedSourceVersion; |
| import javax.lang.model.SourceVersion; |
| import javax.lang.model.element.AnnotationMirror; |
| import javax.lang.model.element.AnnotationValue; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ElementKind; |
| import javax.lang.model.element.ExecutableElement; |
| import javax.lang.model.element.Modifier; |
| import javax.lang.model.element.Name; |
| import javax.lang.model.element.NestingKind; |
| import javax.lang.model.element.PackageElement; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.element.VariableElement; |
| import javax.lang.model.type.DeclaredType; |
| import javax.lang.model.type.MirroredTypeException; |
| import javax.lang.model.type.MirroredTypesException; |
| import javax.lang.model.type.TypeKind; |
| import javax.lang.model.type.TypeMirror; |
| import javax.lang.model.util.ElementFilter; |
| |
| import org.eclipse.jdt.compiler.apt.tests.annotations.TypedAnnos; |
| import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor; |
| |
| /** |
| * A processor that explores the "model" target hierarchy and complains if it does |
| * not find what it expects. To enable this processor, add |
| * -Aorg.eclipse.jdt.compiler.apt.tests.processors.elements.ElementProc to the command line. |
| * @since 3.3 |
| */ |
| @SupportedAnnotationTypes("*") |
| @SupportedSourceVersion(SourceVersion.RELEASE_6) |
| public class ElementProc extends BaseProcessor { |
| |
| // The set of elements we expect getRootElements to return in package pa |
| private static final String[] ROOT_ELEMENT_NAMES = new String[] { |
| "targets.model.pa.AnnoZ", "targets.model.pa.A", "targets.model.pa.IA", "targets.model.pa.ExceptionA"}; |
| |
| // Initialized in collectElements() |
| private TypeElement _elementIA; |
| private TypeElement _elementAB; |
| private TypeElement _elementA; |
| private TypeElement _elementD; |
| private TypeElement _elementDChild; |
| private TypeElement _elementAnnoZ; |
| private TypeElement _elementString; |
| |
| // Initialized in examineDMethods() |
| private ExecutableElement _methodDvoid; |
| private TypeElement _elementDEnum; |
| |
| // Always return false from this processor, because it supports "*". |
| // The return value does not signify success or failure! |
| @Override |
| public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| if (roundEnv.processingOver()) { |
| // We're not interested in the postprocessing round. |
| return false; |
| } |
| Map<String, String> options = processingEnv.getOptions(); |
| if (!options.containsKey(this.getClass().getName())) { |
| // Disable this processor unless we are intentionally performing the test. |
| return false; |
| } |
| |
| if (!collectElements()) { |
| return false; |
| } |
| |
| if (!examineRoundEnv(roundEnv)) { |
| return false; |
| } |
| |
| if (!examineABInterfaces()) { |
| return false; |
| } |
| |
| if (!examineABModifiers()) { |
| return false; |
| } |
| |
| if (!examineDHierarchy()) { |
| return false; |
| } |
| |
| if (!examineAMethodsAndFields()) { |
| return false; |
| } |
| |
| if (!examineAMethodThrowables()) { |
| return false; |
| } |
| |
| if (!examineDMethods()) { |
| return false; |
| } |
| |
| if (!examineDEnum()) { |
| return false; |
| } |
| |
| if (!examinePBPackage()) { |
| return false; |
| } |
| |
| if (!examineDAnnotations()) { |
| return false; |
| } |
| |
| if (!examineGetAnnotation()) { |
| return false; |
| } |
| |
| reportSuccess(); |
| return false; |
| } |
| |
| /** |
| * Collect some elements that will be reused in various tests |
| * @return true if all tests passed |
| */ |
| private boolean collectElements() { |
| _elementIA = _elementUtils.getTypeElement("targets.model.pa.IA"); |
| if (_elementIA == null) { |
| reportError("element IA was not found"); |
| return false; |
| } |
| if (_elementIA.getKind() != ElementKind.INTERFACE) { |
| reportError("IA claims to not be an interface"); |
| return false; |
| } |
| if (_elementIA.getNestingKind() != NestingKind.TOP_LEVEL) { |
| reportError("NestingKind of element IA is not TOP_LEVEL"); |
| return false; |
| } |
| |
| _elementA = _elementUtils.getTypeElement("targets.model.pa.A"); |
| if (_elementA == null) { |
| reportError("element A was not found"); |
| return false; |
| } |
| if (_elementA.getKind() != ElementKind.CLASS) { |
| reportError("A claims to not be a class"); |
| return false; |
| } |
| |
| _elementAnnoZ = _elementUtils.getTypeElement("targets.model.pa.AnnoZ"); |
| if (_elementAnnoZ == null) { |
| reportError("element AnnoZ was not found"); |
| return false; |
| } |
| if (_elementAnnoZ.getKind() != ElementKind.ANNOTATION_TYPE) { |
| reportError("AnnoZ claims to not be an annotation type"); |
| return false; |
| } |
| |
| _elementAB = _elementUtils.getTypeElement("targets.model.pb.AB"); |
| if (_elementAB == null) { |
| reportError("element AB was not found"); |
| return false; |
| } |
| if (_elementAB.getKind() != ElementKind.CLASS) { |
| reportError("AB claims to not be a class"); |
| return false; |
| } |
| |
| _elementD = _elementUtils.getTypeElement("targets.model.pb.D"); |
| if (_elementD == null) { |
| reportError("element D was not found"); |
| return false; |
| } |
| if (_elementD.getKind() != ElementKind.CLASS) { |
| reportError("D claims to not be a class"); |
| return false; |
| } |
| |
| _elementDChild = _elementUtils.getTypeElement("targets.model.pb.DChild"); |
| if (_elementDChild == null) { |
| reportError("secondary element DChild was not found"); |
| return false; |
| } |
| if (_elementDChild.getKind() != ElementKind.CLASS) { |
| reportError("DChild claims to not be a class"); |
| return false; |
| } |
| _elementString = _elementUtils.getTypeElement("java.lang.String"); |
| return true; |
| } |
| |
| /** |
| * Check the methods on RoundEnvironment method |
| * @return true if all tests passed |
| */ |
| private boolean examineRoundEnv(RoundEnvironment roundEnv) { |
| // Verify that we get the root elements we expect |
| Set<String> expectedRootElementNames = new HashSet<String>(ROOT_ELEMENT_NAMES.length); |
| for (String name : ROOT_ELEMENT_NAMES) { |
| expectedRootElementNames.add(name); |
| } |
| Set<? extends Element> actualRootElements = roundEnv.getRootElements(); |
| if (null == actualRootElements) { |
| reportError("getRootElements() returned null"); |
| return false; |
| } |
| for (Element e : actualRootElements) { |
| if (e instanceof TypeElement) { |
| String name = ((TypeElement)e).getQualifiedName().toString(); |
| if (name.startsWith("targets.model.pa.") && !expectedRootElementNames.remove(name)) { |
| reportError("Missing root element " + name); |
| return false; |
| } |
| } |
| } |
| if (!expectedRootElementNames.isEmpty()) { |
| reportError("Found extra root elements including " + expectedRootElementNames.iterator().next()); |
| return false; |
| } |
| |
| // Verify that we get the annotations we expect |
| Set<? extends Element> annotatedWithAnnoZ = roundEnv.getElementsAnnotatedWith(_elementAnnoZ); |
| if (null == annotatedWithAnnoZ || !annotatedWithAnnoZ.contains(_elementD)) { |
| reportError("Elements annotated with AnnoZ does not include D"); |
| return false; |
| } |
| |
| // targets.model.pc.Deprecation contains @Deprecated annotations |
| Set<? extends Element> annotatedWithDeprecated = roundEnv.getElementsAnnotatedWith(Deprecated.class); |
| if (null == annotatedWithDeprecated) { |
| reportError("getElementsAnnotatedWith(@Deprecated) returned null"); |
| return false; |
| } |
| boolean foundDeprecation = false; |
| for (TypeElement deprecatedElement : ElementFilter.typesIn(annotatedWithDeprecated)) { |
| if ("targets.model.pc.Deprecation".equals(deprecatedElement.getQualifiedName().toString())) { |
| foundDeprecation = true; |
| break; |
| } |
| } |
| if (!foundDeprecation) { |
| reportError("getElementsAnnotatedWith(@Deprecation) did not find targets.model.pc.Deprecation"); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Examine the interfaces that AB implements |
| * @return true if all tests passed |
| */ |
| private boolean examineABInterfaces() { |
| List<? extends TypeMirror> interfacesAB = _elementAB.getInterfaces(); |
| if (null == interfacesAB) { |
| reportError("AB.getInterfaces() returned null"); |
| return false; |
| } |
| boolean foundIAinterface = false; |
| for (TypeMirror type : interfacesAB) { |
| Element decl = _typeUtils.asElement(type); |
| if (null == decl) { |
| reportError("One of AB's interfaces, " + type.toString() + ", produced null from Types.asElement()"); |
| return false; |
| } |
| if (_elementIA.equals(decl)) { |
| foundIAinterface = true; |
| break; |
| } |
| } |
| if (!foundIAinterface) { |
| reportError("AB does not have IA as an interface"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the modifiers of AB's contents |
| * @return true if all tests passed |
| */ |
| private boolean examineABModifiers() { |
| Map<String, Element> contents = new HashMap<String, Element>(); |
| for (Element enclosed : _elementAB.getEnclosedElements()) { |
| contents.put(enclosed.getSimpleName().toString(), enclosed); |
| } |
| Element publicMethod = contents.get("methodIAString"); |
| Element protectedField = contents.get("_fieldListIA"); |
| Element privateClass = contents.get("E"); |
| if (null == publicMethod || null == protectedField || null == privateClass) { |
| reportError("AB does not contain the expected enclosed elements"); |
| return false; |
| } |
| Set<Modifier> modifiers = publicMethod.getModifiers(); |
| if (!modifiers.contains(Modifier.PUBLIC) || modifiers.size() > 1) { |
| reportError("AB.methodIAString() has unexpected modifiers"); |
| return false; |
| } |
| modifiers = protectedField.getModifiers(); |
| if (!modifiers.contains(Modifier.PROTECTED) || modifiers.size() > 1) { |
| reportError("AB._fieldListIA() has unexpected modifiers"); |
| return false; |
| } |
| modifiers = privateClass.getModifiers(); |
| if (!modifiers.contains(Modifier.PRIVATE) || modifiers.size() > 1) { |
| reportError("AB.E() has unexpected modifiers"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the hierarchy of element D |
| * @return true if all tests passed |
| */ |
| private boolean examineDHierarchy() { |
| TypeMirror supertypeD = _elementD.getSuperclass(); |
| if (null == supertypeD) { |
| reportError("element D's supertype was null"); |
| return false; |
| } |
| Element superclassD = _typeUtils.asElement(supertypeD); |
| if (!_elementAB.equals(superclassD)) { |
| reportError("element D's superclass did not equal element AB"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Examine the methods and fields of element A |
| * @return true if all tests passed |
| */ |
| private boolean examineAMethodsAndFields() { |
| // METHODS |
| List<? extends Element> enclosedA = _elementA.getEnclosedElements(); |
| if (enclosedA == null) { |
| reportError("elementA.getEnclosedElements() returned null"); |
| return false; |
| } |
| List<ExecutableElement> methodsA = ElementFilter.methodsIn(enclosedA); |
| ExecutableElement methodIAString = null; |
| for (ExecutableElement method : methodsA) { |
| Name methodName = method.getSimpleName(); |
| if ("methodIAString".equals(methodName.toString())) { |
| methodIAString = method; |
| } |
| } |
| if (null == methodIAString) { |
| reportError("element A did not contain methodIAString()"); |
| return false; |
| } |
| if (methodIAString.getKind() != ElementKind.METHOD) { |
| reportError("A.methodIAString is not an ElementKind.METHOD"); |
| return false; |
| } |
| Element enclosingMethodIAStringInA = methodIAString.getEnclosingElement(); |
| if (null == enclosingMethodIAStringInA || !_elementA.equals(enclosingMethodIAStringInA)) { |
| reportError("Element enclosing A.methodIAString() is not A"); |
| return false; |
| } |
| |
| // RETURN AND PARAMS |
| TypeMirror returnType = methodIAString.getReturnType(); |
| if (!(returnType instanceof DeclaredType) || returnType.getKind() != TypeKind.DECLARED) { |
| reportError("Return type of A.methodIAString() is not a declared type"); |
| return false; |
| } |
| if (!_elementString.equals(((DeclaredType)returnType).asElement())) { |
| reportError("Return type of A.methodIAString() does not equal java.lang.String"); |
| return false; |
| } |
| List<? extends VariableElement> paramsMethodIAString = methodIAString.getParameters(); |
| VariableElement int1 = null; |
| for (VariableElement param : paramsMethodIAString) { |
| int1 = param; |
| } |
| TypeMirror int1Type = int1.asType(); |
| if (null == int1Type || int1Type.getKind() != TypeKind.INT) { |
| reportError("The first parameter of A.methodIAString() is not of int type"); |
| return false; |
| } |
| if (!("int1".equals(int1.getSimpleName().toString()))) { |
| reportError("The first parameter of A.methodIAString() is not named int1"); |
| return false; |
| } |
| |
| // FIELDS |
| List<VariableElement> fieldsA = ElementFilter.fieldsIn(enclosedA); |
| VariableElement fieldAint = null; |
| for (VariableElement field : fieldsA) { |
| Name fieldName = field.getSimpleName(); |
| if ("_fieldAint".equals(fieldName.toString())) { |
| fieldAint = field; |
| } |
| } |
| if (null == fieldAint) { |
| reportError("element A did not contain _fieldAint"); |
| return false; |
| } |
| if (fieldAint.getKind() != ElementKind.FIELD) { |
| reportError("A._fieldAint is not an ElementKind.FIELD"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the methods of A which have throws clauses |
| * @return true if all tests passed |
| */ |
| private boolean examineAMethodThrowables() { |
| List<ExecutableElement> methodsA = ElementFilter.methodsIn(_elementA.getEnclosedElements()); |
| ExecutableElement methodIAString = null; // no throws clauses |
| ExecutableElement methodThrows1 = null; |
| ExecutableElement methodThrows2 = null; |
| for (ExecutableElement method : methodsA) { |
| String methodName = method.getSimpleName().toString(); |
| if ("methodIAString".equals(methodName)) { |
| methodIAString = method; |
| } |
| if ("methodThrows1".equals(methodName)) { |
| methodThrows1 = method; |
| } |
| else if ("methodThrows2".equals(methodName)) { |
| methodThrows2 = method; |
| } |
| } |
| if (null == methodIAString || null == methodThrows1 || null == methodThrows2) { |
| reportError("element A did not contain methodIAString(), methodThrows1(), or methodThrows2()"); |
| return false; |
| } |
| List<? extends TypeMirror> thrownTypes0 = methodIAString.getThrownTypes(); |
| List<? extends TypeMirror> thrownTypes1 = methodThrows1.getThrownTypes(); |
| List<? extends TypeMirror> thrownTypes2 = methodThrows2.getThrownTypes(); |
| if (null == thrownTypes0 || null == thrownTypes1 || null == thrownTypes2) { |
| reportError("getThrownTypes() on A.methodIAString(), methodThrows1(), or methodThrows2() returned null"); |
| return false; |
| } |
| if (!thrownTypes0.isEmpty()) { |
| reportError("A.methodIAString unexpectedly reports having a throws clause"); |
| return false; |
| } |
| boolean foundEA = false; |
| for (TypeMirror type : thrownTypes1) { |
| Element element = _typeUtils.asElement(type); |
| if ("ExceptionA".equals(element.getSimpleName().toString())) { |
| foundEA = true; |
| } |
| } |
| if (thrownTypes1.size() != 1 || !foundEA) { |
| reportError("A.methodThrows1() reported unexpected throwables"); |
| return false; |
| } |
| foundEA = false; |
| boolean foundUOE = false; |
| for (TypeMirror type : thrownTypes2) { |
| Element element = _typeUtils.asElement(type); |
| if ("UnsupportedOperationException".equals(element.getSimpleName().toString())) { |
| foundUOE = true; |
| } |
| else if ("ExceptionA".equals(element.getSimpleName().toString())) { |
| foundEA = true; |
| } |
| } |
| if (thrownTypes2.size() != 2 || !foundEA || !foundUOE) { |
| reportError("A.methodThrows2() reported unexpected throwables"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the methods of D (which are interesting because of an enum param and void return) |
| * @return true if all tests passed |
| */ |
| private boolean examineDMethods() { |
| List<ExecutableElement> methodsD = ElementFilter.methodsIn(_elementD.getEnclosedElements()); |
| _methodDvoid = null; |
| for (ExecutableElement method : methodsD) { |
| Name methodName = method.getSimpleName(); |
| if ("methodDvoid".equals(methodName.toString())) { |
| _methodDvoid = method; |
| } |
| } |
| if (null == _methodDvoid) { |
| reportError("element D did not contain methodDvoid()"); |
| return false; |
| } |
| TypeMirror returnType = _methodDvoid.getReturnType(); |
| if (returnType.getKind() != TypeKind.VOID) { |
| reportError("D.methodDvoid() return type was not void"); |
| return false; |
| } |
| List<? extends VariableElement> params = _methodDvoid.getParameters(); |
| if (null == params || params.isEmpty()) { |
| reportError("D.methodDvoid() reports no parameters"); |
| return false; |
| } |
| VariableElement param1 = params.iterator().next(); |
| TypeMirror param1Type = param1.asType(); |
| if (null == param1Type || param1Type.getKind() != TypeKind.DECLARED) { |
| reportError("First parameter of D.methodDvoid() is not a declared type"); |
| return false; |
| } |
| if (!"targets.model.pb.D.DEnum".equals(param1Type.toString())) { |
| reportError("Type of first parameter of D.methodDvoid() is not DEnum"); |
| return false; |
| } |
| Element param1TypeElement = ((DeclaredType)param1Type).asElement(); |
| if (null == param1TypeElement || param1TypeElement.getKind() != ElementKind.ENUM || !(param1TypeElement instanceof TypeElement)) { |
| reportError("Type of first parameter of D.methodDvoid() is not an enum"); |
| return false; |
| } |
| _elementDEnum = (TypeElement)param1TypeElement; |
| return true; |
| } |
| |
| /** |
| * Check the DEnum type declared inside element D |
| * @return true if all tests passed |
| */ |
| private boolean examineDEnum() |
| { |
| if (_elementDEnum.getNestingKind() != NestingKind.MEMBER) { |
| reportError("Type DEnum is not NestingKind.MEMBER"); |
| return false; |
| } |
| Map<String, VariableElement> values = new LinkedHashMap<String, VariableElement>(); |
| for (VariableElement enclosedElement : ElementFilter.fieldsIn(_elementDEnum.getEnclosedElements())) { |
| values.put(enclosedElement.getSimpleName().toString(), enclosedElement); |
| } |
| if (values.size() != 3) { |
| reportError("DEnum should have three values, but instead has: " + values.size()); |
| return false; |
| } |
| Iterator<String> iter = values.keySet().iterator(); |
| if (!"DEnum1".equals(iter.next()) || !"DEnum2".equals(iter.next()) || !"DEnum3".equals(iter.next())) { |
| reportError("DEnum does not have the expected values in the expected order"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Check the PackageDeclaration of pb |
| * @return true if all tests passed |
| */ |
| private boolean examinePBPackage() { |
| Element packagePB = _elementAB.getEnclosingElement(); |
| if (!(packagePB instanceof PackageElement) || packagePB.getKind() != ElementKind.PACKAGE) { |
| reportError("element AB is not enclosed by a package"); |
| return false; |
| } |
| if (!("targets.model.pb".equals(((PackageElement)packagePB).getQualifiedName().toString()))) { |
| reportError("The name of package pb is not targets.model.pb"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Read the annotations on element D (class and method) |
| * @return true if all tests passed |
| */ |
| private boolean examineDAnnotations() { |
| // Examine annotation on class declaration |
| List<? extends AnnotationMirror> annotsD = _elementD.getAnnotationMirrors(); |
| if (null == annotsD || annotsD.isEmpty()) { |
| reportError("element D reports no annotations"); |
| return false; |
| } |
| for (AnnotationMirror annotD : annotsD) { |
| DeclaredType annotDType = annotD.getAnnotationType(); |
| if (null == annotDType) { |
| reportError("annotation mirror of AnnoZ on element D reports null type"); |
| return false; |
| } |
| Element annotDElem = annotDType.asElement(); |
| if (!(annotDElem instanceof TypeElement) || |
| !"targets.model.pa.AnnoZ".equals(((TypeElement)annotDElem).getQualifiedName().toString())) { |
| reportError("annotation on element D is not TypeElement targets.model.pa.AnnoZ"); |
| return false; |
| } |
| Map<? extends ExecutableElement, ? extends AnnotationValue> values = annotD.getElementValues(); |
| if (null == values || values.isEmpty()) { |
| reportError("@AnnoZ on element D reports no values"); |
| return false; |
| } |
| boolean foundStringMethod = false; |
| for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : values.entrySet()) { |
| String methodName = entry.getKey().getSimpleName().toString(); |
| if ("annoZString".equals(methodName)) { |
| foundStringMethod = true; |
| Object value = entry.getValue().getValue(); |
| if (!"annoZOnD".equals(value)) { |
| reportError("Value of annoZString param on element D is not \"annoZOnD\""); |
| return false; |
| } |
| } |
| } |
| if (!foundStringMethod) { |
| reportError("Failed to find method annoZString on @AnnoZ on element D"); |
| return false; |
| } |
| |
| // Check Elements.getElementValuesWithDefaults() |
| Map<? extends ExecutableElement, ? extends AnnotationValue> defaults = |
| _elementUtils.getElementValuesWithDefaults(annotD); |
| if (null == defaults) { |
| reportError("Element.getElementValuesWithDefaults(annotD) returned null"); |
| return false; |
| } |
| for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : defaults.entrySet()) { |
| String methodName = entry.getKey().getSimpleName().toString(); |
| if ("annoZString".equals(methodName)) { |
| foundStringMethod = true; |
| Object value = entry.getValue().getValue(); |
| if (!"annoZOnD".equals(value)) { |
| reportError("Explicit value of AnnoZ.annoZString is not \"annoZOnD\""); |
| return false; |
| } |
| } |
| else if ("annoZint".equals(methodName)) { |
| foundStringMethod = true; |
| Object value = entry.getValue().getValue(); |
| if (null == value || !value.equals(17)) { |
| reportError("Default value of AnnoZ.annoZint() is not 17"); |
| return false; |
| } |
| } |
| } |
| } |
| |
| List<? extends AnnotationMirror> annotsMethodDvoid = _methodDvoid.getAnnotationMirrors(); |
| if (null == annotsMethodDvoid || annotsMethodDvoid.isEmpty()) { |
| reportError("method D.methodDvoid() reports no annotations"); |
| return false; |
| } |
| for (AnnotationMirror annotMethodDvoid : annotsMethodDvoid) { |
| DeclaredType annotDType = annotMethodDvoid.getAnnotationType(); |
| if (null == annotDType) { |
| reportError("annotation mirror of AnnoZ on D.methodDvoid() reports null type"); |
| return false; |
| } |
| Element annotDElem = annotDType.asElement(); |
| if (!(annotDElem instanceof TypeElement) || |
| !"targets.model.pa.AnnoZ".equals(((TypeElement)annotDElem).getQualifiedName().toString())) { |
| reportError("annotation on D.methodDvoid() is not TypeElement targets.model.pa.AnnoZ"); |
| return false; |
| } |
| Map<? extends ExecutableElement, ? extends AnnotationValue> values = annotMethodDvoid.getElementValues(); |
| if (null == values || values.isEmpty()) { |
| reportError("@AnnoZ on D.methodDvoid() reports no values"); |
| return false; |
| } |
| boolean foundIntMethod = false; |
| for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : values.entrySet()) { |
| String methodName = entry.getKey().getSimpleName().toString(); |
| if ("annoZint".equals(methodName)) { |
| foundIntMethod = true; |
| Object value = entry.getValue().getValue(); |
| if (!(value instanceof Integer) || (Integer)value != 31) { |
| reportError("Value of annoZint param on D.methodDvoid() is not 31"); |
| return false; |
| } |
| } |
| } |
| if (!foundIntMethod) { |
| reportError("Failed to find method annoZint on @AnnoZ on D.methodDvoid()"); |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Test the Element.getAnnotation() implementation |
| * @return true if all tests passed |
| */ |
| private boolean examineGetAnnotation() { |
| TypeElement annotatedElement = _elementUtils.getTypeElement("targets.model.pc.AnnotatedWithManyTypes.Annotated"); |
| if (null == annotatedElement || annotatedElement.getKind() != ElementKind.CLASS) { |
| reportError("examineGetAnnotation: couldn't get AnnotatedWithManyTypes.Annotated element"); |
| return false; |
| } |
| final String badValue = "examineGetAnnotation: unexpected value for "; |
| TypedAnnos.AnnoByte annoByte = annotatedElement.getAnnotation(TypedAnnos.AnnoByte.class); |
| if (null == annoByte || annoByte.value() != 3) { |
| reportError(badValue + "AnnoByte"); |
| return false; |
| } |
| TypedAnnos.AnnoBoolean annoBoolean = annotatedElement.getAnnotation(TypedAnnos.AnnoBoolean.class); |
| if (null == annoBoolean || !annoBoolean.value()) { |
| reportError(badValue + "AnnoBoolean"); |
| return false; |
| } |
| TypedAnnos.AnnoChar annoChar = annotatedElement.getAnnotation(TypedAnnos.AnnoChar.class); |
| if (null == annoChar || annoChar.value() != 'c') { |
| reportError(badValue + "AnnoChar"); |
| return false; |
| } |
| TypedAnnos.AnnoDouble annoDouble = annotatedElement.getAnnotation(TypedAnnos.AnnoDouble.class); |
| if (null == annoDouble || annoDouble.value() != 6.3) { |
| reportError(badValue + "AnnoDouble"); |
| return false; |
| } |
| TypedAnnos.AnnoFloat annoFloat = annotatedElement.getAnnotation(TypedAnnos.AnnoFloat.class); |
| if (null == annoFloat || annoFloat.value() != 26.7F) { |
| reportError(badValue + "AnnoFloat"); |
| return false; |
| } |
| TypedAnnos.AnnoInt annoInt = annotatedElement.getAnnotation(TypedAnnos.AnnoInt.class); |
| if (null == annoInt || annoInt.value() != 19) { |
| reportError(badValue + "AnnoInt"); |
| return false; |
| } |
| TypedAnnos.AnnoLong annoLong = annotatedElement.getAnnotation(TypedAnnos.AnnoLong.class); |
| if (null == annoLong || annoLong.value() != 300L) { |
| reportError(badValue + "AnnoLong"); |
| return false; |
| } |
| TypedAnnos.AnnoShort annoShort = annotatedElement.getAnnotation(TypedAnnos.AnnoShort.class); |
| if (null == annoShort || annoShort.value() != 289) { |
| reportError(badValue + "AnnoShort"); |
| return false; |
| } |
| TypedAnnos.AnnoString annoString = annotatedElement.getAnnotation(TypedAnnos.AnnoString.class); |
| if (null == annoString || !"foo".equals(annoString.value())) { |
| reportError(badValue + "AnnoString"); |
| return false; |
| } |
| TypedAnnos.AnnoEnumConst annoEnumConst = annotatedElement.getAnnotation(TypedAnnos.AnnoEnumConst.class); |
| if (null == annoEnumConst || annoEnumConst.value() != TypedAnnos.Enum.A) { |
| reportError(badValue + "AnnoEnumConst"); |
| return false; |
| } |
| TypedAnnos.AnnoType annoType = annotatedElement.getAnnotation(TypedAnnos.AnnoType.class); |
| if (null == annoType) { |
| reportError(badValue + "AnnoType"); |
| return false; |
| } |
| try { |
| Class<?> clazz = annoType.value(); |
| reportError("examineGetAnnotation: annoType.value() should have thrown a MirroredTypeException but instead returned " + clazz); |
| return false; |
| } |
| catch (MirroredTypeException mte) { |
| TypeMirror clazzMirror = mte.getTypeMirror(); |
| if (null == clazzMirror || clazzMirror.getKind() != TypeKind.DECLARED) { |
| reportError("examineGetAnnotation: annoType.value() returned an incorrect mirror: " + clazzMirror); |
| return false; |
| } |
| } |
| TypedAnnos.AnnoAnnoChar annoAnnoChar = annotatedElement.getAnnotation(TypedAnnos.AnnoAnnoChar.class); |
| if (null == annoAnnoChar || null == annoAnnoChar.value() || 'x' != annoAnnoChar.value().value()) { |
| reportError(badValue + "AnnoAnnoChar"); |
| return false; |
| } |
| TypedAnnos.AnnoArrayInt annoArrayInt = annotatedElement.getAnnotation(TypedAnnos.AnnoArrayInt.class); |
| if (null == annoArrayInt) { |
| reportError(badValue + "AnnoArrayInt"); |
| return false; |
| } |
| int[] arrayInt = annoArrayInt.value(); |
| if (arrayInt == null || arrayInt.length != 3 || arrayInt[1] != 8) { |
| reportError(badValue + "AnnoArrayInt contents"); |
| return false; |
| } |
| //TODO: AnnoArrayString |
| //TODO: AnnoArrayAnnoChar |
| //TODO: AnnoArrayEnumConst |
| TypedAnnos.AnnoArrayType annoArrayType = annotatedElement.getAnnotation(TypedAnnos.AnnoArrayType.class); |
| if (null == annoArrayType) { |
| reportError(badValue + "AnnoArrayType"); |
| return false; |
| } |
| try { |
| Class<?>[] contents = annoArrayType.value(); |
| reportError("examineGetAnnotation: annoArrayType.value() should have thrown a MirroredTypesException but instead returned " + contents); |
| return false; |
| } |
| catch (MirroredTypesException mte) { |
| List<? extends TypeMirror> clazzMirrors = mte.getTypeMirrors(); |
| if (null == clazzMirrors || clazzMirrors.size() != 2) { |
| reportError("examineGetAnnotation: annoArrayType.value() returned an incorrect mirror list"); |
| return false; |
| } |
| } |
| catch (MirroredTypeException mte) { |
| // ignore, because javac incorrectly throws this; see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6519115 |
| } |
| return true; |
| } |
| } |