Search in sources :

Example 71 with ExecutableElement

use of javax.lang.model.element.ExecutableElement in project tiger by google.

the class NewInjectorGenerator method generateTopLevelInjectors.

private void generateTopLevelInjectors() {
    SetMultimap<NewBindingKey, ClassName> keyToPackagedInjectorMap = Utils.reverseSetMultimap(generatedBindingsForPackagedInjector);
    // messager.printMessage(Kind.NOTE,
    // "generatedBindingsForPackagedInjector: " + generatedBindingsForPackagedInjector);
    // messager.printMessage(Kind.NOTE, "keyToPackagedInjectorMap: " + keyToPackagedInjectorMap);
    Set<ClassName> topLevelInjectedClassNames = new HashSet<>();
    for (ComponentInfo component : orderedComponents) {
        TypeSpec.Builder injectorBuilder = TypeSpec.classBuilder(getTopLevelInjectorName(component)).addAnnotation(AnnotationSpec.builder(Generated.class).addMember("value", "$S", GENERATOR_NAME).build()).addModifiers(Modifier.PUBLIC);
        // Member injector interfaces.
        for (TypeElement injector : memberInjectors.get(component)) {
            injectorBuilder.addSuperinterface(TypeName.get(injector.asType()));
        }
        MethodSpec.Builder ctorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
        // Containing top level injector.
        String containingInjectorName = "containingInjector";
        if (componentTree.get(component) != null) {
            ClassName containingInjectorClassName = ClassName.get(topLevelPackageString, getTopLevelInjectorName(componentTree.get(component)));
            injectorBuilder.addField(containingInjectorClassName, containingInjectorName, Modifier.PRIVATE);
            ctorBuilder.addParameter(containingInjectorClassName, containingInjectorName).addStatement("this.$L = $L", containingInjectorName, containingInjectorName);
        }
        // Passed modules.
        Set<TypeElement> allPassedModules = new HashSet<>();
        allPassedModules.addAll(nonNullaryCtorModules.get(component));
        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(memberInjectors.get(component));
        while (!allMembersInjectors.isEmpty()) {
            TypeElement injector = Iterables.getFirst(allMembersInjectors, null);
            Preconditions.checkNotNull(injector, String.format("Empty allMembersInjector."));
            allMembersInjectors.remove(injector);
            for (TypeMirror parentInterface : injector.getInterfaces()) {
                allMembersInjectors.add((TypeElement) ((DeclaredType) parentInterface).asElement());
            }
            for (Element element : injector.getEnclosedElements()) {
                if (!element.getKind().equals(ElementKind.METHOD)) {
                    continue;
                }
                // Injection methods.
                if (Utils.isInjectionMethod(element)) {
                    ExecutableElement method = (ExecutableElement) element;
                    TypeMirror typeMirror = Iterables.getOnlyElement(method.getParameters()).asType();
                    if (typeMirror.getKind().equals(TypeKind.TYPEVAR)) {
                        // TODO(freeman): support generic injection method.
                        continue;
                    }
                    TypeElement cls = (TypeElement) ((DeclaredType) typeMirror).asElement();
                    if (!topLevelInjectedClassNames.add(ClassName.get(cls))) {
                        continue;
                    }
                    ClassName packagedInjectorClassName = getPackagedInjectorNameOfScope(Utils.getPackageString(cls), component.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.isProvisionMethodInInjector(element)) {
                    // non-injection methods, provision methods or getSubComponent method in
                    // editors. NOTE(freeman): subcomponent should be converted to component.
                    ExecutableElement method = (ExecutableElement) element;
                    if (!miscMethodNames.add(method.getSimpleName().toString())) {
                        continue;
                    }
                    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getSimpleName().toString()).addModifiers(Modifier.PUBLIC).returns(TypeName.get(method.getReturnType()));
                    NewBindingKey providedKey = Utils.getKeyProvidedByMethod(method);
                    ClassName packagedInjectorClassName = null;
                    for (ClassName className : keyToPackagedInjectorMap.get(providedKey)) {
                        if (isInjectorOfScope(className, component.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), getProvisionMethodName(providedKey));
                    }
                    // System.out.println("provision method added: " + methodBuilder.build());
                    injectorBuilder.addMethod(methodBuilder.build());
                } else {
                    messager.printMessage(Kind.WARNING, String.format("Element %s ignored from injector %s.", element, injector));
                }
            }
        }
        // Methods to get injectors.
        for (Map.Entry<ClassName, TypeSpec.Builder> entry : packagedInjectorBuilders.entrySet()) {
            ClassName injectorClassName = entry.getKey();
            if (!component.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(component) != null) {
                ClassName containingPackageInjectorClassName = getInjectorNameOfScope(injectorClassName, componentTree.get(component).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());
        }
        generateInjectorBuilder(component, injectorBuilder);
        JavaFile javaFile = JavaFile.builder(topLevelPackageString, injectorBuilder.build()).build();
        try {
            javaFile.writeTo(processingEnv.getFiler());
        } catch (IOException e) {
            Throwables.propagate(e);
        }
    }
}
Also used : PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) 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) HashSet(java.util.HashSet) MethodSpec(com.squareup.javapoet.MethodSpec) TypeElement(javax.lang.model.element.TypeElement) IOException(java.io.IOException) JavaFile(com.squareup.javapoet.JavaFile) HashMap(java.util.HashMap) Map(java.util.Map) TypeSpec(com.squareup.javapoet.TypeSpec) DeclaredType(javax.lang.model.type.DeclaredType)

