Search in sources :

Example 86 with Element

use of javax.lang.model.element.Element in project dagger by square.

the class InjectAdapterProcessor method generateInjectAdapter.

/**
   * Write a companion class for {@code type} that extends {@link Binding}.
   *
   * @param constructor the injectable constructor, or null if this binding
   *     supports members injection only.
   */
private void generateInjectAdapter(TypeElement type, ExecutableElement constructor, List<Element> fields) throws IOException {
    String packageName = getPackage(type).getQualifiedName().toString();
    TypeMirror supertype = getApplicationSupertype(type);
    if (supertype != null) {
        supertype = processingEnv.getTypeUtils().erasure(supertype);
    }
    ClassName injectedClassName = ClassName.get(type);
    ClassName adapterClassName = adapterName(injectedClassName, INJECT_ADAPTER_SUFFIX);
    boolean isAbstract = type.getModifiers().contains(ABSTRACT);
    boolean injectMembers = !fields.isEmpty() || supertype != null;
    boolean disambiguateFields = !fields.isEmpty() && (constructor != null) && !constructor.getParameters().isEmpty();
    boolean dependent = injectMembers || ((constructor != null) && !constructor.getParameters().isEmpty());
    TypeSpec.Builder result = TypeSpec.classBuilder(adapterClassName.simpleName()).addOriginatingElement(type).addModifiers(PUBLIC, FINAL).superclass(ParameterizedTypeName.get(ClassName.get(Binding.class), injectedClassName)).addJavadoc("$L", bindingTypeDocs(injectableType(type.asType()), isAbstract, injectMembers, dependent).toString());
    for (Element field : fields) {
        result.addField(memberBindingField(disambiguateFields, field));
    }
    if (constructor != null) {
        for (VariableElement parameter : constructor.getParameters()) {
            result.addField(parameterBindingField(disambiguateFields, parameter));
        }
    }
    if (supertype != null) {
        result.addField(supertypeBindingField(supertype));
    }
    result.addMethod(writeInjectAdapterConstructor(constructor, type, injectedClassName));
    if (dependent) {
        result.addMethod(attachMethod(constructor, fields, disambiguateFields, injectedClassName, supertype, true));
        result.addMethod(getDependenciesMethod(constructor, fields, disambiguateFields, supertype, true));
    }
    if (constructor != null) {
        result.addMethod(getMethod(constructor, disambiguateFields, injectMembers, injectedClassName));
    }
    if (injectMembers) {
        result.addMethod(membersInjectMethod(fields, disambiguateFields, injectedClassName, supertype));
    }
    JavaFile javaFile = JavaFile.builder(packageName, result.build()).addFileComment(AdapterJavadocs.GENERATED_BY_DAGGER).build();
    javaFile.writeTo(processingEnv.getFiler());
}
Also used : Binding(dagger.internal.Binding) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ClassName(com.squareup.javapoet.ClassName) JavaFile(com.squareup.javapoet.JavaFile) Util.rawTypeToString(dagger.internal.codegen.Util.rawTypeToString) Util.elementToString(dagger.internal.codegen.Util.elementToString) VariableElement(javax.lang.model.element.VariableElement) TypeSpec(com.squareup.javapoet.TypeSpec)

Example 87 with Element

use of javax.lang.model.element.Element in project dagger by square.

the class InjectAdapterProcessor method validateInjectable.

