use of javax.lang.model.type.ExecutableType in project tiger by google.
the class GeneralInjectorGeneratorHubClone method generateProvisionMethodFromClass.
/**
* Generic is handled.
*/
protected final void generateProvisionMethodFromClass(BindingKey key, String suffix) {
// logger.n("key: " + key + " referencingClass: " +
// referencingClass);
TypeElement cls = utils.getClassFromKey(key);
DeclaredType clsType = (DeclaredType) utils.getTypeFromKey(key);
ExecutableElement ctor = utils.findInjectedCtor(cls);
Preconditions.checkNotNull(ctor, String.format("Did not find ctor for %s", cls));
ExecutableType ctorType = (ExecutableType) types.asMemberOf(clsType, ctor);
List<BindingKey> dependencyKeys = utils.getDependenciesFromMethod(ctorType, ctor);
// TODO: clean this.
// if (key.getTypeName() instanceof ParameterizedTypeName) {
// logger.n("be here :" + key);
// List<BindingKey> specializedKeys = new ArrayList<>();
// Map<TypeVariableName, TypeName> map =
// utils.getMapFromTypeVariableToSpecialized((ParameterizedTypeName) key.getTypeName(),
// (ParameterizedTypeName) TypeName.get(cls.asType()));
// for (BindingKey k : dependencyKeys) {
// specializedKeys.add(utils.specializeIfNeeded(k, map));
// }
// dependencyKeys = specializedKeys;
// }
// logger.n("dependencyKeys: " +
// dependencyKeys);
MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(getProvisionMethodName(key) + suffix);
methodSpecBuilder.addModifiers(suffix.isEmpty() ? Modifier.PUBLIC : Modifier.PRIVATE).returns(key.getTypeName());
onProvisionMethodStart(methodSpecBuilder, key);
methodSpecBuilder.addStatement("$T result", key.getTypeName());
addNewStatementToMethodSpec(methodSpecBuilder, Iterables.getOnlyElement(dependencies.get(key)), "result");
if (shouldInjectAfterCreation() && !utils.isNotSpecializedGeneric(cls.asType()) && utils.hasInjectedFieldsOrMethodsRecursively(cls, processingEnv)) {
// logger.n("hasInjected");
generateInjectionMethod(key);
methodSpecBuilder.addStatement("inject(result)");
}
methodSpecBuilder.addStatement("return result");
onProvisionMethodEnd(methodSpecBuilder, key);
injectorBuilder.addMethod(methodSpecBuilder.build());
}
use of javax.lang.model.type.ExecutableType in project tiger by google.
the class HubInjectorGenerator method generateImplicitMethods.
/**
* Generates those methods that are not declared in the (sub)component interface.
*/
protected void generateImplicitMethods() {
utils.traverseAndDo(types, (DeclaredType) eitherComponent.asType(), eitherComponent, p -> {
Element e = p.second;
// logger.n("element: " + e);
if (!utils.isMethod(e)) {
return null;
}
ExecutableElement method = (ExecutableElement) e;
ExecutableType methodType = (ExecutableType) p.first;
if (utils.isInjectionMethod(method)) {
TypeElement injectedTypeElement = (TypeElement) ((DeclaredType) Iterables.getOnlyElement(methodType.getParameterTypes())).asElement();
logger.l(Kind.NOTE, "injection method for: " + injectedTypeElement);
generateInjectionMethod(injectedTypeElement, "inject");
} else if (utils.isProvisionMethodInInjector(method)) {
generateProvisionMethodIfNeeded(utils.getKeyProvidedByMethod(method));
} else {
// TODO: ignore known elements like builders.
logger.w("Unknown element %s from injector %s.", method, eitherComponent);
}
return null;
});
// logger.n("packagedInjectorBuilders: " + packagedInjectorBuilders);
// Inherited provision methods.
// for (CoreInjectorInfo component : orderedCoreinjectors) {
// if (componentTree.get(component) == null) {
// continue;
// }
// for (Map.Entry<ClassName, Builder> entry : packagedInjectorBuilders.entrySet()) {
// ClassName packagedInjectorClassName = entry.getKey();
// if (!component
// .equals(getComponentFromPackagedInjectorClassName(packagedInjectorClassName))) {
// continue;
// }
// generateInheritedProvisionMethods(packagedInjectorClassName);
// }
// }
// Inherited injection methods.
// for (CoreInjectorInfo component : orderedCoreinjectors) {
// if (componentTree.get(component) == null) {
// continue;
// }
// for (Map.Entry<ClassName, Builder> entry : packagedInjectorBuilders.entrySet()) {
// ClassName packagedInjectorClassName = entry.getKey();
// if (!component
// .equals(getComponentFromPackagedInjectorClassName(packagedInjectorClassName))) {
// continue;
// }
// generateInheritedInjectionMethods(packagedInjectorClassName);
// }
// }
// JavaFile javaFile =
// JavaFile.builder(utils.getPackage(eitherComponent).getQualifiedName().toString(),
// builder.build()).build();
// logger.l( // Kind.NOTE, "javaFile for: " + builder.build() + "\n" + javaFile.toString());
// logger.n("file: %s", javaFile));
// try {
// // javaFile.writeTo(processingEnv.getFiler());
// } catch (IOException e) {
// Throwables.propagate(e);
// }
}
use of javax.lang.model.type.ExecutableType in project tiger by google.
the class CoreInjectorGenerator method generateTopLevelInjectors.
private void generateTopLevelInjectors() {
messager.printMessage(Kind.NOTE, "generateTopLevelInjectors");
SetMultimap<BindingKey, ClassName> keyToPackagedInjectorMap = utils.reverseSetMultimap(generatedBindingsForPackagedInjector);
for (CoreInjectorInfo coreInjectorInfo : orderedCoreinjectors) {
TypeSpec.Builder injectorBuilder = TypeSpec.classBuilder(getTopLevelInjectorName(coreInjectorInfo, topLevelInjectorPrefix, topLevelInjectorSuffix)).addAnnotation(AnnotationSpec.builder(Generated.class).addMember("value", "$S", GENERATOR_NAME).build()).addModifiers(Modifier.PUBLIC);
// method simple name and type.
Set<Pair<String, TypeName>> injectionMethodsDone = new HashSet<>();
// Member injector interfaces.
for (TypeElement injector : coreInjectorToComponentMap.get(coreInjectorInfo)) {
injectorBuilder.addSuperinterface(TypeName.get(injector.asType()));
}
// Ctor
MethodSpec.Builder ctorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
ctorBuilder.addStatement("$T.out.printf($S, $L)", ClassName.get(System.class), "This is tiger: %s\n", "this");
// Ctor - Containing top level injector.
// TODO: remove this .
String containingInjectorName = "containingInjector";
if (componentTree.get(coreInjectorInfo) != null) {
ClassName containingInjectorClassName = ClassName.get(topLevelPackageString, getTopLevelInjectorName(componentTree.get(coreInjectorInfo), topLevelInjectorPrefix, topLevelInjectorSuffix));
injectorBuilder.addField(containingInjectorClassName, containingInjectorName, Modifier.PRIVATE);
ctorBuilder.addParameter(containingInjectorClassName, containingInjectorName).addStatement("this.$L = $L", containingInjectorName, containingInjectorName);
}
// Ctor - ancester top level injectors.
CoreInjectorInfo tmp = coreInjectorInfo;
while (componentTree.get(tmp) != null) {
tmp = componentTree.get(tmp);
ClassName className = ClassName.get(topLevelPackageString, getTopLevelInjectorName(tmp, topLevelInjectorPrefix, topLevelInjectorSuffix));
String sourceCodeName = utils.getSourceCodeName(className);
injectorBuilder.addField(className, sourceCodeName);
if (tmp.equals(componentTree.get(coreInjectorInfo))) {
ctorBuilder.addStatement("this.$L = $L", sourceCodeName, containingInjectorName);
} else {
ctorBuilder.addStatement("this.$L = $L.$L", sourceCodeName, containingInjectorName, sourceCodeName);
}
}
// Ctor - Component dependencies
for (TypeElement dep : utils.sortByFullName(coreInjectorToComponentDependencyMap.get(coreInjectorInfo))) {
if (utils.isEitherComponent(dep)) {
continue;
}
ClassName className = ClassName.get(dep);
String sourceCodeName = utils.getSourceCodeName(className);
injectorBuilder.addField(className, sourceCodeName, Modifier.PUBLIC);
ctorBuilder.addParameter(className, sourceCodeName).addStatement("this.$L = $L", sourceCodeName, sourceCodeName);
}
// Ctor - @BindsInstance
for (BindingKey key : utils.sortBindingKeys(coreInjectorToBindsInstanceMap.get(coreInjectorInfo))) {
String sourceCodeName = utils.getSourceCodeNameHandlingBox(key, dependencies);
injectorBuilder.addField(key.getTypeName(), sourceCodeName, Modifier.PUBLIC);
ctorBuilder.addParameter(key.getTypeName(), sourceCodeName).addStatement("this.$L = $L", sourceCodeName, sourceCodeName);
}
// Ctor - Passed modules.
Set<TypeElement> allPassedModules = new HashSet<>();
allPassedModules.addAll(nonNullaryCtorModules.get(coreInjectorInfo));
allPassedModules.addAll(nonNullaryCtorUnscopedModules);
for (TypeElement passedModule : utils.sortByFullName(allPassedModules)) {
String moduleName = utils.getSourceCodeName(passedModule);
ClassName moduleTypeName = (ClassName) TypeName.get(passedModule.asType());
ctorBuilder.addParameter(moduleTypeName, moduleName).addStatement("this.$N = $N", moduleName, moduleName);
injectorBuilder.addField(moduleTypeName, moduleName, Modifier.PRIVATE).addMethod(MethodSpec.methodBuilder(utils.getGetMethodName(moduleTypeName)).addModifiers(Modifier.PUBLIC).returns(moduleTypeName).addStatement("return $N", moduleName).build());
}
injectorBuilder.addMethod(ctorBuilder.build());
// Injection methods and non-injection methods.
Set<String> miscMethodNames = new HashSet<>();
Set<TypeElement> allMembersInjectors = Sets.newHashSet(coreInjectorToComponentMap.get(coreInjectorInfo));
for (TypeElement injector : allMembersInjectors) {
for (Element element : processingEnv.getElementUtils().getAllMembers(injector)) {
messager.printMessage(Kind.NOTE, "method: " + element);
if (!element.getKind().equals(ElementKind.METHOD)) {
continue;
}
ExecutableElement method = (ExecutableElement) element;
ExecutableType methodType = (ExecutableType) processingEnv.getTypeUtils().asMemberOf((DeclaredType) injector.asType(), method);
// Injection methods.
if (utils.isInjectionMethod(element)) {
// TODO: add duplicate check for provision method also.
if (injectionMethodsDone.add(Pair.of(method.getSimpleName().toString(), TypeName.get(Iterables.getOnlyElement(methodType.getParameterTypes())))) == false) {
messager.printMessage(Kind.WARNING, "duplicate injection method: " + method);
continue;
}
TypeMirror typeMirror = Iterables.getOnlyElement(methodType.getParameterTypes());
TypeElement cls = (TypeElement) ((DeclaredType) typeMirror).asElement();
messager.printMessage(Kind.NOTE, TAG + ".generateTopLevelInjector-injection method : " + methodType);
ClassName packagedInjectorClassName = getPackagedInjectorNameOfScope(utils.getPackageString(cls), coreInjectorInfo.getScope());
injectorBuilder.addMethod(MethodSpec.methodBuilder(method.getSimpleName().toString()).addModifiers(Modifier.PUBLIC).addParameter(ClassName.get(cls), "arg").addStatement("$L().inject(arg)", utils.getGetMethodName(packagedInjectorClassName)).build());
} else if (utils.isComponentProvisionMethod(element)) {
messager.printMessage(Kind.ERROR, "Injecting components is not supported: " + element);
} else if (utils.isSubcomponentProvisionMethod(element)) {
generateGetSubcomponentMethod((ExecutableElement) element, injectorBuilder);
} else if (utils.isProvisionMethodInInjector(element)) {
if (!miscMethodNames.add(method.getSimpleName().toString())) {
continue;
}
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getSimpleName().toString()).addModifiers(Modifier.PUBLIC).returns(TypeName.get(method.getReturnType()));
BindingKey providedKey = utils.getKeyProvidedByMethod(method);
ClassName packagedInjectorClassName = null;
for (ClassName className : keyToPackagedInjectorMap.get(providedKey)) {
if (isInjectorOfScope(className, coreInjectorInfo.getScope())) {
packagedInjectorClassName = className;
break;
}
}
if (packagedInjectorClassName == null) {
messager.printMessage(Kind.WARNING, String.format("PackagedInjector or multiBindingInjector not found for key: %s " + "from provisionMethod: %s. Probably it is not used.", providedKey, method));
// Create a dumb method
String statement = "return ";
TypeKind typeKind = method.getReturnType().getKind();
if (typeKind.equals(TypeKind.BOOLEAN)) {
statement += "false";
} else if (typeKind.equals(TypeKind.CHAR)) {
statement += "\'0\'";
} else if (typeKind.isPrimitive()) {
statement += "0";
} else {
statement += "null";
}
methodBuilder.addStatement(statement);
} else {
String statement = "return $L().$L()";
methodBuilder.addStatement(statement, utils.getGetMethodName(packagedInjectorClassName), utils.getProvisionMethodName(dependencies, providedKey));
}
// messager.printMessage(Kind.NOTE, "provision method added: " + methodBuilder.build());
injectorBuilder.addMethod(methodBuilder.build());
// } else if (utils.isEitherComponentProvisionMethod(element)) {
// // TODO: support get component method.
// if(utils.isComponentProvisionMethod(element)) {
// throw new RuntimeException("component provision method is not suported yet.");
// }
// generateGetSubcomponentMethod((ExecutableElement) element, injectorBuilder);
// } else if (utils.isEitherComponentBuilderProvisionMethod(element)) {
// /**
// * TODO: handle it in the way consistent with other {@link DependencySourceType} in
// * {@link #generateProvisionMethodIfNeeded(BindingKey, TypeElement)}
// */
// generateExplicitProvisionMethodForEitherComponentBuilder(
// (ExecutableElement) element, injectorBuilder);
} else if (isIrrelevantMethodInInjector(element)) {
// do nothing
} else {
messager.printMessage(Kind.WARNING, String.format("Element %s ignored from injector %s.", element, injector));
}
}
}
// Methods to get packaged injectors.
for (Map.Entry<ClassName, TypeSpec.Builder> entry : packagedInjectorBuilders.entrySet()) {
ClassName injectorClassName = entry.getKey();
if (!coreInjectorInfo.equals(getComponentFromPackagedInjectorClassName(injectorClassName))) {
continue;
}
String packagedInjectorSourceCodeName = utils.getSourceCodeName(injectorClassName);
injectorBuilder.addField(injectorClassName, packagedInjectorSourceCodeName, Modifier.PRIVATE);
MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(utils.getGetMethodName(injectorClassName)).addModifiers(Modifier.PUBLIC).returns(injectorClassName).addStatement("$T result = $N", injectorClassName, packagedInjectorSourceCodeName).beginControlFlow("if (result == null)");
StringBuilder stringBuilder = new StringBuilder("result = $N = new $T(this");
if (componentTree.get(coreInjectorInfo) != null) {
ClassName containingPackageInjectorClassName = getInjectorNameOfScope(injectorClassName, componentTree.get(coreInjectorInfo).getScope());
stringBuilder.append(", ").append(containingInjectorName).append(".").append(utils.getGetMethodName(containingPackageInjectorClassName)).append("()");
}
stringBuilder.append(")");
methodSpecBuilder.addStatement(stringBuilder.toString(), packagedInjectorSourceCodeName, injectorClassName);
methodSpecBuilder.endControlFlow().addStatement("return result");
injectorBuilder.addMethod(methodSpecBuilder.build());
}
// Builder and builder().
generateInjectorBuilder(coreInjectorInfo, injectorBuilder);
ClassName builderClassName = getTopLevelInjectorBuilderClassName(coreInjectorInfo);
MethodSpec.Builder methodSpecBuilder = // "Dagger compatible component will have "builder()", we need a different name.
MethodSpec.methodBuilder("getBuilder").addModifiers(Modifier.PUBLIC, Modifier.STATIC).returns(builderClassName).addStatement("return new $T()", builderClassName);
injectorBuilder.addMethod(methodSpecBuilder.build());
// provision methods for (sub)component builders that can be provided by this core injector.
for (TypeElement b : coreInjectorToBothBuilderMap.get(coreInjectorInfo)) {
generateImplicitProvisionMethodForEitherComponentBuilderInTopLevelInjector(injectorBuilder, b);
}
// Write
JavaFile javaFile = JavaFile.builder(topLevelPackageString, injectorBuilder.build()).build();
try {
javaFile.writeTo(processingEnv.getFiler());
} catch (IOException e) {
messager.printMessage(Kind.ERROR, e.toString());
}
}
}
use of javax.lang.model.type.ExecutableType in project tiger by google.
the class CoreInjectorGenerator method generatePackagedInjectors.
private void generatePackagedInjectors() {
for (CoreInjectorInfo coreInjectorInfo : orderedCoreinjectors) {
Set<ClassName> injected = new HashSet<>();
Set<TypeElement> components = Sets.newHashSet(coreInjectorToComponentMap.get(coreInjectorInfo));
for (TypeElement c : components) {
for (Element e : elements.getAllMembers(c)) {
messager.printMessage(Kind.NOTE, "generatePackagedInjectors: element: " + e);
if (!utils.isMethod(e)) {
continue;
}
ExecutableElement method = (ExecutableElement) e;
ExecutableType methodType = ((ExecutableType) types.asMemberOf(((DeclaredType) c.asType()), e));
if (utils.isInjectionMethod(method)) {
TypeElement injectedTypeElement = (TypeElement) ((DeclaredType) Iterables.getOnlyElement(methodType.getParameterTypes())).asElement();
if (!injected.add(ClassName.get(injectedTypeElement))) {
continue;
}
messager.printMessage(Kind.NOTE, TAG + ".generatePackagedInjectors: injection method for: " + injectedTypeElement);
generateInjectionMethod(injectedTypeElement, coreInjectorInfo.getScope());
} else if (utils.isProvisionMethodInInjector(method)) {
generateProvisionMethodIfNeeded(utils.getKeyProvidedByMethod((ExecutableElement) method), c);
} else {
// TODO: ignore known elements like builders.
messager.printMessage(Kind.WARNING, String.format("Unknown element %s from injector %s.", method, c));
}
}
}
}
messager.printMessage(Kind.NOTE, TAG + ".generatePackagedInjectors. packagedInjectorBuilders: " + packagedInjectorBuilders);
// Inherited provision methods.
for (CoreInjectorInfo component : orderedCoreinjectors) {
if (componentTree.get(component) == null) {
continue;
}
for (Map.Entry<ClassName, TypeSpec.Builder> entry : packagedInjectorBuilders.entrySet()) {
ClassName packagedInjectorClassName = entry.getKey();
if (!component.equals(getComponentFromPackagedInjectorClassName(packagedInjectorClassName))) {
continue;
}
generateInheritedProvisionMethods(packagedInjectorClassName);
}
}
// Inherited injection methods.
for (CoreInjectorInfo component : orderedCoreinjectors) {
if (componentTree.get(component) == null) {
continue;
}
for (Map.Entry<ClassName, TypeSpec.Builder> entry : packagedInjectorBuilders.entrySet()) {
ClassName packagedInjectorClassName = entry.getKey();
if (!component.equals(getComponentFromPackagedInjectorClassName(packagedInjectorClassName))) {
continue;
}
generateInheritedInjectionMethods(packagedInjectorClassName);
}
}
for (Map.Entry<ClassName, TypeSpec.Builder> entry : packagedInjectorBuilders.entrySet()) {
String packageString = entry.getKey().packageName();
TypeSpec.Builder builder = entry.getValue();
JavaFile javaFile = JavaFile.builder(packageString, builder.build()).build();
// messager.printMessage(Kind.NOTE, String.format("java file: %s", javaFile));
try {
javaFile.writeTo(processingEnv.getFiler());
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
use of javax.lang.model.type.ExecutableType in project tiger by google.
the class TigerDaggerGeneratorProcessor method completeComponents.
/**
* Find all the (sub)components in question. {@link Component}s are from annotation already. But
* some {@link Subcomponent}s can only be traced by provision methods for them or their builders.
*/
private void completeComponents(Set<TypeElement> components) {
Set<TypeElement> work = Sets.newHashSet(components);
Set<TypeElement> done = Sets.newHashSet();
while (!work.isEmpty()) {
TypeElement c = Preconditions.checkNotNull(Iterables.getFirst(work, null));
work.remove(c);
done.add(c);
utils.traverseAndDo(types, (DeclaredType) c.asType(), c, pair -> {
TypeMirror type = pair.getFirst();
Element element = pair.getSecond();
if (utils.isEitherComponentProvisionMethod(element) || utils.isEitherComponentBuilderProvisionMethod(element)) {
TypeElement newFound = (TypeElement) ((DeclaredType) ((ExecutableType) type).getReturnType()).asElement();
if (utils.isEitherComponentBuilder(newFound)) {
newFound = (TypeElement) newFound.getEnclosingElement();
}
if (!components.contains(newFound)) {
components.add(newFound);
messager.printMessage(Kind.NOTE, TAG + ".completeComponents found new " + newFound + "component: " + c + " method: " + element);
}
if (!done.contains(newFound)) {
work.add(newFound);
}
}
return null;
});
}
}
Aggregations