Example 72 with ExecutableElement

use of javax.lang.model.element.ExecutableElement in project tiger by google.

the class NewInjectorGenerator method generateAll.

private void generateAll() {
    for (ComponentInfo component : orderedComponents) {
        Set<ClassName> injected = new HashSet<>();
        Set<TypeElement> allMembersInjectors = Sets.newHashSet(memberInjectors.get(component));
        while (!allMembersInjectors.isEmpty()) {
            TypeElement injector = Iterables.getFirst(allMembersInjectors, null);
            Preconditions.checkNotNull(injector, String.format("Empty allMembersInjector."));
            allMembersInjectors.remove(injector);
            for (TypeMirror parentInterface : injector.getInterfaces()) {
                allMembersInjectors.add((TypeElement) ((DeclaredType) parentInterface).asElement());
            }
            for (Element method : injector.getEnclosedElements()) {
                if (Utils.isInjectionMethod(method)) {
                    VariableElement var = Iterables.getOnlyElement(((ExecutableElement) method).getParameters());
                    if (var.asType().getKind().equals(TypeKind.TYPEVAR)) {
                        // TODO(freeman): support generic injection method.
                        continue;
                    }
                    TypeElement varTypeElement = (TypeElement) ((DeclaredType) var.asType()).asElement();
                    if (!injected.add(ClassName.get(varTypeElement))) {
                        continue;
                    }
                    generateInjectionMethod(varTypeElement, component.getScope());
                } else if (Utils.isProvisionMethodInInjector(method)) {
                    generateProvisionMethodIfNeeded(Utils.getKeyProvidedByMethod((ExecutableElement) method), injector);
                } else {
                    messager.printMessage(Kind.WARNING, String.format("Unknown element %s from injector %s.", method, injector));
                }
            }
        }
    }
    for (ComponentInfo component : orderedComponents) {
        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);
        }
    }
    for (ComponentInfo component : orderedComponents) {
        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);
        }
    }
    generateTopLevelInjectors();
}
Also used : TypeElement(javax.lang.model.element.TypeElement) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) Builder(com.squareup.javapoet.TypeSpec.Builder) VariableElement(javax.lang.model.element.VariableElement) IOException(java.io.IOException) TypeMirror(javax.lang.model.type.TypeMirror) Builder(com.squareup.javapoet.TypeSpec.Builder) ClassName(com.squareup.javapoet.ClassName) JavaFile(com.squareup.javapoet.JavaFile) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet) DeclaredType(javax.lang.model.type.DeclaredType) TypeSpec(com.squareup.javapoet.TypeSpec)