private boolean validateInjectable(Element injectable) {
    Element injectableType = injectable.getEnclosingElement();
    if (injectable.getKind() == ElementKind.CLASS) {
        error("@Inject is not valid on a class: " + elementToString(injectable), injectable);
        return false;
    }
    if (injectable.getKind() == ElementKind.METHOD) {
        error("Method injection is not supported: " + elementToString(injectable), injectable);
        return false;
    }
    if (injectable.getKind() == ElementKind.FIELD && injectable.getModifiers().contains(FINAL)) {
        error("Can't inject a final field: " + elementToString(injectable), injectable);
        return false;
    }
    if (injectable.getKind() == ElementKind.FIELD && injectable.getModifiers().contains(PRIVATE)) {
        error("Can't inject a private field: " + elementToString(injectable), injectable);
        return false;
    }
    if (injectable.getKind() == ElementKind.CONSTRUCTOR && injectable.getModifiers().contains(PRIVATE)) {
        error("Can't inject a private constructor: " + elementToString(injectable), injectable);
        return false;
    }
    ElementKind elementKind = injectableType.getEnclosingElement().getKind();
    boolean isClassOrInterface = elementKind.isClass() || elementKind.isInterface();
    boolean isStatic = injectableType.getModifiers().contains(STATIC);
    if (isClassOrInterface && !isStatic) {
        error("Can't inject a non-static inner class: " + elementToString(injectable), injectableType);
        return false;
    }
    return true;
}
Also used : ElementKind(javax.lang.model.element.ElementKind) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement)

Example 88 with Element

use of javax.lang.model.element.Element in project dagger by square.

the class ModuleAdapterProcessor method providerMethodsByClass.

/**
   * Returns a map containing all {@code @Provides} methods, indexed by class.
   */
private Map<String, List<ExecutableElement>> providerMethodsByClass(RoundEnvironment env) {
    Elements elementUtils = processingEnv.getElementUtils();
    Types types = processingEnv.getTypeUtils();
    Map<String, List<ExecutableElement>> result = new HashMap<String, List<ExecutableElement>>();
    provides: for (Element providerMethod : findProvidesMethods(env)) {
        switch(providerMethod.getEnclosingElement().getKind()) {
            case CLASS:
                // valid, move along
                break;
            default:
                // TODO(tbroyer): pass annotation information
                error("Unexpected @Provides on " + elementToString(providerMethod), providerMethod);
                continue;
        }
        TypeElement type = (TypeElement) providerMethod.getEnclosingElement();
        Set<Modifier> typeModifiers = type.getModifiers();
        if (typeModifiers.contains(PRIVATE) || typeModifiers.contains(ABSTRACT)) {
            error("Classes declaring @Provides methods must not be private or abstract: " + type.getQualifiedName(), type);
            continue;
        }
        Set<Modifier> methodModifiers = providerMethod.getModifiers();
        if (methodModifiers.contains(PRIVATE) || methodModifiers.contains(ABSTRACT) || methodModifiers.contains(STATIC)) {
            error("@Provides methods must not be private, abstract or static: " + type.getQualifiedName() + "." + providerMethod, providerMethod);
            continue;
        }
        ExecutableElement providerMethodAsExecutable = (ExecutableElement) providerMethod;
        if (!providerMethodAsExecutable.getThrownTypes().isEmpty()) {
            error("@Provides methods must not have a throws clause: " + type.getQualifiedName() + "." + providerMethod, providerMethod);
            continue;
        }
        // Invalidate return types.
        TypeMirror returnType = types.erasure(providerMethodAsExecutable.getReturnType());
        if (!returnType.getKind().equals(TypeKind.ERROR)) {
            // processors is not "invalid" in this way, so ignore).
            for (String invalidTypeName : INVALID_RETURN_TYPES) {
                TypeElement invalidTypeElement = elementUtils.getTypeElement(invalidTypeName);
                if (invalidTypeElement != null && types.isSameType(returnType, types.erasure(invalidTypeElement.asType()))) {
                    error(String.format("@Provides method must not return %s directly: %s.%s", invalidTypeElement, type.getQualifiedName(), providerMethod), providerMethod);
                    // Skip to next provides method.
                    continue provides;
                }
            }
        }
        List<ExecutableElement> methods = result.get(type.getQualifiedName().toString());
        if (methods == null) {
            methods = new ArrayList<ExecutableElement>();
            result.put(type.getQualifiedName().toString(), methods);
        }
        methods.add(providerMethodAsExecutable);
    }
    TypeMirror objectType = elementUtils.getTypeElement("java.lang.Object").asType();
    // should still be registered and a ModuleAdapter should still be written.
    for (Element module : env.getElementsAnnotatedWith(Module.class)) {
        if (!module.getKind().equals(ElementKind.CLASS)) {
            error("Modules must be classes: " + elementToString(module), module);
            continue;
        }
        TypeElement moduleType = (TypeElement) module;
        // Verify that all modules do not extend from non-Object types.
        if (!types.isSameType(moduleType.getSuperclass(), objectType)) {
            error("Modules must not extend from other classes: " + elementToString(module), module);
        }
        String moduleName = moduleType.getQualifiedName().toString();
        if (result.containsKey(moduleName))
            continue;
        result.put(moduleName, new ArrayList<ExecutableElement>());
    }
    return result;
}
Also used : SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Types(javax.lang.model.util.Types) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) Util.typeToString(dagger.internal.codegen.Util.typeToString) Util.elementToString(dagger.internal.codegen.Util.elementToString) Elements(javax.lang.model.util.Elements) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) ArrayList(java.util.ArrayList)

