package org.robolectric.annotation.processing.validator;
import org.robolectric.annotation.processing.RobolectricModel;
import java.util.List;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.SimpleTypeVisitor6;
import javax.tools.Diagnostic.Kind;
/**
* Validator that checks usages of {@link org.robolectric.annotation.RealObject}.
*/
public class RealObjectValidator extends FoundOnImplementsValidator {
public RealObjectValidator(RobolectricModel model, ProcessingEnvironment env) {
super(model, env, "org.robolectric.annotation.RealObject");
}
public static String join(List<?> params) {
StringBuffer retval = new StringBuffer();
boolean comma = false;
for (Object p : params) {
if (comma) {
retval.append(',');
}
comma = true;
retval.append(p);
}
return retval.toString();
}
TypeVisitor<Void,VariableElement> typeVisitor = new SimpleTypeVisitor6<Void,VariableElement>() {
@Override
public Void visitDeclared(DeclaredType t, VariableElement v) {
List<? extends TypeMirror> typeParams = t.getTypeArguments();
List<? extends TypeParameterElement> parentTypeParams = parent.getTypeParameters();
if (!parentTypeParams.isEmpty() && typeParams.isEmpty()) {
messager.printMessage(Kind.ERROR, "@RealObject is missing type parameters", v);
} else {
String typeString = join(typeParams);
String parentString = join(parentTypeParams);
if (!typeString.equals(parentString)) {
messager.printMessage(Kind.ERROR, "Parameter type mismatch: expecting <" + parentString + ">, was <" + typeString + '>', v);
}
}
return null;
}
};
TypeElement parent;
@Override
public Void visitVariable(VariableElement elem, TypeElement parent) {
this.parent = parent;
TypeMirror impClass = model.getImplementedClass(imp);
if (impClass != null) {
TypeMirror elemType = elem.asType();
if (!types.isAssignable(impClass, elemType)) {
error("@RealObject with type <" + elemType + ">; expected <" + impClass + '>');
}
typeVisitor.visit(elemType, elem);
}
return null;
}
}