Search in sources :

Example 16 with TypeMirror

use of javax.lang.model.type.TypeMirror in project ARouter by alibaba.

the class AutowiredProcessor method generateHelper.

private void generateHelper() throws IOException, IllegalAccessException {
    TypeElement type_ISyringe = elements.getTypeElement(ISYRINGE);
    TypeMirror iProvider = elements.getTypeElement(Consts.IPROVIDER).asType();
    TypeMirror activityTm = elements.getTypeElement(Consts.ACTIVITY).asType();
    TypeMirror fragmentTm = elements.getTypeElement(Consts.FRAGMENT).asType();
    TypeMirror fragmentTmV4 = elements.getTypeElement(Consts.FRAGMENT_V4).asType();
    // Build input param name.
    ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();
    if (MapUtils.isNotEmpty(parentAndChild)) {
        for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {
            // Build method : 'inject'
            MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT).addAnnotation(Override.class).addModifiers(PUBLIC).addParameter(objectParamSpec);
            TypeElement parent = entry.getKey();
            List<Element> childs = entry.getValue();
            String qualifiedName = parent.getQualifiedName().toString();
            String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
            String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;
            logger.info(">>> Start process " + childs.size() + " field in " + parent.getSimpleName() + " ... <<<");
            injectMethodBuilder.addStatement("$T substitute = ($T)target", ClassName.get(parent), ClassName.get(parent));
            // Generate method body, start inject.
            for (Element element : childs) {
                Autowired fieldConfig = element.getAnnotation(Autowired.class);
                String fieldName = element.getSimpleName().toString();
                if (types.isSubtype(element.asType(), iProvider)) {
                    // It's provider
                    if ("".equals(fieldConfig.name())) {
                        // User has not set service path, then use byType.
                        // Getter
                        injectMethodBuilder.addStatement("substitute." + fieldName + " = $T.getInstance().navigation($T.class)", ARouterClass, ClassName.get(element.asType()));
                    } else {
                        // use byName
                        // Getter
                        injectMethodBuilder.addStatement("substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation();", ClassName.get(element.asType()), ARouterClass, fieldConfig.name());
                    }
                    // Validater
                    if (fieldConfig.required()) {
                        injectMethodBuilder.beginControlFlow("if (substitute." + fieldName + " == null)");
                        injectMethodBuilder.addStatement("throw new RuntimeException(\"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", ClassName.get(parent));
                        injectMethodBuilder.endControlFlow();
                    }
                } else {
                    // It's normal intent value
                    String statment = "substitute." + fieldName + " = substitute.";
                    boolean isActivity = false;
                    if (types.isSubtype(parent.asType(), activityTm)) {
                        // Activity, then use getIntent()
                        isActivity = true;
                        statment += "getIntent().";
                    } else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) {
                        // Fragment, then use getArguments()
                        statment += "getArguments().";
                    } else {
                        throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!");
                    }
                    statment = buildStatement(statment, typeUtils.typeExchange(element), isActivity);
                    if (statment.startsWith("$T.")) {
                        // Not mortals
                        injectMethodBuilder.addStatement("substitute." + fieldName + " = " + statment, JsonClass, (StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()), ClassName.get(element.asType()));
                    } else {
                        injectMethodBuilder.addStatement(statment, StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name());
                    }
                    // Validater
                    if (fieldConfig.required() && !element.asType().getKind().isPrimitive()) {
                        // Primitive wont be check.
                        injectMethodBuilder.beginControlFlow("if (substitute." + fieldName + " == null)");
                        injectMethodBuilder.addStatement("throw new RuntimeException(\"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", ClassName.get(parent));
                        injectMethodBuilder.endControlFlow();
                    }
                }
            }
            // Generate autowired helper
            JavaFile.builder(packageName, TypeSpec.classBuilder(fileName).addJavadoc(WARNING_TIPS).addSuperinterface(ClassName.get(type_ISyringe)).addModifiers(PUBLIC).addMethod(injectMethodBuilder.build()).build()).build().writeTo(mFiler);
            logger.info(">>> " + parent.getSimpleName() + " has been processed, " + fileName + " has been generated. <<<");
        }
        logger.info(">>> Autowired processor stop. <<<");
    }
}
Also used : ParameterSpec(com.squareup.javapoet.ParameterSpec) MethodSpec(com.squareup.javapoet.MethodSpec) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) Autowired(com.alibaba.android.arouter.facade.annotation.Autowired) TypeMirror(javax.lang.model.type.TypeMirror) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map)