Example 89 with Element

use of javax.lang.model.element.Element in project dagger by square.

the class ValidationProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> types, RoundEnvironment env) {
    List<Element> allElements = new ArrayList<Element>();
    Map<Element, Element> parametersToTheirMethods = new LinkedHashMap<Element, Element>();
    getAllElements(env, allElements, parametersToTheirMethods);
    for (Element element : allElements) {
        try {
            validateProvides(element);
        } catch (CodeGenerationIncompleteException e) {
            // Upstream compiler issue in play. Ignore this element.
            continue;
        }
        validateScoping(element);
        validateQualifiers(element, parametersToTheirMethods);
    }
    return false;
}
Also used : CodeGenerationIncompleteException(dagger.internal.codegen.Util.CodeGenerationIncompleteException) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap)

Example 90 with Element

use of javax.lang.model.element.Element in project javapoet by square.

the class JavaFile method writeTo.

/** Writes this to {@code filer}. */
public void writeTo(Filer filer) throws IOException {
    String fileName = packageName.isEmpty() ? typeSpec.name : packageName + "." + typeSpec.name;
    List<Element> originatingElements = typeSpec.originatingElements;
    JavaFileObject filerSourceFile = filer.createSourceFile(fileName, originatingElements.toArray(new Element[originatingElements.size()]));
    try (Writer writer = filerSourceFile.openWriter()) {
        writeTo(writer);
    } catch (Exception e) {
        try {
            filerSourceFile.delete();
        } catch (Exception ignored) {
        }
        throw e;
    }
}
Also used : SimpleJavaFileObject(javax.tools.SimpleJavaFileObject) JavaFileObject(javax.tools.JavaFileObject) Element(javax.lang.model.element.Element) Writer(java.io.Writer) OutputStreamWriter(java.io.OutputStreamWriter) IOException(java.io.IOException)

Aggregations

Element (javax.lang.model.element.Element)286 TypeElement (javax.lang.model.element.TypeElement)227 ExecutableElement (javax.lang.model.element.ExecutableElement)148 VariableElement (javax.lang.model.element.VariableElement)96 TypeMirror (javax.lang.model.type.TypeMirror)68 PackageElement (javax.lang.model.element.PackageElement)48 ArrayList (java.util.ArrayList)39 DeclaredType (javax.lang.model.type.DeclaredType)30 IOException (java.io.IOException)29 Map (java.util.Map)26 HashSet (java.util.HashSet)23 LinkedHashSet (java.util.LinkedHashSet)22 List (java.util.List)22 Set (java.util.Set)22 Test (org.junit.Test)21 ElementKind (javax.lang.model.element.ElementKind)20 AnnotationMirror (javax.lang.model.element.AnnotationMirror)19 Elements (javax.lang.model.util.Elements)18 HashMap (java.util.HashMap)16 LinkedHashMap (java.util.LinkedHashMap)15