Search in sources :

Example 61 with JavaFile

use of com.squareup.javapoet.JavaFile 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());
        }
    }
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Builder(com.squareup.javapoet.TypeSpec.Builder) TypeKind(javax.lang.model.type.TypeKind) TypeMirror(javax.lang.model.type.TypeMirror) Builder(com.squareup.javapoet.TypeSpec.Builder) ClassName(com.squareup.javapoet.ClassName) Pair(com.google.common.base.Pair) HashSet(java.util.HashSet) MethodSpec(com.squareup.javapoet.MethodSpec) TypeElement(javax.lang.model.element.TypeElement) IOException(java.io.IOException) JavaFile(com.squareup.javapoet.JavaFile) Map(java.util.Map) HashMap(java.util.HashMap) TypeSpec(com.squareup.javapoet.TypeSpec) DeclaredType(javax.lang.model.type.DeclaredType)

Example 62 with JavaFile

use of com.squareup.javapoet.JavaFile 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);
        }
    }
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Builder(com.squareup.javapoet.TypeSpec.Builder) IOException(java.io.IOException) Builder(com.squareup.javapoet.TypeSpec.Builder) ClassName(com.squareup.javapoet.ClassName) JavaFile(com.squareup.javapoet.JavaFile) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet) DeclaredType(javax.lang.model.type.DeclaredType) TypeSpec(com.squareup.javapoet.TypeSpec)

Example 63 with JavaFile

use of com.squareup.javapoet.JavaFile in project tiger by google.

the class TailChaser method chase.

public void chase() {
    TypeSpec.Builder builder = TypeSpec.classBuilder("Tail" + round++).addModifiers(Modifier.PUBLIC).addAnnotation(Tail.class);
    JavaFile javaFile = JavaFile.builder("tiger", builder.build()).build();
    try {
        javaFile.writeTo(filer);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Also used : JavaFile(com.squareup.javapoet.JavaFile) IOException(java.io.IOException) TypeSpec(com.squareup.javapoet.TypeSpec)

Example 64 with JavaFile

use of com.squareup.javapoet.JavaFile in project tiger by google.

the class Tiger3ProcessorForComponent method handleHub.

@Override
protected void handleHub() {
    prepairForHubInjectorGeneration();
    generateHubInjectors(allEitherComponents, componentToParentMap);
    JavaFile javaFile = JavaFile.builder("tiger", debugBuilder.build()).build();
    try {
        javaFile.writeTo(processingEnv.getFiler());
    } catch (IOException e) {
        logger.e("write to %s failed: %s", javaFile, e);
    }
}
Also used : JavaFile(com.squareup.javapoet.JavaFile) IOException(java.io.IOException)

Example 65 with JavaFile

use of com.squareup.javapoet.JavaFile in project tiger by google.

the class Tiger4ProcessorForComponent method handleHub.

@Override
protected void handleHub() {
    prepairForHubInjectorGeneration();
    generateHubInjectors(allEitherComponents, componentToParentMap);
    JavaFile javaFile = JavaFile.builder("tiger", debugBuilder.build()).build();
    try {
        javaFile.writeTo(processingEnv.getFiler());
    } catch (IOException e) {
        logger.e("write to %s failed: %s", javaFile, e);
    }
}
Also used : JavaFile(com.squareup.javapoet.JavaFile) IOException(java.io.IOException)

Aggregations

JavaFile (com.squareup.javapoet.JavaFile)68 TypeSpec (com.squareup.javapoet.TypeSpec)43 IOException (java.io.IOException)42 TypeElement (javax.lang.model.element.TypeElement)25 MethodSpec (com.squareup.javapoet.MethodSpec)21 ClassName (com.squareup.javapoet.ClassName)19 Element (javax.lang.model.element.Element)15 ExecutableElement (javax.lang.model.element.ExecutableElement)12 HashMap (java.util.HashMap)10 File (java.io.File)9 HashSet (java.util.HashSet)9 Map (java.util.Map)9 VariableElement (javax.lang.model.element.VariableElement)9 Builder (com.squareup.javapoet.TypeSpec.Builder)8 ArrayList (java.util.ArrayList)8 ProcessorException (com.github.mvp4g.mvp4g2.processor.ProcessorException)6 PackageElement (javax.lang.model.element.PackageElement)6 DeclaredType (javax.lang.model.type.DeclaredType)6 TypeMirror (javax.lang.model.type.TypeMirror)6 CodeBlock (com.squareup.javapoet.CodeBlock)5