Search in sources :

Example 11 with Element

use of javax.lang.model.element.Element in project epoxy by airbnb.

the class ProcessorUtils method isSubtypeOfType.

static boolean isSubtypeOfType(TypeMirror typeMirror, String otherType) {
    if (otherType.equals(typeMirror.toString())) {
        return true;
    }
    if (typeMirror.getKind() != TypeKind.DECLARED) {
        return false;
    }
    DeclaredType declaredType = (DeclaredType) typeMirror;
    List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
    if (typeArguments.size() > 0) {
        StringBuilder typeString = new StringBuilder(declaredType.asElement().toString());
        typeString.append('<');
        for (int i = 0; i < typeArguments.size(); i++) {
            if (i > 0) {
                typeString.append(',');
            }
            typeString.append('?');
        }
        typeString.append('>');
        if (typeString.toString().equals(otherType)) {
            return true;
        }
    }
    Element element = declaredType.asElement();
    if (!(element instanceof TypeElement)) {
        return false;
    }
    TypeElement typeElement = (TypeElement) element;
    TypeMirror superType = typeElement.getSuperclass();
    if (isSubtypeOfType(superType, otherType)) {
        return true;
    }
    for (TypeMirror interfaceType : typeElement.getInterfaces()) {
        if (isSubtypeOfType(interfaceType, otherType)) {
            return true;
        }
    }
    return false;
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableElement(javax.lang.model.element.VariableElement) Element(javax.lang.model.element.Element) TypeElement(javax.lang.model.element.TypeElement) DeclaredType(javax.lang.model.type.DeclaredType)

Example 12 with Element

use of javax.lang.model.element.Element in project epoxy by airbnb.

the class ResourceProcessor method processorResources.

void processorResources(RoundEnvironment env) {
    resources.clear();
    if (trees == null) {
        return;
    }
    RClassScanner scanner = new RClassScanner();
    for (Class<? extends Annotation> annotation : EpoxyProcessor.getSupportedAnnotations()) {
        for (Element element : env.getElementsAnnotatedWith(annotation)) {
            JCTree tree = (JCTree) trees.getTree(element, getMirror(element, annotation));
            if (tree != null) {
                // tree can be null if the references are compiled types and not source
                tree.accept(scanner);
            }
        }
    }
    for (String rClass : scanner.getRClasses()) {
        parseRClass(rClass, resources);
    }
}
Also used : VariableElement(javax.lang.model.element.VariableElement) Element(javax.lang.model.element.Element) TypeElement(javax.lang.model.element.TypeElement) JCTree(com.sun.tools.javac.tree.JCTree)

Example 13 with Element

use of javax.lang.model.element.Element in project epoxy by airbnb.

the class ConfigManager method processConfigurations.

List<Exception> processConfigurations(RoundEnvironment roundEnv) {
    configurationMap.clear();
    Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(PackageEpoxyConfig.class);
    List<Exception> errors = new ArrayList<>();
    for (Element element : annotatedElements) {
        String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
        if (configurationMap.containsKey(packageName)) {
            errors.add(buildEpoxyException("Only one Epoxy configuration annotation is allowed per package (%s)", packageName));
        }
        PackageEpoxyConfig annotation = element.getAnnotation(PackageEpoxyConfig.class);
        configurationMap.put(packageName, PackageConfigSettings.create(annotation));
    }
    return errors;
}
Also used : Element(javax.lang.model.element.Element) TypeElement(javax.lang.model.element.TypeElement) ArrayList(java.util.ArrayList) ProcessorUtils.buildEpoxyException(com.airbnb.epoxy.ProcessorUtils.buildEpoxyException)

Example 14 with Element

use of javax.lang.model.element.Element 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 15 with Element

use of javax.lang.model.element.Element 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)

Aggregations

Element (javax.lang.model.element.Element)286 TypeElement (javax.lang.model.element.TypeElement)227 ExecutableElement (javax.lang.model.element.ExecutableElement)148 VariableElement (javax.lang.model.element.VariableElement)96 TypeMirror (javax.lang.model.type.TypeMirror)68 PackageElement (javax.lang.model.element.PackageElement)48 ArrayList (java.util.ArrayList)39 DeclaredType (javax.lang.model.type.DeclaredType)30 IOException (java.io.IOException)29 Map (java.util.Map)26 HashSet (java.util.HashSet)23 LinkedHashSet (java.util.LinkedHashSet)22 List (java.util.List)22 Set (java.util.Set)22 Test (org.junit.Test)21 ElementKind (javax.lang.model.element.ElementKind)20 AnnotationMirror (javax.lang.model.element.AnnotationMirror)19 Elements (javax.lang.model.util.Elements)18 HashMap (java.util.HashMap)16 LinkedHashMap (java.util.LinkedHashMap)15