Example 73 with ExecutableElement

use of javax.lang.model.element.ExecutableElement in project tiger by google.

the class NewDependencyCollector method collectFromInjectedMembersRecursively.

/**
   * Collects dependencies of the give {@link TypeElement} from the injected
   * members, either fields or methods, of the {@link TypeElement}.
   */
private Set<NewBindingKey> collectFromInjectedMembersRecursively(TypeElement classElement) {
    Preconditions.checkArgument(Utils.findInjectedCtor(classElement, env) == null, String.format("class %s should not have injected ctor", classElement));
    Set<NewBindingKey> dependencies = new HashSet<>();
    TypeMirror superMirror = classElement.getSuperclass();
    if (!superMirror.getKind().equals(TypeKind.NONE)) {
        TypeElement parent = (TypeElement) ((DeclaredType) superMirror).asElement();
        dependencies = collectFromInjectedMembersRecursively(parent);
    }
    for (Element element : classElement.getEnclosedElements()) {
        if (element.getKind().equals(ElementKind.FIELD) && Utils.isInjected(element, env)) {
            dependencies.add(NewBindingKey.get(element.asType(), Utils.getQualifier(element)));
        }
        if (element.getKind().equals(ElementKind.METHOD) && Utils.isInjected(element, env)) {
            dependencies.addAll(getDependenciesFrom((ExecutableElement) element));
        }
    }
    return dependencies;
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) HashSet(java.util.HashSet)

Example 74 with ExecutableElement

use of javax.lang.model.element.ExecutableElement in project tiger by google.

the class NewDependencyCollector method collectFromModule.

/**
   * Collects dependencies from a given {@link dagger.Module}. Type.SET and
   * Type.SET_VALUES are put together with Key.get(Set<elementType>, annotation)
   * for easier later processing.
   */