Example 17 with TypeMirror

use of javax.lang.model.type.TypeMirror in project ARouter by alibaba.

the class RouteProcessor method parseRoutes.

private void parseRoutes(Set<? extends Element> routeElements) throws IOException {
    if (CollectionUtils.isNotEmpty(routeElements)) {
        // Perpare the type an so on.
        logger.info(">>> Found routes, size is " + routeElements.size() + " <<<");
        rootMap.clear();
        TypeMirror type_Activity = elements.getTypeElement(ACTIVITY).asType();
        TypeMirror type_Service = elements.getTypeElement(SERVICE).asType();
        TypeElement type_Parcelable = elements.getTypeElement(PARCELABLE);
        // Interface of ARouter
        TypeElement type_IRouteGroup = elements.getTypeElement(IROUTE_GROUP);
        TypeElement type_IProviderGroup = elements.getTypeElement(IPROVIDER_GROUP);
        ClassName routeMetaCn = ClassName.get(RouteMeta.class);
        ClassName routeTypeCn = ClassName.get(RouteType.class);
        /*
               Build input type, format as :

               ```Map<String, Class<? extends IRouteGroup>>```
             */
        ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), ParameterizedTypeName.get(ClassName.get(Class.class), WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup))));
        /*

              ```Map<String, RouteMeta>```
             */
        ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), ClassName.get(RouteMeta.class));
        /*
              Build input param name.
             */
        ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
        ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
        // Ps. its param type same as groupParamSpec!
        ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();
        /*
              Build method : 'loadInto'
             */
        MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO).addAnnotation(Override.class).addModifiers(PUBLIC).addParameter(rootParamSpec);
        //  Follow a sequence, find out metas of group first, generate java file, then statistics them as root.
        for (Element element : routeElements) {
            TypeMirror tm = element.asType();
            Route route = element.getAnnotation(Route.class);
            RouteMeta routeMete = null;
            if (types.isSubtype(tm, type_Activity)) {
                // Activity
                logger.info(">>> Found activity route: " + tm.toString() + " <<<");
                // Get all fields annotation by @Autowired
                Map<String, Integer> paramsType = new HashMap<>();
                for (Element field : element.getEnclosedElements()) {
                    if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) {
                        // It must be field, then it has annotation, but it not be provider.
                        Autowired paramConfig = field.getAnnotation(Autowired.class);
                        paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field));
                    }
                }
                routeMete = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
            } else if (types.isSubtype(tm, iProvider)) {
                // IProvider
                logger.info(">>> Found provider route: " + tm.toString() + " <<<");
                routeMete = new RouteMeta(route, element, RouteType.PROVIDER, null);
            } else if (types.isSubtype(tm, type_Service)) {
                // Service
                logger.info(">>> Found service route: " + tm.toString() + " <<<");
                routeMete = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
            }
            categories(routeMete);
        // if (StringUtils.isEmpty(moduleName)) {   // Hasn't generate the module name.
        //     moduleName = ModuleUtils.generateModuleName(element, logger);
        // }
        }
        MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO).addAnnotation(Override.class).addModifiers(PUBLIC).addParameter(providerParamSpec);
        // Start generate java source, structure is divided into upper and lower levels, used for demand initialization.
        for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {
            String groupName = entry.getKey();
            MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO).addAnnotation(Override.class).addModifiers(PUBLIC).addParameter(groupParamSpec);
            // Build group method body
            Set<RouteMeta> groupData = entry.getValue();
            for (RouteMeta routeMeta : groupData) {
                switch(routeMeta.getType()) {
                    case // Need cache provider's super class
                    PROVIDER:
                        List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
                        for (TypeMirror tm : interfaces) {
                            if (types.isSubtype(tm, iProvider)) {
                                // This interface extend the IProvider, so it can be used for mark provider
                                loadIntoMethodOfProviderBuilder.addStatement("providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))", // Spite unuseless name
                                tm.toString().substring(tm.toString().lastIndexOf(".") + 1), routeMetaCn, routeTypeCn, ClassName.get((TypeElement) routeMeta.getRawType()), routeMeta.getPath(), routeMeta.getGroup());
                            }
                        }
                        break;
                    default:
                        break;
                }
                // Make map body for paramsType
                StringBuilder mapBodyBuilder = new StringBuilder();
                Map<String, Integer> paramsType = routeMeta.getParamsType();
                if (MapUtils.isNotEmpty(paramsType)) {
                    for (Map.Entry<String, Integer> types : paramsType.entrySet()) {
                        mapBodyBuilder.append("put(\"").append(types.getKey()).append("\", ").append(types.getValue()).append("); ");
                    }
                }
                String mapBody = mapBodyBuilder.toString();
                loadIntoMethodOfGroupBuilder.addStatement("atlas.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, " + (StringUtils.isEmpty(mapBody) ? null : ("new java.util.HashMap<String, Integer>(){{" + mapBodyBuilder.toString() + "}}")) + ", " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))", routeMeta.getPath(), routeMetaCn, routeTypeCn, ClassName.get((TypeElement) routeMeta.getRawType()), routeMeta.getPath().toLowerCase(), routeMeta.getGroup().toLowerCase());
            }
            // Generate groups
            String groupFileName = NAME_OF_GROUP + groupName;
            JavaFile.builder(PACKAGE_OF_GENERATE_FILE, TypeSpec.classBuilder(groupFileName).addJavadoc(WARNING_TIPS).addSuperinterface(ClassName.get(type_IRouteGroup)).addModifiers(PUBLIC).addMethod(loadIntoMethodOfGroupBuilder.build()).build()).build().writeTo(mFiler);
            logger.info(">>> Generated group: " + groupName + "<<<");
            rootMap.put(groupName, groupFileName);
        }
        if (MapUtils.isNotEmpty(rootMap)) {
            // Generate root meta by group name, it must be generated before root, then I can findout the class of group.
            for (Map.Entry<String, String> entry : rootMap.entrySet()) {
                loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
            }
        }
        // Wirte provider into disk
        String providerMapFileName = NAME_OF_PROVIDER + SEPARATOR + moduleName;
        JavaFile.builder(PACKAGE_OF_GENERATE_FILE, TypeSpec.classBuilder(providerMapFileName).addJavadoc(WARNING_TIPS).addSuperinterface(ClassName.get(type_IProviderGroup)).addModifiers(PUBLIC).addMethod(loadIntoMethodOfProviderBuilder.build()).build()).build().writeTo(mFiler);
        logger.info(">>> Generated provider map, name is " + providerMapFileName + " <<<");
        // Write root meta into disk.
        String rootFileName = NAME_OF_ROOT + SEPARATOR + moduleName;
        JavaFile.builder(PACKAGE_OF_GENERATE_FILE, TypeSpec.classBuilder(rootFileName).addJavadoc(WARNING_TIPS).addSuperinterface(ClassName.get(elements.getTypeElement(ITROUTE_ROOT))).addModifiers(PUBLIC).addMethod(loadIntoMethodOfRootBuilder.build()).build()).build().writeTo(mFiler);
        logger.info(">>> Generated root, name is " + rootFileName + " <<<");
    }
}
Also used : RouteMeta(com.alibaba.android.arouter.facade.model.RouteMeta) Set(java.util.Set) TreeSet(java.util.TreeSet) ParameterSpec(com.squareup.javapoet.ParameterSpec) MethodSpec(com.squareup.javapoet.MethodSpec) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) Autowired(com.alibaba.android.arouter.facade.annotation.Autowired) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(com.squareup.javapoet.ClassName) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) Route(com.alibaba.android.arouter.facade.annotation.Route) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName)

