use of com.squareup.javapoet.MethodSpec in project arez by arez.
the class TrackedDescriptor method buildTracked.
/**
* Generate the tracked wrapper.
* This is wrapped in case the user ever wants to explicitly call method
*/
@Nonnull
private MethodSpec buildTracked() throws ArezProcessorException {
assert null != _trackedMethod;
assert null != _trackedMethodType;
final MethodSpec.Builder builder = MethodSpec.methodBuilder(_trackedMethod.getSimpleName().toString());
ProcessorUtil.copyAccessModifiers(_trackedMethod, builder);
ProcessorUtil.copyExceptions(_trackedMethodType, builder);
ProcessorUtil.copyTypeParameters(_trackedMethodType, builder);
ProcessorUtil.copyDocumentedAnnotations(_trackedMethod, builder);
builder.addAnnotation(Override.class);
final TypeMirror returnType = _trackedMethodType.getReturnType();
builder.returns(TypeName.get(returnType));
final boolean isProcedure = returnType.getKind() == TypeKind.VOID;
final List<? extends TypeMirror> thrownTypes = _trackedMethod.getThrownTypes();
final boolean isSafe = thrownTypes.isEmpty();
final StringBuilder statement = new StringBuilder();
final ArrayList<Object> parameterNames = new ArrayList<>();
GeneratorUtil.generateNotDisposedInvariant(_componentDescriptor, builder);
if (!isProcedure) {
statement.append("return ");
}
statement.append("$N().");
parameterNames.add(_componentDescriptor.getContextMethodName());
if (isProcedure && isSafe) {
statement.append("safeTrack");
} else if (isProcedure) {
statement.append("track");
} else if (isSafe) {
statement.append("safeTrack");
} else {
statement.append("track");
}
statement.append("( this.$N, ");
parameterNames.add(getFieldName());
statement.append("() -> super.");
statement.append(_trackedMethod.getSimpleName());
statement.append("(");
boolean firstParam = true;
final List<? extends VariableElement> parameters = _trackedMethod.getParameters();
final int paramCount = parameters.size();
for (int i = 0; i < paramCount; i++) {
final VariableElement element = parameters.get(i);
final TypeName parameterType = TypeName.get(_trackedMethodType.getParameterTypes().get(i));
final ParameterSpec.Builder param = ParameterSpec.builder(parameterType, element.getSimpleName().toString(), Modifier.FINAL);
ProcessorUtil.copyDocumentedAnnotations(element, param);
builder.addParameter(param.build());
parameterNames.add(element.getSimpleName().toString());
if (!firstParam) {
statement.append(",");
}
firstParam = false;
statement.append("$N");
}
statement.append(")");
if (_reportParameters) {
for (final VariableElement parameter : parameters) {
parameterNames.add(parameter.getSimpleName().toString());
statement.append(", $N");
}
}
statement.append(" )");
GeneratorUtil.generateTryBlock(builder, thrownTypes, b -> b.addStatement(statement.toString(), parameterNames.toArray()));
return builder.build();
}
use of com.squareup.javapoet.MethodSpec in project ucsFramework by cjsoftware-lib.
the class PreserveUiStateProcessor method addSaveFieldMethod.
private MethodSpec addSaveFieldMethod(TypeName valueOwnerType, DoPreservedField field) {
MethodSpec.Builder saveFieldMethod = MethodSpec.methodBuilder(String.format(METHOD_SAVE_FIELD_NAME_TEMPLATE, field.getField().getSimpleName())).addParameter(valueOwnerType, PARAMETER_FIELD_OWNER_NAME);
Types typeUtils = getProcessorModel().getTypeUtils();
Elements elementUtils = getProcessorModel().getElementUtils();
TypeMirror valueStrategy = elementUtils.getTypeElement(ValuePreservationStrategy.class.getCanonicalName()).asType();
for (TypeMirror strategy : field.getPreservationStrategyList()) {
String fieldName = String.format(FIELD_PRESERVE_STRATEGY_INSTANCE, field.getField().getSimpleName(), typeUtils.asElement(strategy).getSimpleName());
if (implementsInterface(typeUtils, valueStrategy, strategy)) {
saveFieldMethod.addStatement("$N.saveValue($N, $N.$N)", fieldName, PARAMETER_FIELD_OWNER_NAME, PARAMETER_FIELD_OWNER_NAME, field.getField().getSimpleName());
} else {
saveFieldMethod.addStatement("$N.saveState($N, $N.$N)", fieldName, PARAMETER_FIELD_OWNER_NAME, PARAMETER_FIELD_OWNER_NAME, field.getField().getSimpleName());
}
}
return saveFieldMethod.build();
}
use of com.squareup.javapoet.MethodSpec in project ucsFramework by cjsoftware-lib.
the class PreserveUiStateProcessor method addSaveMethod.
private MethodSpec addSaveMethod(TypeName valueOwnerType, List<DoPreservedField> fieldList) {
MethodSpec.Builder saveMethod = MethodSpec.methodBuilder("savePreservedFields").addAnnotation(Override.class).addModifiers(Modifier.PUBLIC).addParameter(ParameterSpec.builder(valueOwnerType, PARAMETER_FIELD_OWNER_NAME).build());
for (DoPreservedField field : fieldList) {
saveMethod.addStatement("$N($N)", String.format(METHOD_SAVE_FIELD_NAME_TEMPLATE, field.getField()), PARAMETER_FIELD_OWNER_NAME);
}
saveMethod.addStatement("$N = true", FIELD_HAVE_STATE);
return saveMethod.build();
}
use of com.squareup.javapoet.MethodSpec in project AndroidLife by CaMnter.
the class RouteProcessor method parseRoutes.
/**
* 处理 @Route 元素
*
* 0. 准备一下生成 ARouter$$Group$$???,ARouter$$Providers$$??? 和 ARouter$$Root$$???
* - java class 需要的 TypeMirror,TypeElement,ClassName,ParameterizedTypeName,ParameterSpec
* - 以及 MethodSpec
*
* 1. 遍历每一个 @Route 元素
* 2. 拿到每一个 @Route 元素 的 TypeMirror
*
* 3.1 判断是否是 Activity 的子类,是的话
* - 3.1.1 获取该 Element 下的所有 子元素,提取出所有 @Autowired 的 子元素
* - 3.1.2 根据 所有 @Autowired 的 子元素,拿到 所有 @Autowired 的 子元素 的 TypeMirror
* - 3.1.3 根据 所有 @Autowired 的 TypeMirror,获取到 所有 @Autowired 的 子元素 的 TypeKind enum 类型
* - 3.1.4 key = @Autowired 的 name,value = TypeKind enum 类型。缓存成一个 HashMap
* - 3.1.5 用该 HashMap 生成一个 RouteType = Activity 的 RouteMeta
* 3.2 判断是否是 IProvider 的子类,是的话,生成一个 RouteType = IProvider 的 RouteMeta
* 3.3 判断是否是 Service 的子类,是的话,生成一个 RouteType = Service 的 RouteMeta
* 3.4 判断是否是 Fragment 的子类,是的话,生成一个 RouteType = Fragment 的 RouteMeta
*
* 4. 将 RouteMeta 归类
*
* 5. 生成 ARouter$$Group$$??? java class 及其中内容
* 6. 生成 ARouter$$Providers$$??? java class 及其中内容
* 7. 生成 ARouter$$Root$$??? java class 及其中内容
*
* @param routeElements Set<? extends Element>
* @throws IOException IOException
*/
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();
/**
* 实例化 android.app.Activity 的 TypeMirror
* 实例化 android.app.Service 的 TypeMirror
* 实例化 android.app.Fragment 的 TypeMirror
* 实例化 android.support.v4.app.Fragment 的 TypeMirror
*/
TypeMirror type_Activity = elements.getTypeElement(ACTIVITY).asType();
TypeMirror type_Service = elements.getTypeElement(SERVICE).asType();
TypeMirror fragmentTm = elements.getTypeElement(FRAGMENT).asType();
TypeMirror fragmentTmV4 = elements.getTypeElement(Consts.FRAGMENT_V4).asType();
/**
* Interface of ARouter
*
* 实例化 IRouteGroup 的 TypeElement
* 实例化 IProviderGroup 的 TypeElement
* 实例化 RouteMeta 的 ClassName
* 实例化 RouteType 的 ClassName
*/
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>>```
*
* ( 用于 ARouter$$Root$$??? )
* @Override
* public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
* 中的参数类型
* 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>```
*
* ( 用于 ARouter$$Group$$??? )
* @Override
* public void loadInto(Map<String, RouteMeta> atlas)
* 中的参数类型
* Map<String, RouteMeta>
*/
ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), ClassName.get(RouteMeta.class));
/**
* Build input param name.
*
* 实例化参数:
*
* Map<String, Class<? extends IRouteGroup>> routes( 用于 ARouter$$Root$$??? )
* Map<String, RouteMeta> atlas( 用于 ARouter$$Group$$??? )
* Map<String, RouteMeta> providers( 用于 ARouter$$Providers$$??? )
*/
ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();
/**
* Build method : 'loadInto'
*
* 整个 loadInto 方法( 用于 ARouter$$Root$$??? )
* @Override
* public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
*/
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.
*
* 1. 遍历每一个 @Route 元素
* 2. 拿到每一个 @Route 元素 的 TypeMirror
*
* 3.1 判断是否是 Activity 的子类,是的话
* - 3.1.1 获取该 Element 下的所有 子元素,提取出所有 @Autowired 的 子元素
* - 3.1.2 根据 所有 @Autowired 的 子元素,拿到 所有 @Autowired 的 子元素 的 TypeMirror
* - 3.1.3 根据 所有 @Autowired 的 TypeMirror,获取到 所有 @Autowired 的 子元素 的 TypeKind enum 类型
* - 3.1.4 key = @Autowired 的 name,value = TypeKind enum 类型。缓存成一个 HashMap
* - 3.1.5 用该 HashMap 生成一个 RouteType = Activity 的 RouteMeta
* 3.2 判断是否是 IProvider 的子类,是的话,生成一个 RouteType = IProvider 的 RouteMeta
* 3.3 判断是否是 Service 的子类,是的话,生成一个 RouteType = Service 的 RouteMeta
* 3.4 判断是否是 Fragment 的子类,是的话,生成一个 RouteType = Fragment 的 RouteMeta
*
* 4. 将 RouteMeta 归类
*
* 5. 生成 ARouter$$Group$$??? java class 及其中内容
* 6. 生成 ARouter$$Providers$$??? java class 及其中内容
* 7. 生成 ARouter$$Root$$??? java class 及其中内容
*/
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);
} else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
logger.info(">>> Found fragment route: " + tm.toString() + " <<<");
routeMete = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null);
}
categories(routeMete);
// if (StringUtils.isEmpty(moduleName)) { // Hasn't generate the module name.
// moduleName = ModuleUtils.generateModuleName(element, logger);
// }
}
/**
* Build method : 'loadInto'
*
* 整个 loadInto 方法( 用于 ARouter$$Providers$$??? )
* @Override
* public void loadInto(Map<String, RouteMeta> providers)
*/
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();
/**
* 整个 loadInto 方法( 用于 ARouter$$Group$$??? )
* @Override
* public void loadInto(Map<String, RouteMeta> atlas)
*/
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()) {
/**
* 在 ARouter$$Providers$$??? # loadInto(Map<String, RouteMeta> providers)
* 添加 缓存语句
* eg:
* providers.put("com.alibaba.android.arouter.demo.testservice.HelloService", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/service/hello", "service", null, -1, -2147483648));
*/
case // Need cache provider's super class
PROVIDER:
List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
for (TypeMirror tm : interfaces) {
if (types.isSameType(tm, iProvider)) {
// Its implements iProvider interface himself.
// 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() + "))", (routeMeta.getRawType()).toString(), routeMetaCn, routeTypeCn, ClassName.get((TypeElement) routeMeta.getRawType()), routeMeta.getPath(), routeMeta.getGroup());
} else 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() + "))", tm.toString(), // So stupid, will duplicate only save class name.
routeMetaCn, routeTypeCn, ClassName.get((TypeElement) routeMeta.getRawType()), routeMeta.getPath(), routeMeta.getGroup());
}
}
break;
default:
break;
}
/**
* Make map body for paramsType
*
* 在 ARouter$$Group$$??? # loadInto(Map<String, RouteMeta> atlas)
* 中的 缓存语句 键值对语句
* eg:
* atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap<String, Integer>(){{put("pac", 9); put("obj", 10); put("name", 8); put("boy", 0); put("age", 3); put("url", 8); }}, -1, -2147483648));
* 键值对语句:
* put("pac", 9); put("obj", 10); put("name", 8); put("boy", 0); put("age", 3); put("url", 8);
*/
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();
/**
* 在 ARouter$$Group$$??? # loadInto(Map<String, RouteMeta> atlas)
* 添加 缓存语句
* eg:
* atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap<String, Integer>(){{put("pac", 9); put("obj", 10); put("name", 8); put("boy", 0); put("age", 3); put("url", 8); }}, -1, -2147483648));
*/
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
*
* 生成 java class
* public class ARouter$$Group$$??? implements IRouteGroup
*/
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);
}
/**
* 在 ARouter$$Root$$??? # (Map<String, Class<? extends IRouteGroup>> routes)
* 添加 缓存语句
* eg:
* routes.put("service", ARouter$$Group$$service.class);
*/
if (MapUtils.isNotEmpty(rootMap)) {
// Generate root meta by group name, it must be generated before root, then I can find out 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()));
}
}
/**
* Write provider into disk
*
* 生成 java class
* public class ARouter$$Providers$$??? implements IProviderGroup
*/
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 provider into disk
*
* 生成 java class
* public class ARouter$$Root$$??? implements IRouteRoot
*/
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 com.squareup.javapoet.MethodSpec in project AndroidLife by CaMnter.
the class RouterClass method putFieldMethodBuilder.
/**
* SmartRouter # putValue(final int value)
* SmartRouter # putValue(@NonNull final Integer value)
*
* @return List<MethodSpec>
*/
private List<MethodSpec> putFieldMethodBuilder() {
final List<MethodSpec> putMethods = new ArrayList<>();
for (RouterFieldAnnotation routerFieldAnnotation : this.routerFieldAnnotationList) {
final TypeMirror fieldTypeMirror = routerFieldAnnotation.getFieldType();
final TypeName fieldTypeName = TypeName.get(fieldTypeMirror);
final String fieldTypeString = fieldTypeMirror.toString();
final String fieldName = routerFieldAnnotation.getFieldName().toString();
final String expectName = "put" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
final MethodSpec.Builder putMethodBuilder = MethodSpec.methodBuilder(expectName).addModifiers(Modifier.PUBLIC).returns(TypeName.VOID).addCode(CodeBlock.of("this.put($S, value);\n", fieldName));
switch(fieldTypeString) {
case CHAR:
case BYTE:
case SHORT:
case INT:
case FLOAT:
case DOUBLE:
case LONG:
case BOOLEAN:
putMethodBuilder.addParameter(fieldTypeName, "value", Modifier.FINAL);
putMethods.add(putMethodBuilder.build());
break;
case BOXED_CHAR:
case BOXED_BYTE:
case BOXED_SHORT:
case BOXED_INT:
case BOXED_FLOAT:
case BOXED_DOUBLE:
case BOXED_LONG:
case BOXED_BOOLEAN:
case STRING:
putMethodBuilder.addParameter(createNonNullParameter(fieldTypeName, "value", Modifier.FINAL));
putMethods.add(putMethodBuilder.build());
break;
}
}
return putMethods;
}
Aggregations