package org.robolectric.annotation.processing.validator;
import org.robolectric.annotation.processing.RobolectricModel;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementVisitor;
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.util.AbstractElementVisitor6;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
/**
* Base class for validators.
*/
public abstract class Validator implements ElementVisitor<Void, Element> {
final protected RobolectricModel model;
final protected Elements elements;
final protected Types types;
final protected Messager messager;
final protected TypeElement annotationType;
// This is the easiest way to do it because visit() is final in AbstractEV6
final ElementVisitor<Void, Element> visitorAdapter = new AbstractElementVisitor6<Void, Element>() {
@Override
public Void visitPackage(PackageElement e, Element p) {
return Validator.this.visitPackage(e, p);
}
@Override
public Void visitType(TypeElement e, Element p) {
return Validator.this.visitType(e, p);
}
@Override
public Void visitVariable(VariableElement e, Element p) {
return Validator.this.visitVariable(e, p);
}
@Override
public Void visitExecutable(ExecutableElement e, Element p) {
return Validator.this.visitExecutable(e, p);
}
@Override
public Void visitTypeParameter(TypeParameterElement e, Element p) {
return Validator.this.visitTypeParameter(e, p);
}
};
protected Element currentElement;
protected AnnotationMirror currentAnnotation;
public Validator(RobolectricModel model, ProcessingEnvironment env, String annotationType) {
this.model = model;
elements = env.getElementUtils();
types = env.getTypeUtils();
messager = env.getMessager();
// FIXME: Need to test case where type lookup fails
this.annotationType = elements.getTypeElement(annotationType);
}
protected AnnotationMirror getCurrentAnnotation() {
if (currentAnnotation == null) {
currentAnnotation = model.getAnnotationMirror(currentElement, annotationType);
}
return currentAnnotation;
}
protected void message(Kind severity, String msg, AnnotationValue av) {
final AnnotationMirror am = getCurrentAnnotation();
messager.printMessage(severity, msg, currentElement, am, av);
}
protected void message(Kind severity, String msg) {
final AnnotationMirror am = getCurrentAnnotation();
messager.printMessage(severity, msg, currentElement, am);
}
protected void error(String msg) {
message(Kind.ERROR, msg);
}
protected void error(String msg, AnnotationValue av) {
message(Kind.ERROR, msg, av);
}
public void init(Element e, Element p) {
currentElement = e;
currentAnnotation = null;
}
public TypeElement getAnnotationType() {
return annotationType;
}
@Override
public Void visit(Element e, Element p) {
init(e, p);
return visitorAdapter.visit(e, p);
}
@Override
public Void visit(Element e) {
return visit(e, null);
}
@Override
public Void visitPackage(PackageElement e, Element p) {
return null;
}
@Override
public Void visitType(TypeElement e, Element p) {
return null;
}
@Override
public Void visitVariable(VariableElement e, Element p) {
return null;
}
@Override
public Void visitExecutable(ExecutableElement e, Element p) {
return null;
}
@Override
public Void visitTypeParameter(TypeParameterElement e, Element p) {
return null;
}
@Override
public Void visitUnknown(Element e, Element p) {
return null;
}
}