Example 18 with TypeMirror

use of javax.lang.model.type.TypeMirror in project immutables by immutables.

the class SourceOrdering method getAllAccessorsProvider.

/**
   * While we have {@link SourceOrdering}, there's still a problem: We have inheritance hierarchy
   * and
   * we want to have all defined or inherited accessors returned as members of target type, like
   * {@link Elements#getAllMembers(TypeElement)}, but we need to have them properly and stably
   * sorted.
   * This implementation doesn't try to correctly resolve order for accessors inherited from
   * different supertypes(interfaces), just something that stable and reasonable wrt source ordering
   * without handling complex cases.
   * @param elements the elements utility
   * @param types the types utility
   * @param type the type to traverse
   * @return provider of all accessors in source order and mapping
   */
public static AccessorProvider getAllAccessorsProvider(final Elements elements, final Types types, final TypeElement type) {
    class CollectedOrdering extends Ordering<Element> {

        class Intratype {

            Ordering<String> ordering;

            int rank;
        }

        final Map<String, Intratype> accessorOrderings = Maps.newLinkedHashMap();

        final List<TypeElement> linearizedTypes = Lists.newArrayList();

        final Predicate<String> accessorNotYetInOrderings = Predicates.not(Predicates.in(accessorOrderings.keySet()));

        final ArrayListMultimap<String, TypeElement> accessorMapping = ArrayListMultimap.create();

        CollectedOrdering() {
            traverse(type);
            traverseObjectForInterface();
        }

        private void traverseObjectForInterface() {
            if (type.getKind() == ElementKind.INTERFACE) {
                traverse(elements.getTypeElement(Object.class.getName()));
            }
        }

        void traverse(@Nullable TypeElement element) {
            if (element == null || isJavaLangObject(element)) {
                return;
            }
            collectEnclosing(element);
            traverse(asTypeElement(element.getSuperclass()));
            for (TypeMirror implementedInterface : element.getInterfaces()) {
                traverse(asTypeElement(implementedInterface));
            }
        }

        @Nullable
        TypeElement asTypeElement(TypeMirror type) {
            if (type.getKind() == TypeKind.DECLARED) {
                return (TypeElement) ((DeclaredType) type).asElement();
            }
            return null;
        }

        void collectEnclosing(TypeElement type) {
            FluentIterable<String> accessorsInType = FluentIterable.from(SourceOrdering.getEnclosedElements(type)).filter(IsParameterlessNonstaticNonobject.PREDICATE).transform(ToSimpleName.FUNCTION);
            for (String accessor : accessorsInType) {
                accessorMapping.put(accessor, type);
            }
            List<String> accessors = accessorsInType.filter(accessorNotYetInOrderings).toList();
            Intratype intratype = new Intratype();
            intratype.rank = linearizedTypes.size();
            intratype.ordering = Ordering.explicit(accessors);
            for (String name : accessors) {
                accessorOrderings.put(name, intratype);
            }
            linearizedTypes.add(type);
        }

        @Override
        public int compare(Element left, Element right) {
            String leftKey = ToSimpleName.FUNCTION.apply(left);
            String rightKey = ToSimpleName.FUNCTION.apply(right);
            Intratype leftIntratype = accessorOrderings.get(leftKey);
            Intratype rightIntratype = accessorOrderings.get(rightKey);
            if (leftIntratype == null || rightIntratype == null) {
                // FIXME figure out why it happens (null)
                return Boolean.compare(leftIntratype == null, rightIntratype == null);
            }
            return leftIntratype == rightIntratype ? leftIntratype.ordering.compare(leftKey, rightKey) : Integer.compare(leftIntratype.rank, rightIntratype.rank);
        }
    }
    final CollectedOrdering ordering = new CollectedOrdering();
    final ImmutableList<ExecutableElement> sortedList = ordering.immutableSortedCopy(disambiguateMethods(ElementFilter.methodsIn(elements.getAllMembers(type))));
    return new AccessorProvider() {

        ImmutableListMultimap<String, TypeElement> accessorMapping = ImmutableListMultimap.copyOf(ordering.accessorMapping);

        @Override
        public ImmutableListMultimap<String, TypeElement> accessorMapping() {
            return accessorMapping;
        }

        @Override
        public ImmutableList<ExecutableElement> get() {
            return sortedList;
        }
    };
}
Also used : 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) Predicate(com.google.common.base.Predicate) TypeMirror(javax.lang.model.type.TypeMirror) Ordering(com.google.common.collect.Ordering) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) ArrayListMultimap(com.google.common.collect.ArrayListMultimap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) Nullable(javax.annotation.Nullable)

