package architect.autostack.compiler; import com.google.auto.common.MoreElements; import java.util.ArrayList; import java.util.List; import javax.inject.Scope; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import architect.robot.AutoStackable; import autodagger.compiler.utils.AutoComponentExtractorUtil; import processorworkflow.AbstractExtractor; import processorworkflow.Errors; import processorworkflow.ExtractorUtils; import processorworkflow.Logger; /** * @author Lukasz Piliszczuk - lukasz.pili@gmail.com */ public class ScopeExtractor extends AbstractExtractor { private static final String COMPONENT = "component"; private static final String PATH_VIEW = "pathWithView"; private AnnotationMirror scopeAnnotationTypeMirror; private AnnotationMirror componentAnnotationTypeMirror; private TypeMirror componentDependency; private TypeMirror pathViewTypeMirror; private int pathLayout; // private List<VariableElement> fromPathFieldsElements; private List<VariableElement> constructorsParamtersElements; public ScopeExtractor(Element element, Types types, Elements elements, Errors errors) { super(element, types, elements, errors); Logger.d("Extract %s", element.getSimpleName()); extract(); } @Override public void extract() { componentAnnotationTypeMirror = ExtractorUtils.getValueFromAnnotation(element, AutoStackable.class, COMPONENT); if (componentAnnotationTypeMirror == null) { errors.addMissing("@AutoComponent"); return; } // get dependency from @AutoComponent List<TypeMirror> deps = AutoComponentExtractorUtil.getDependencies(componentAnnotationTypeMirror, errors); if (deps.size() != 1) { errors.addInvalid("@AutoComponent must have only 1 dependency"); return; } componentDependency = deps.get(0); pathViewTypeMirror = ExtractorUtils.getValueFromAnnotation(element, AutoStackable.class, PATH_VIEW); pathLayout = element.getAnnotation(AutoStackable.class).pathWithLayout(); scopeAnnotationTypeMirror = findScope(); // fromPathFieldsElements = new ArrayList<>(); constructorsParamtersElements = new ArrayList<>(); int constructorsCount = 0; for (Element enclosedElement : element.getEnclosedElements()) { // if (enclosedElement.getKind() == ElementKind.FIELD && // MoreElements.isAnnotationPresent(enclosedElement, FromPath.class)) { // Logger.d("Get field : %s", enclosedElement.getSimpleName()); // fromPathFieldsElements.add(MoreElements.asVariable(enclosedElement)); // } else if (enclosedElement.getKind() == ElementKind.CONSTRUCTOR) { constructorsCount++; for (VariableElement variableElement : MoreElements.asExecutable(enclosedElement).getParameters()) { constructorsParamtersElements.add(variableElement); } } } if (constructorsCount > 1) { errors.addInvalid("Cannot have several constructors"); return; } } /** * Find annotation that is itself annoted with @Scope * If there is one, it will be later applied on the generated component * Otherwise the component will be unscoped * Throw error if more than one scope annotation found */ private AnnotationMirror findScope() { AnnotationMirror annotationTypeMirror = null; for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { Element annotationElement = annotationMirror.getAnnotationType().asElement(); if (MoreElements.isAnnotationPresent(annotationElement, Scope.class)) { // already found one scope if (annotationTypeMirror != null) { errors.addInvalid("Several dagger scopes on same element are not allowed"); continue; } annotationTypeMirror = annotationMirror; } } return annotationTypeMirror; } public AnnotationMirror getScopeAnnotationTypeMirror() { return scopeAnnotationTypeMirror; } public AnnotationMirror getComponentAnnotationTypeMirror() { return componentAnnotationTypeMirror; } public TypeMirror getPathViewTypeMirror() { return pathViewTypeMirror; } public TypeMirror getComponentDependency() { return componentDependency; } public int getPathLayout() { return pathLayout; } // public List<VariableElement> getFromPathFieldsElements() { // return fromPathFieldsElements; // } public List<VariableElement> getConstructorsParamtersElements() { return constructorsParamtersElements; } }