Skip to content

Commit

Permalink
Merge pull request google#272 from cgruber/renameanalysisbindings
Browse files Browse the repository at this point in the history
Re-name and slightly restructure much of the processor code
cgruber committed Jun 7, 2013
2 parents 08fd708 + 768c731 commit 2477211
Showing 14 changed files with 130 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -16,10 +16,10 @@
package dagger.internal.codegen;

/**
* Utility class providing some commonly used boilerplate between {@code InjectProcessor}
* and {@code ProvidesProcessor}.
* Utility class providing some commonly used boilerplate between {@code InjectAdapterProcessor}
* and {@code ModuleAdapterProcessor}.
*/
public final class ProcessorJavadocs {
public final class AdapterJavadocs {
static final String GENERATED_BY_DAGGER = "Code generated by dagger-compiler. Do not edit.";
static final String MEMBERS_INJECT_METHOD = ""
+ "Injects any {@code @Inject} annotated fields in the given instance,\n"
Original file line number Diff line number Diff line change
@@ -25,6 +25,9 @@
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

import static dagger.internal.codegen.TypeUtils.rawTypeToString;
import static dagger.internal.codegen.TypeUtils.typeToString;

/**
* Creates keys using javac's mirror APIs. Unlike {@code Keys}, this class uses
* APIs not available on Android.
@@ -41,13 +44,13 @@ private GeneratorKeys() {
* generated code.
*/
public static String rawMembersKey(TypeMirror type) {
return "members/" + CodeGen.rawTypeToString(type, '$');
return "members/" + rawTypeToString(type, '$');
}

/** Returns the provider key for {@code type}. */
public static String get(TypeMirror type) {
StringBuilder result = new StringBuilder();
CodeGen.typeToString(type, result, '$');
typeToString(type, result, '$');
return result.toString();
}

@@ -58,7 +61,7 @@ public static String get(ExecutableElement method) {
if (qualifier != null) {
qualifierToString(qualifier, result);
}
CodeGen.typeToString(method.getReturnType(), result, '$');
typeToString(method.getReturnType(), result, '$');
return result.toString();
}

@@ -70,7 +73,7 @@ public static String getSetKey(ExecutableElement method) {
qualifierToString(qualifier, result);
}
result.append(SET_PREFIX);
CodeGen.typeToString(method.getReturnType(), result, '$');
typeToString(method.getReturnType(), result, '$');
result.append(">");
return result.toString();
}
@@ -82,14 +85,14 @@ public static String get(VariableElement variable) {
if (qualifier != null) {
qualifierToString(qualifier, result);
}
CodeGen.typeToString(variable.asType(), result, '$');
typeToString(variable.asType(), result, '$');
return result.toString();
}

private static void qualifierToString(AnnotationMirror qualifier, StringBuilder result) {
// TODO: guarantee that element values are sorted by name (if there are multiple)
result.append('@');
CodeGen.typeToString(qualifier.getAnnotationType(), result, '$');
typeToString(qualifier.getAnnotationType(), result, '$');
result.append('(');
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry
: qualifier.getElementValues().entrySet()) {
Original file line number Diff line number Diff line change
@@ -25,11 +25,11 @@
* A {@code Linker.ErrorHandler} which gathers errors and reports them via a processing
* environment.
*/
final class ReportingErrorHandler implements Linker.ErrorHandler {
final class GraphAnalysisErrorHandler implements Linker.ErrorHandler {
private final ProcessingEnvironment processingEnv;
private final String moduleName;

ReportingErrorHandler(ProcessingEnvironment processingEnv, String moduleName) {
GraphAnalysisErrorHandler(ProcessingEnvironment processingEnv, String moduleName) {
this.processingEnv = processingEnv;
this.moduleName = moduleName;
}
Original file line number Diff line number Diff line change
@@ -30,17 +30,18 @@
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

import static dagger.internal.codegen.TypeUtils.getApplicationSupertype;

/**
* A build time binding that injects the constructor and fields of a class.
*/
final class AtInjectBinding extends Binding<Object> {
final class GraphAnalysisInjectBinding extends Binding<Object> {
private final TypeElement type;
private final List<String> keys;
private final Binding<?>[] bindings;
private final String supertypeKey;
private Binding supertypeBinding;

private AtInjectBinding(String provideKey, String membersKey,
private GraphAnalysisInjectBinding(String provideKey, String membersKey,
TypeElement type, List<String> keys, String supertypeKey) {
super(provideKey, membersKey, type.getAnnotation(Singleton.class) != null,
type.getQualifiedName().toString());
@@ -50,7 +51,7 @@ private AtInjectBinding(String provideKey, String membersKey,
this.supertypeKey = supertypeKey;
}

static AtInjectBinding create(TypeElement type, boolean mustHaveInjections) {
static GraphAnalysisInjectBinding create(TypeElement type, boolean mustHaveInjections) {
List<String> requiredKeys = new ArrayList<String>();
boolean hasInjectConstructor = false;
boolean hasNoArgsConstructor = false;
@@ -94,7 +95,7 @@ static AtInjectBinding create(TypeElement type, boolean mustHaveInjections) {
}

// Attach the supertype.
TypeMirror supertype = CodeGen.getApplicationSupertype(type);
TypeMirror supertype = getApplicationSupertype(type);
String supertypeKey = supertype != null
? GeneratorKeys.rawMembersKey(supertype)
: null;
@@ -103,7 +104,7 @@ static AtInjectBinding create(TypeElement type, boolean mustHaveInjections) {
? GeneratorKeys.get(type.asType())
: null;
String membersKey = GeneratorKeys.rawMembersKey(type.asType());
return new AtInjectBinding(provideKey, membersKey, type, requiredKeys, supertypeKey);
return new GraphAnalysisInjectBinding(provideKey, membersKey, type, requiredKeys, supertypeKey);
}

private static boolean hasAtInject(Element enclosed) {
@@ -117,8 +118,8 @@ private static boolean hasAtInject(Element enclosed) {
getClass().getClassLoader());
}
if (supertypeKey != null) {
supertypeBinding = linker.requestBinding(supertypeKey, requiredBy,
getClass().getClassLoader(), false, true);
// Force the binding lookup.
linker.requestBinding(supertypeKey, requiredBy, getClass().getClassLoader(), false, true);
}
}

Original file line number Diff line number Diff line change
@@ -29,11 +29,11 @@
* {@link Binding#get} or {@link Binding#injectMembers} methods. They are only suitable
* for graph analysis and error detection.
*/
public final class CompileTimeLoader implements Loader {
public final class GraphAnalysisLoader implements Loader {

private final ProcessingEnvironment processingEnv;

public CompileTimeLoader(ProcessingEnvironment processingEnv) {
public GraphAnalysisLoader(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}

@@ -51,7 +51,7 @@ public CompileTimeLoader(ProcessingEnvironment processingEnv) {
if (type.getKind() == ElementKind.INTERFACE) {
return null;
}
return AtInjectBinding.create(type, mustHaveInjections);
return GraphAnalysisInjectBinding.create(type, mustHaveInjections);
}

@Override public <T> ModuleAdapter<T> getModuleAdapter(Class<? extends T> moduleClass, T module) {
Original file line number Diff line number Diff line change
@@ -51,11 +51,16 @@
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;

import static dagger.internal.codegen.TypeUtils.getAnnotation;
import static dagger.internal.codegen.TypeUtils.getPackage;
import static dagger.internal.codegen.TypeUtils.isInterface;
import static dagger.internal.codegen.TypeUtils.methodName;

/**
* Performs full graph analysis on a module.
*/
@SupportedAnnotationTypes("dagger.Module")
public final class FullGraphProcessor extends AbstractProcessor {
public final class GraphAnalysisProcessor extends AbstractProcessor {
private final Set<String> delayedModuleNames = new LinkedHashSet<String>();

@Override public SourceVersion getSupportedSourceVersion() {
@@ -86,7 +91,7 @@ public final class FullGraphProcessor extends AbstractProcessor {
}

for (Element element : modules) {
Map<String, Object> annotation = CodeGen.getAnnotation(Module.class, element);
Map<String, Object> annotation = getAnnotation(Module.class, element);
TypeElement moduleType = (TypeElement) element;

if (annotation.get("complete").equals(Boolean.TRUE)) {
@@ -132,27 +137,28 @@ private Map<String, Binding<?>> processCompleteModule(TypeElement rootModule,
boolean ignoreCompletenessErrors) {
Map<String, TypeElement> allModules = new LinkedHashMap<String, TypeElement>();
collectIncludesRecursively(rootModule, allModules, new LinkedList<String>());
ArrayList<CodeGenStaticInjection> staticInjections = new ArrayList<CodeGenStaticInjection>();
ArrayList<GraphAnalysisStaticInjection> staticInjections =
new ArrayList<GraphAnalysisStaticInjection>();

Linker.ErrorHandler errorHandler = ignoreCompletenessErrors ? Linker.ErrorHandler.NULL
: new ReportingErrorHandler(processingEnv, rootModule.getQualifiedName().toString());
Linker linker = new Linker(null, new CompileTimeLoader(processingEnv), errorHandler);
: new GraphAnalysisErrorHandler(processingEnv, rootModule.getQualifiedName().toString());
Linker linker = new Linker(null, new GraphAnalysisLoader(processingEnv), errorHandler);
// Linker requires synchronization for calls to requestBinding and linkAll.
// We know statically that we're single threaded, but we synchronize anyway
// to make the linker happy.
synchronized (linker) {
Map<String, Binding<?>> baseBindings = new LinkedHashMap<String, Binding<?>>();
Map<String, Binding<?>> overrideBindings = new LinkedHashMap<String, Binding<?>>();
for (TypeElement module : allModules.values()) {
Map<String, Object> annotation = CodeGen.getAnnotation(Module.class, module);
Map<String, Object> annotation = getAnnotation(Module.class, module);
boolean overrides = (Boolean) annotation.get("overrides");
boolean library = (Boolean) annotation.get("library");
Map<String, Binding<?>> addTo = overrides ? overrideBindings : baseBindings;

// Gather the injectable types from the annotation.
for (Object injectableTypeObject : (Object[]) annotation.get("injects")) {
TypeMirror injectableType = (TypeMirror) injectableTypeObject;
String key = CodeGen.isInterface(injectableType)
String key = isInterface(injectableType)
? GeneratorKeys.get(injectableType)
: GeneratorKeys.rawMembersKey(injectableType);
linker.requestBinding(key, module.getQualifiedName().toString(),
@@ -163,7 +169,7 @@ private Map<String, Binding<?>> processCompleteModule(TypeElement rootModule,
for (Object staticInjection : (Object[]) annotation.get("staticInjections")) {
TypeMirror staticInjectionTypeMirror = (TypeMirror) staticInjection;
Element element = processingEnv.getTypeUtils().asElement(staticInjectionTypeMirror);
staticInjections.add(new CodeGenStaticInjection(element));
staticInjections.add(new GraphAnalysisStaticInjection(element));
}

// Gather the enclosed @Provides methods.
@@ -208,7 +214,7 @@ private Map<String, Binding<?>> processCompleteModule(TypeElement rootModule,

linker.installBindings(baseBindings);
linker.installBindings(overrideBindings);
for (CodeGenStaticInjection staticInjection : staticInjections) {
for (GraphAnalysisStaticInjection staticInjection : staticInjections) {
staticInjection.attach(linker);
}

@@ -225,7 +231,7 @@ private String shortMethodName(ExecutableElement method) {

void collectIncludesRecursively(
TypeElement module, Map<String, TypeElement> result, Deque<String> path) {
Map<String, Object> annotation = CodeGen.getAnnotation(Module.class, module);
Map<String, Object> annotation = getAnnotation(Module.class, module);
if (annotation == null) {
// TODO(tbroyer): pass annotation information
throw new ModuleValidationException("No @Module on " + module, module);
@@ -253,7 +259,7 @@ void collectIncludesRecursively(
result.put(name, module);

// Recurse for each included module.
Types typeUtils = processingEnv.getTypeUtils();
Types types = processingEnv.getTypeUtils();
List<Object> seedModules = new ArrayList<Object>();
seedModules.addAll(Arrays.asList((Object[]) annotation.get("includes")));
if (!annotation.get("addsTo").equals(Void.class)) seedModules.add(annotation.get("addsTo"));
@@ -264,7 +270,7 @@ void collectIncludesRecursively(
"Unexpected value for include: " + include + " in " + module, module);
continue;
}
TypeElement includedModule = (TypeElement) typeUtils.asElement((TypeMirror) include);
TypeElement includedModule = (TypeElement) types.asElement((TypeMirror) include);
path.push(name);
collectIncludesRecursively(includedModule, result, path);
path.pop();
@@ -276,8 +282,7 @@ static class ProviderMethodBinding extends Binding<Object> {
private final Binding<?>[] parameters;

protected ProviderMethodBinding(String provideKey, ExecutableElement method, boolean library) {
super(provideKey, null, method.getAnnotation(Singleton.class) != null,
CodeGen.methodName(method));
super(provideKey, null, method.getAnnotation(Singleton.class) != null, methodName(method));
this.method = method;
this.parameters = new Binding[method.getParameters().size()];
setLibrary(library);
@@ -307,12 +312,12 @@ protected ProviderMethodBinding(String provideKey, ExecutableElement method, boo

void writeDotFile(TypeElement module, Map<String, Binding<?>> bindings) throws IOException {
JavaFileManager.Location location = StandardLocation.SOURCE_OUTPUT;
String path = CodeGen.getPackage(module).getQualifiedName().toString();
String path = getPackage(module).getQualifiedName().toString();
String file = module.getQualifiedName().toString().substring(path.length() + 1) + ".dot";
FileObject resource = processingEnv.getFiler().createResource(location, path, file, module);

Writer writer = resource.openWriter();
DotWriter dotWriter = new DotWriter(writer);
GraphVizWriter dotWriter = new GraphVizWriter(writer);
new GraphVisualizer().write(bindings, dotWriter);
dotWriter.close();
}
Original file line number Diff line number Diff line change
@@ -20,17 +20,19 @@
import javax.inject.Inject;
import javax.lang.model.element.Element;

public final class CodeGenStaticInjection extends StaticInjection {
import static dagger.internal.codegen.TypeUtils.isStatic;

public final class GraphAnalysisStaticInjection extends StaticInjection {

private final Element enclosingClass;

public CodeGenStaticInjection(Element enclosingClass) {
public GraphAnalysisStaticInjection(Element enclosingClass) {
this.enclosingClass = enclosingClass;
}

@Override public void attach(Linker linker) {
for (Element enclosedElement : enclosingClass.getEnclosedElements()) {
if (enclosedElement.getKind().isField() && CodeGen.isStatic(enclosedElement)) {
if (enclosedElement.getKind().isField() && isStatic(enclosedElement)) {
Inject injectAnnotation = enclosedElement.getAnnotation(Inject.class);
if (injectAnnotation != null) {
String key = GeneratorKeys.get(enclosedElement.asType());
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ public final class GraphVisualizer {
+ "((\\[\\])*)" // Arrays. Group 4.
+ "");

public void write(Map<String, Binding<?>> bindings, DotWriter writer) throws IOException {
public void write(Map<String, Binding<?>> bindings, GraphVizWriter writer) throws IOException {
Map<Binding<?>, String> namesIndex = buildNamesIndex(bindings);

writer.beginGraph("concentrate", "true");
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
/**
* Emits dot graphs.
*/
public final class DotWriter implements Closeable {
public final class GraphVizWriter implements Closeable {
private static final String INDENT = " ";
private final Writer out;
private int indent = 0;
@@ -36,7 +36,7 @@ public final class DotWriter implements Closeable {
* @param out the stream to which dot data will be written. This should be a
* buffered stream.
*/
public DotWriter(Writer out) {
public GraphVizWriter(Writer out) {
this.out = out;
}

Loading

0 comments on commit 2477211

Please sign in to comment.