![JAR search and dependency download from the Maven repository](/logo.png)
dagger.internal.codegen.FullGraphProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dagger-compiler Show documentation
Show all versions of dagger-compiler Show documentation
Tools to generate Dagger injection and module adapters from annotated code and validate them.
The newest version!
/*
* Copyright (C) 2012 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.internal.codegen;
import dagger.Module;
import dagger.Provides;
import dagger.internal.Binding;
import dagger.internal.Linker;
import dagger.internal.SetBinding;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.inject.Singleton;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;
/**
* Performs full graph analysis on a module.
*/
@SupportedAnnotationTypes("dagger.Module")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public final class FullGraphProcessor extends AbstractProcessor {
/**
* Perform full-graph analysis on complete modules. This checks that all of
* the module's dependencies are satisfied.
*/
@Override public boolean process(Set extends TypeElement> types, RoundEnvironment env) {
try {
for (Element element : env.getElementsAnnotatedWith(Module.class)) {
Map annotation = CodeGen.getAnnotation(Module.class, element);
if (!annotation.get("complete").equals(Boolean.TRUE)) {
continue;
}
TypeElement moduleType = (TypeElement) element;
Map> bindings = processCompleteModule(moduleType);
writeDotFile(moduleType, bindings);
}
} catch (IOException e) {
error("Graph processing failed: " + e);
}
return true;
}
private void error(String message) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message);
}
private Map> processCompleteModule(TypeElement rootModule) {
Map allModules = new LinkedHashMap();
collectIncludesRecursively(rootModule, allModules);
Linker linker = new Linker(null, new CompileTimePlugin(processingEnv),
new ReportingErrorHandler(processingEnv, rootModule.getQualifiedName().toString()));
// 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> baseBindings = new LinkedHashMap>();
Map> overrideBindings = new LinkedHashMap>();
for (TypeElement module : allModules.values()) {
Map annotation = CodeGen.getAnnotation(Module.class, module);
boolean overrides = (Boolean) annotation.get("overrides");
Map> addTo = overrides ? overrideBindings : baseBindings;
// Gather the entry points from the annotation.
for (Object entryPoint : (Object[]) annotation.get("entryPoints")) {
linker.requestBinding(GeneratorKeys.rawMembersKey((TypeMirror) entryPoint),
module.getQualifiedName().toString(), false);
}
// Gather the static injections.
// TODO.
// Gather the enclosed @Provides methods.
for (Element enclosed : module.getEnclosedElements()) {
Provides provides = enclosed.getAnnotation(Provides.class);
if (provides == null) {
continue;
}
ExecutableElement providerMethod = (ExecutableElement) enclosed;
String key = GeneratorKeys.get(providerMethod);
ProviderMethodBinding binding = new ProviderMethodBinding(key, providerMethod);
switch (provides.type()) {
case UNIQUE:
ProviderMethodBinding clobbered = (ProviderMethodBinding) addTo.put(key, binding);
if (clobbered != null) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
"Duplicate bindings for " + key
+ ": " + shortMethodName(clobbered.method)
+ ", " + shortMethodName(binding.method));
}
break;
case SET:
String elementKey = GeneratorKeys.getElementKey(providerMethod);
SetBinding.add(addTo, elementKey, binding);
break;
default:
throw new AssertionError("Unknown @Provides type " + provides.type());
}
}
}
linker.installBindings(baseBindings);
linker.installBindings(overrideBindings);
// Link the bindings. This will traverse the dependency graph, and report
// errors if any dependencies are missing.
return linker.linkAll();
}
}
private String shortMethodName(ExecutableElement method) {
return method.getEnclosingElement().getSimpleName().toString()
+ "." + method.getSimpleName() + "()";
}
private void collectIncludesRecursively(TypeElement module, Map result) {
// Add the module.
result.put(module.getQualifiedName().toString(), module);
// Recurse for each included module.
Types typeUtils = processingEnv.getTypeUtils();
Map annotation = CodeGen.getAnnotation(Module.class, module);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy