package autodagger.compiler; import com.google.auto.common.MoreElements; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; import javax.inject.Qualifier; 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.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import autodagger.AutoExpose; import processorworkflow.AbstractExtractor; import processorworkflow.Errors; import processorworkflow.ExtractorUtils; /** * Extracts @AutoInjector and @AutoExpose * * @author Lukasz Piliszczuk - lukasz.pili@gmail.com */ public class AdditionExtractor extends AbstractExtractor { /** * The addition element represented by @AutoInjector or @AutoExpose * It's either the element itself, or the element of an annotation if the @AutoXXX * is applied on the annotation */ private TypeElement additionElement; private final Class<? extends Annotation> additionAnnotation; private String providerMethodName; private AnnotationMirror qualifierAnnotationMirror; private List<TypeMirror> targetTypeMirrors; private List<TypeMirror> parameterizedTypeMirrors; public AdditionExtractor(Element additionElement, Class<? extends Annotation> additionAnnotation, Element element, Types types, Elements elements, Errors errors) { super(element, types, elements, errors); this.additionAnnotation = additionAnnotation; try { this.additionElement = MoreElements.asType(additionElement); } catch (Exception e) { errors.addInvalid(additionElement, "%s must be a class", additionElement.getSimpleName()); return; } extract(); } @Override public void extract() { targetTypeMirrors = getTypeMirrors("value"); if (targetTypeMirrors.isEmpty()) { // if there's no value, the target is the element itself targetTypeMirrors.add(additionElement.asType()); } parameterizedTypeMirrors = getTypeMirrors("parameterizedTypes"); // @AutoExpose on provider method can have qualifier if (additionAnnotation.equals(AutoExpose.class) && element.getKind() == ElementKind.METHOD) { qualifierAnnotationMirror = findQualifier(element); providerMethodName = element.getSimpleName().toString(); } } private AnnotationMirror findQualifier(Element element) { List<AnnotationMirror> annotationMirrors = ExtractorUtil.findAnnotatedAnnotation(element, Qualifier.class); if (annotationMirrors.isEmpty()) { return null; } if (annotationMirrors.size() > 1) { errors.getParent().addInvalid(element, "Cannot have several qualifiers (@Qualifier)."); return null; } return annotationMirrors.get(0); } private List<TypeMirror> getTypeMirrors(String member) { List<AnnotationValue> values = ExtractorUtils.getValueFromAnnotation(element, additionAnnotation, member); if (values == null || values.isEmpty()) { return new ArrayList<>(); } List<TypeMirror> typeMirrors = new ArrayList<>(); for (AnnotationValue value : values) { try { TypeMirror tm = (TypeMirror) value.getValue(); typeMirrors.add(tm); } catch (Exception e) { errors.addInvalid("Cannot extract member %s because %s", member, e.getMessage()); } } return typeMirrors; } public TypeElement getAdditionElement() { return additionElement; } public String getProviderMethodName() { return providerMethodName; } public AnnotationMirror getQualifierAnnotationMirror() { return qualifierAnnotationMirror; } public List<TypeMirror> getTargetTypeMirrors() { return targetTypeMirrors; } public List<TypeMirror> getParameterizedTypeMirrors() { return parameterizedTypeMirrors; } }