private Collection<NewDependencyInfo> collectFromModule(TypeElement module) {
    Collection<NewDependencyInfo> result = new HashSet<>();
    for (Element e : module.getEnclosedElements()) {
        if (!Utils.isProvidesMethod(e, env)) {
            continue;
        }
        ExecutableElement executableElement = (ExecutableElement) e;
        TypeMirror returnType = executableElement.getReturnType();
        TypeKind returnTypeKind = returnType.getKind();
        Preconditions.checkState(returnTypeKind.isPrimitive() || returnTypeKind.equals(TypeKind.DECLARED) || returnTypeKind.equals(TypeKind.ARRAY), String.format("Unexpected type %s from method %s in module %s.", returnTypeKind, executableElement, module));
        if (!Utils.isBindableType(returnType)) {
            errors.add(String.format("Unbindable type found: %s from module %s by method %s", returnType, module, executableElement));
        }
        AnnotationMirror annotation = Utils.getQualifier(executableElement);
        NewBindingKey key = NewBindingKey.get(returnType, annotation);
        List<NewBindingKey> keys = Utils.getDependenciesFromExecutableElement(executableElement);
        Provides.Type provideType = Utils.getProvidesType(executableElement);
        if (Provides.Type.SET.equals(provideType)) {
            key = NewBindingKey.get(ParameterizedTypeName.get(ClassName.get(Set.class), key.getTypeName()), annotation);
        } else if (Provides.Type.MAP.equals(provideType)) {
            AnnotationMirror mapKeyedMirror = Preconditions.checkNotNull(Utils.getMapKey(executableElement), String.format("Map binding %s missed MapKey.", executableElement));
            AnnotationMirror mapKeyMirror = Utils.getAnnotationMirror(mapKeyedMirror.getAnnotationType().asElement(), MapKey.class);
            AnnotationValue unwrapValue = Utils.getAnnotationValue(mapKeyMirror, "unwrapValue");
            if (unwrapValue != null && !((Boolean) unwrapValue.getValue())) {
                messager.printMessage(Kind.ERROR, String.format("MapKey with unwrapValue false is not supported, yet. Biding: %s", executableElement));
            }
            TypeMirror keyTypeMirror = Preconditions.checkNotNull(Utils.getElementTypeMirror(mapKeyedMirror, "value"), String.format("Get key type failed for binding %s", executableElement));
            TypeMirror valueTypeMirror = executableElement.getReturnType();
            AnnotationMirror qualifier = Utils.getQualifier(executableElement);
            key = NewBindingKey.get(ParameterizedTypeName.get(ClassName.get(Map.class), TypeName.get(keyTypeMirror), TypeName.get(valueTypeMirror)), qualifier);
        }
        NewDependencyInfo newDependencyInfo = new NewDependencyInfo(key, Sets.newHashSet(keys), module, executableElement, provideType);
        result.add(newDependencyInfo);
    }
    //    messager.printMessage(Kind.NOTE, String.format("collectFromModule: result: %s", result));
    return result;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeKind(javax.lang.model.type.TypeKind) Provides(dagger.Provides) AnnotationMirror(javax.lang.model.element.AnnotationMirror) MapKey(dagger.MapKey) TypeMirror(javax.lang.model.type.TypeMirror) AnnotationValue(javax.lang.model.element.AnnotationValue) HashSet(java.util.HashSet)

Example 75 with ExecutableElement

use of javax.lang.model.element.ExecutableElement in project j2objc by google.

the class ElementReferenceMapper method endVisit.

//TODO(malvania): Add the field type class to reference classes.
//Currently, jdt only supports well known types. Soon, we can get type mirror from field 
//and resolve the type by its name using a resolve method in the parser environment.
@Override
public void endVisit(VariableDeclarationFragment fragment) {
    //TODO(malvania): Add field to elementReferenceMap when field detection is enabled and the
    //  ElementUtil.getBinaryName() method doesn't break when called on a static block's
    //  ExecutableElement.
    //String fieldID = stitchFieldIdentifier(fragment);
    //elementReferenceMap.putIfAbsent(fieldID, new FieldReferenceNode(fragment));
    Element element = fragment.getVariableElement().getEnclosingElement();
    if (element instanceof TypeElement) {
        TypeElement type = (TypeElement) element;
        if (ElementUtil.isPublic(fragment.getVariableElement())) {
            ClassReferenceNode node = (ClassReferenceNode) elementReferenceMap.get(stitchClassIdentifier(type));
            if (node == null) {
                node = new ClassReferenceNode(type);
            }
            node.containsPublicField = true;
            elementReferenceMap.putIfAbsent(stitchClassIdentifier(type), node);
        }
    }
}
Also used : TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) TypeElement(javax.lang.model.element.TypeElement)

Aggregations

ExecutableElement (javax.lang.model.element.ExecutableElement)345 TypeElement (javax.lang.model.element.TypeElement)158 TypeMirror (javax.lang.model.type.TypeMirror)97 VariableElement (javax.lang.model.element.VariableElement)85 Element (javax.lang.model.element.Element)72 Test (org.junit.Test)41 GeneratedExecutableElement (com.google.devtools.j2objc.types.GeneratedExecutableElement)32 DeclaredType (javax.lang.model.type.DeclaredType)31 ArrayList (java.util.ArrayList)26 JBlock (com.helger.jcodemodel.JBlock)25 JInvocation (com.helger.jcodemodel.JInvocation)20 MethodDeclaration (com.google.devtools.j2objc.ast.MethodDeclaration)18 JVar (com.helger.jcodemodel.JVar)18 Map (java.util.Map)18 HashSet (java.util.HashSet)17 IJExpression (com.helger.jcodemodel.IJExpression)16 ElementValidation (org.androidannotations.ElementValidation)15 Block (com.google.devtools.j2objc.ast.Block)13 JMethod (com.helger.jcodemodel.JMethod)13 Elements (javax.lang.model.util.Elements)13