| /******************************************************************************* |
| * 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.generics; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.annotation.processing.ProcessingEnvironment; |
| 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.ElementKind; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.element.TypeParameterElement; |
| import javax.lang.model.type.DeclaredType; |
| import javax.lang.model.type.TypeMirror; |
| import javax.lang.model.util.ElementFilter; |
| |
| import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor; |
| |
| /** |
| * Processor that tests our handling of parameterized types |
| * by exploring the parameterized types in resources/targets. |
| */ |
| @SupportedAnnotationTypes({"*"}) |
| @SupportedSourceVersion(SourceVersion.RELEASE_6) |
| public class GenericsProc extends BaseProcessor |
| { |
| // Initialized in collectElements() |
| private TypeElement _elementA; |
| private TypeElement _elementAC; |
| private TypeElement _elementObject; |
| private TypeElement _elementString; |
| private TypeElement _elementIterator; |
| |
| @Override |
| public synchronized void init(ProcessingEnvironment processingEnv) |
| { |
| super.init(processingEnv); |
| } |
| |
| @Override |
| public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) |
| { |
| if (roundEnv.processingOver()) { |
| 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 (!examineACNames()) { |
| return false; |
| } |
| if (!examineACTypeParams()) { |
| return false; |
| } |
| if (!examineATypeParams()) { |
| return false; |
| } |
| if (!examineFTypeParams()) { |
| return false; |
| } |
| |
| reportSuccess(); |
| return false; |
| } |
| |
| /** |
| * Collect some elements that will be reused in various tests |
| * @return true if all tests passed |
| */ |
| private boolean collectElements() { |
| _elementAC = _elementUtils.getTypeElement("targets.model.pb.AC"); |
| if (_elementAC == null) { |
| reportError("element AC was not found"); |
| return false; |
| } |
| if (_elementAC.getKind() != ElementKind.CLASS) { |
| reportError("AC claims to not be a class"); |
| return false; |
| } |
| _elementA = _elementUtils.getTypeElement("targets.model.pa.A"); |
| if (_elementA == null || _elementA.getKind() != ElementKind.CLASS) { |
| reportError("element A was not found or was not a class"); |
| return false; |
| } |
| _elementObject = _elementUtils.getTypeElement("java.lang.Object"); |
| _elementString = _elementUtils.getTypeElement("java.lang.String"); |
| _elementIterator = _elementUtils.getTypeElement("java.util.Iterator"); |
| return true; |
| } |
| |
| /** |
| * Examine the qualified and simple names of element AC and subelements |
| * @return true if all tests passed |
| */ |
| private boolean examineACNames() |
| { |
| String qnameAC = _elementAC.getQualifiedName().toString(); |
| if (!"targets.model.pb.AC".equals(qnameAC)) { |
| reportError("AC's qualified name is unexpected: " + qnameAC); |
| return false; |
| } |
| String snameAC = _elementAC.getSimpleName().toString(); |
| if (!"AC".equals(snameAC)) { |
| reportError("AC's simple name is unexpected: " + snameAC); |
| return false; |
| } |
| List<TypeElement> childElements = ElementFilter.typesIn(_elementAC.getEnclosedElements()); |
| if (childElements == null || childElements.size() != 1) { |
| reportError("AC should contain one child type"); |
| return false; |
| } |
| TypeElement elementACInner = childElements.iterator().next(); |
| String qnameInner = elementACInner.getQualifiedName().toString(); |
| if (!"targets.model.pb.AC.ACInner".equals(qnameInner)) { |
| reportError("AC.ACInner's qualified name is unexpected: " + qnameInner); |
| return false; |
| } |
| String snameInner = elementACInner.getSimpleName().toString(); |
| if (!"ACInner".equals(snameInner)) { |
| reportError("AC.ACInner's simple name is unexpected: " + snameInner); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the type parameters of element AC |
| * @return true if all tests passed |
| */ |
| private boolean examineACTypeParams() |
| { |
| List<? extends TypeParameterElement> params = _elementAC.getTypeParameters(); |
| if (null == params || params.size() != 2) { |
| reportError("element AC does not report 2 type parameters"); |
| return false; |
| } |
| Iterator<? extends TypeParameterElement> iter = params.iterator(); |
| TypeParameterElement t1 = iter.next(); |
| TypeParameterElement t2 = iter.next(); |
| if (!"T1".equals(t1.getSimpleName().toString()) || |
| !"T2".equals(t2.getSimpleName().toString())) { |
| reportError("Type parameters of element AC are not named T1 and T2"); |
| return false; |
| } |
| if (t1.getKind() != ElementKind.TYPE_PARAMETER) { |
| reportError("Type parameter T1 of element AC claims not to be ElementKind.TYPE_PARAMTER"); |
| return false; |
| } |
| if (!_elementAC.equals(t2.getGenericElement())) { |
| reportError("Type parameter T2 of element AC does not return AC from getGenericElement()"); |
| return false; |
| } |
| List<? extends TypeMirror> boundsT1 = t1.getBounds(); |
| if (null == boundsT1 || boundsT1.size() != 2) { |
| reportError("Type parameter T1 of element AC has wrong number of bounds"); |
| return false; |
| } |
| TypeMirror boundT1_0 = boundsT1.get(0); |
| if (!(boundT1_0 instanceof DeclaredType) || !_elementString.equals(((DeclaredType)boundT1_0).asElement())) { |
| reportError("Bound[0] of type parameter T1 of element AC is not String"); |
| return false; |
| } |
| TypeMirror boundT1_1 = boundsT1.get(1); |
| if (!(boundT1_1 instanceof DeclaredType) || !_elementIterator.equals(((DeclaredType)boundT1_1).asElement())) { |
| reportError("Bound[1] of type parameter T1 of element AC is not Iterator"); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the type parameters of element A |
| * @return true if all tests passed |
| */ |
| private boolean examineATypeParams() |
| { |
| List<? extends TypeParameterElement> params = _elementA.getTypeParameters(); |
| if (null == params || !params.isEmpty()) { |
| reportError("element A reports an unexpected number of type parameters: " + params); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Examine the type parameters of element F |
| * @return true if all tests passed |
| */ |
| private boolean examineFTypeParams() |
| { |
| TypeElement elementF = _elementUtils.getTypeElement("targets.model.pc.F"); |
| if (null == elementF || elementF.getKind() != ElementKind.CLASS) { |
| reportError("examineFTypeParams: couldn't load element F"); |
| return false; |
| } |
| List<? extends TypeParameterElement> params = elementF.getTypeParameters(); |
| if (null == params || params.size() != 1) { |
| reportError("examineFTypeParams: F reports an unexpected number of type parameters: " + params); |
| return false; |
| } |
| TypeParameterElement param = params.iterator().next(); |
| List<? extends TypeMirror> bounds = param.getBounds(); |
| if (null == bounds || bounds.size() != 1) { |
| reportError("examineFTypeParams: F's type parameter has an unexpected number of bounds: " + bounds); |
| return false; |
| } |
| TypeMirror elementType = _elementObject.asType(); |
| if (!elementType.equals(bounds.iterator().next())) { |
| reportError("examineFTypeParams: F's type bounds should only contain Object"); |
| return false; |
| } |
| return true; |
| } |
| } |