package autodagger.compiler;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import autodagger.AutoExpose;
import autodagger.AutoInjector;
import dagger.Provides;
import processorworkflow.AbstractComposer;
import processorworkflow.AbstractProcessing;
import processorworkflow.Errors;
import processorworkflow.Logger;
/**
* @author Lukasz Piliszczuk - lukasz.pili@gmail.com
*/
public class AdditionProcessing extends AbstractProcessing<AdditionSpec, State> {
public AdditionProcessing(Elements elements, Types types, Errors errors, State state) {
super(elements, types, errors, state);
}
@Override
public Set<Class<? extends Annotation>> supportedAnnotations() {
return ImmutableSet.of(AutoInjector.class, AutoExpose.class);
}
@Override
public boolean processElement(Element element, Errors.ElementErrors elementErrors) {
// @AutoX applied on annotation
if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
// @AutoX is applied on another annotation, find out the targets of that annotation
Set<? extends Element> targetElements = roundEnvironment.getElementsAnnotatedWith(MoreElements.asType(element));
for (Element targetElement : targetElements) {
if (!process(targetElement, element)) {
return false;
}
}
return true;
}
// @AutoX applied on method
// only valid for @AutoExpose with @Provides
if (element.getKind() == ElementKind.METHOD) {
if (processedAnnotation.equals(AutoInjector.class)) {
errors.addInvalid(element, "@AutoInjector cannot be applied on the method %s", element.getSimpleName());
return false;
}
if (!MoreElements.isAnnotationPresent(element, Provides.class)) {
errors.addInvalid(element, "@AutoExpose can be applied on @Provides method only, %s is missing it", element.getSimpleName());
return false;
}
ExecutableElement executableElement = MoreElements.asExecutable(element);
Element returnElement = MoreTypes.asElement(executableElement.getReturnType());
return process(returnElement, element);
}
process(element, element);
return !errors.hasErrors();
}
private boolean process(Element targetElement, Element element) {
AdditionExtractor extractor = new AdditionExtractor(targetElement, processedAnnotation, element, types, elements, errors);
if (errors.hasErrors()) {
return false;
}
Preconditions.checkArgument(!extractor.getTargetTypeMirrors().isEmpty(), "Addition target cannot be empty");
if (processedAnnotation.equals(AutoInjector.class)) {
state.addInjectorExtractor(extractor);
} else {
state.addExposeExtractor(extractor);
}
return true;
}
@Override
public AbstractComposer<AdditionSpec> createComposer() {
return null;
}
}