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. <<<");
}
}
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 + " <<<");
}
}
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;
}
};
}
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();
}
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);
}
Aggregations