blob: fb387cacb210eec95314704dbf2509db1b5e91cc [file] [log] [blame]
/*******************************************************************************
* 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.visitors;
import java.util.EnumSet;
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.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.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.AbstractAnnotationValueVisitor6;
import javax.lang.model.util.ElementScanner6;
import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor;
/**
* Processor that tests a variety of Visitors
*/
@SupportedAnnotationTypes({"*"})
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class VisitorProc extends BaseProcessor
{
/**
* This visitor is invoked on the top-level types in resources/targets/model.
* We expect to see each of the visitX() methods get hit as a result.
*/
private static class ElementVisitorTester extends ElementScanner6<Void, Void> {
public enum Visited { TYPE, EXECUTABLE, VARIABLE, TYPEPARAM, PACKAGE, UNKNOWN }
private EnumSet<Visited> _visited = EnumSet.noneOf(Visited.class);
public boolean checkVisits() {
boolean asExpected = true;
asExpected &= _visited.contains(Visited.TYPE);
asExpected &= _visited.contains(Visited.EXECUTABLE);
asExpected &= _visited.contains(Visited.VARIABLE);
// TODO: Following two cases not yet implemented:
//asExpected &= _visited.contains(Visited.TYPEPARAM);
//asExpected &= _visited.contains(Visited.PACKAGE);
return asExpected;
}
/**
* Check that we can visit types.
* @return true if all tests passed
*/
@Override
public Void visitType(TypeElement e, Void p) {
_visited.add(Visited.TYPE);
// Scan the type's subtypes, fields, and methods
return super.visitType(e, p);
}
/**
* Check that we can visit methods.
*/
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
_visited.add(Visited.EXECUTABLE);
// Scan the method's parameters
return super.visitExecutable(e, p);
}
/**
* Check that we can visit variables.
*/
@Override
public Void visitVariable(VariableElement e, Void p) {
_visited.add(Visited.VARIABLE);
// Variables do not enclose any elements, so no need to call super.
return null;
}
/**
* Check that we can visit type parameters.
*/
@Override
public Void visitTypeParameter(TypeParameterElement e, Void p) {
_visited.add(Visited.TYPEPARAM);
// Type parameters do not enclose any elements, so no need to call super.
return null;
}
/**
* Check that we can visit packages.
*/
@Override
public Void visitPackage(PackageElement e, Void p) {
_visited.add(Visited.PACKAGE);
// We don't want to scan the package's types here, so don't call super.
return null;
}
/**
* This should not actually be encountered.
*/
@Override
public Void visitUnknown(Element e, Void p) {
_visited.add(Visited.UNKNOWN);
return null;
}
}
/*
* The specific values checked by this visitor correspond to values in targets.model.pc.TypedAnnos.java
*/
private static class AnnotationVisitorTester extends AbstractAnnotationValueVisitor6<Void, Void> {
public enum Visited { ANNOTATION, ARRAY, BOOLEAN, BYTE, CHAR, DOUBLE, ENUMCONSTANT, FLOAT, INT, LONG, SHORT, STRING, TYPE }
private EnumSet<Visited> _visited = EnumSet.noneOf(Visited.class);
public boolean checkVisits() {
boolean asExpected = true;
asExpected &= _visited.contains(Visited.ANNOTATION);
asExpected &= _visited.contains(Visited.ARRAY);
asExpected &= _visited.contains(Visited.BOOLEAN);
asExpected &= _visited.contains(Visited.BYTE);
asExpected &= _visited.contains(Visited.CHAR);
asExpected &= _visited.contains(Visited.DOUBLE);
asExpected &= _visited.contains(Visited.ENUMCONSTANT);
asExpected &= _visited.contains(Visited.FLOAT);
asExpected &= _visited.contains(Visited.INT);
asExpected &= _visited.contains(Visited.LONG);
asExpected &= _visited.contains(Visited.SHORT);
asExpected &= _visited.contains(Visited.STRING);
asExpected &= _visited.contains(Visited.TYPE);
return asExpected;
}
@Override
public Void visitAnnotation(AnnotationMirror a, Void p)
{
if (a != null && a.getElementValues() != null) {
_visited.add(Visited.ANNOTATION);
}
// we could scan the values of the nested annotation here, but that doesn't help our test case
return null;
}
@Override
public Void visitArray(List<? extends AnnotationValue> vals, Void p)
{
if ( null != vals && vals.size() == 2 ) {
if ( vals.iterator().next().getValue() instanceof TypeMirror) {
_visited.add(Visited.ARRAY);
}
}
// we could scan the array values here, but that doesn't help our test case
return null;
}
@Override
public Void visitBoolean(boolean b, Void p)
{
if (b) {
_visited.add(Visited.BOOLEAN);
}
return null;
}
@Override
public Void visitByte(byte b, Void p)
{
if (b == 3) {
_visited.add(Visited.BYTE);
}
return null;
}
@Override
public Void visitChar(char c, Void p)
{
if (c == 'c') {
_visited.add(Visited.CHAR);
}
return null;
}
@Override
public Void visitDouble(double d, Void p)
{
if (d == 6.3) {
_visited.add(Visited.DOUBLE);
}
return null;
}
@Override
public Void visitEnumConstant(VariableElement c, Void p)
{
if (c.getKind() == ElementKind.ENUM_CONSTANT) {
if ("A".equals(c.getSimpleName().toString())) {
_visited.add(Visited.ENUMCONSTANT);
}
}
return null;
}
@Override
public Void visitFloat(float f, Void p)
{
if (f == 26.7F) {
_visited.add(Visited.FLOAT);
}
return null;
}
@Override
public Void visitInt(int i, Void p)
{
if (i == 19) {
_visited.add(Visited.INT);
}
return null;
}
@Override
public Void visitLong(long i, Void p)
{
if (i == 300L) {
_visited.add(Visited.LONG);
}
return null;
}
@Override
public Void visitShort(short s, Void p)
{
if (s == 289) {
_visited.add(Visited.SHORT);
}
return null;
}
@Override
public Void visitString(String s, Void p)
{
if ("foo".equals(s)) {
_visited.add(Visited.STRING);
}
return null;
}
@Override
public Void visitType(TypeMirror t, Void p)
{
if ("java.lang.Exception".equals(t.toString())) {
_visited.add(Visited.TYPE);
}
return null;
}
}
@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;
}
ElementVisitorTester elementVisitor = new ElementVisitorTester();
elementVisitor.scan(roundEnv.getRootElements(), null);
if (!elementVisitor.checkVisits()) {
reportError("Element visitor was not visited as expected");
return false;
}
AnnotationVisitorTester annoValVisitor = new AnnotationVisitorTester();
TypeElement typedAnnosDecl = _elementUtils.getTypeElement("org.eclipse.jdt.compiler.apt.tests.annotations.TypedAnnos");
if (null == typedAnnosDecl) {
reportError("Couldn't find targets.model.pc.AnnotatedWithManyTypes");
return false;
}
for (TypeElement anno : annotations) {
if (typedAnnosDecl.equals(anno.getEnclosingElement())) {
for (Element elem : roundEnv.getElementsAnnotatedWith(anno)) {
for (AnnotationMirror annoMirror : elem.getAnnotationMirrors()) {
if (anno.equals(annoMirror.getAnnotationType().asElement())) {
Map<? extends ExecutableElement, ? extends AnnotationValue> values = annoMirror.getElementValues();
for (AnnotationValue val : values.values()) {
val.accept(annoValVisitor, null);
}
}
}
}
}
}
if (!annoValVisitor.checkVisits()) {
reportError("Annotation value visitor was not visited as expected");
return false;
}
reportSuccess();
return false;
}
}