Example 19 with TypeMirror

use of javax.lang.model.type.TypeMirror in project immutables by immutables.

the class Imports method extractImports.

private ImmutableList<TypeMirror> extractImports(TypeElement type) {
    ImmutableList.Builder<TypeMirror> importedTypes = ImmutableList.builder();
    for (TypeElement t = type; t != null; t = (TypeElement) types.asElement(t.getSuperclass())) {
        importedTypes.addAll(extractDeclaredImports(t).reverse());
        importedTypes.addAll(extractDeclaredImports(elements.getPackageOf(type)).reverse());
    }
    return importedTypes.build().reverse();
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) ImmutableList(com.google.common.collect.ImmutableList) TypeElement(javax.lang.model.element.TypeElement)

Example 20 with TypeMirror

use of javax.lang.model.type.TypeMirror in project immutables by immutables.

the class FactoryMethodAttributesCollector method collect.

void collect() {
    ExecutableElement factoryMethodElement = (ExecutableElement) protoclass.sourceElement();
    Parameterizable element = (Parameterizable) (factoryMethodElement.getKind() == ElementKind.CONSTRUCTOR ? factoryMethodElement.getEnclosingElement() : type.element);
    for (VariableElement parameter : factoryMethodElement.getParameters()) {
        TypeMirror returnType = parameter.asType();
        ValueAttribute attribute = new ValueAttribute();
        attribute.isGenerateAbstract = true;
        attribute.reporter = reporter;
        attribute.returnType = returnType;
        attribute.element = parameter;
        String parameterName = parameter.getSimpleName().toString();
        attribute.names = styles.forAccessorWithRaw(parameterName, parameterName);
        attribute.containingType = type;
        attributes.add(attribute);
    }
    Instantiator encodingInstantiator = protoclass.encodingInstantiator();
    @Nullable InstantiationCreator instantiationCreator = encodingInstantiator.creatorFor(element);
    for (ValueAttribute attribute : attributes) {
        attribute.initAndValidate(instantiationCreator);
    }
    if (instantiationCreator != null) {
        type.additionalImports(instantiationCreator.imports);
    }
    type.attributes.addAll(attributes);
    type.throwing = extractThrowsClause(factoryMethodElement);
}
Also used : InstantiationCreator(org.immutables.value.processor.encode.Instantiator.InstantiationCreator) TypeMirror(javax.lang.model.type.TypeMirror) ExecutableElement(javax.lang.model.element.ExecutableElement) Parameterizable(javax.lang.model.element.Parameterizable) Instantiator(org.immutables.value.processor.encode.Instantiator) VariableElement(javax.lang.model.element.VariableElement) Nullable(javax.annotation.Nullable)

Aggregations

TypeMirror (javax.lang.model.type.TypeMirror)475 TypeElement (javax.lang.model.element.TypeElement)197 ExecutableElement (javax.lang.model.element.ExecutableElement)105 Test (org.junit.Test)90 VariableElement (javax.lang.model.element.VariableElement)88 DeclaredType (javax.lang.model.type.DeclaredType)76 Element (javax.lang.model.element.Element)61 ArrayList (java.util.ArrayList)36 Expression (com.google.devtools.j2objc.ast.Expression)32 PrefixExpression (com.google.devtools.j2objc.ast.PrefixExpression)28 Elements (javax.lang.model.util.Elements)28 FunctionInvocation (com.google.devtools.j2objc.ast.FunctionInvocation)24 AbstractJClass (com.helger.jcodemodel.AbstractJClass)24 List (java.util.List)23 Types (javax.lang.model.util.Types)22 InfixExpression (com.google.devtools.j2objc.ast.InfixExpression)21 TypeParameterElement (javax.lang.model.element.TypeParameterElement)21 ArrayType (javax.lang.model.type.ArrayType)21 FunctionElement (com.google.devtools.j2objc.types.FunctionElement)20 IJExpression (com.helger.jcodemodel.IJExpression)20