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());
}
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;
}
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;
}
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;
}
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;
}
}
Aggregations