下面列出了怎么用javax.annotation.processing.Messager的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* @param originTypeElement 原始类文件,用于获取包名,以及打印错误
*/
public static void writeToFile(final TypeElement originTypeElement, final TypeSpec.Builder typeBuilder,
final Elements elementUtils, final Messager messager, final Filer filer) {
final TypeSpec typeSpec = typeBuilder.build();
final JavaFile javaFile = JavaFile
.builder(getPackageName(originTypeElement, elementUtils), typeSpec)
// 不用导入java.lang包
.skipJavaLangImports(true)
// 4空格缩进
.indent(" ")
.build();
try {
// 输出到processingEnv.getFiler()会立即参与编译
// 如果自己指定路径,可以生成源码到指定路径,但是可能无法被编译器检测到,本轮无法参与编译,需要再进行一次编译
javaFile.writeTo(filer);
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR, getStackTrace(e), originTypeElement);
}
}
/**
* 初始化方法
* @param processingEnvironment 获取信息
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
//节点工具类 (类、函数、属性都是节点)
elementUtils = processingEnvironment.getElementUtils();
//文件生成器 类/资源
filer = processingEnvironment.getFiler();
Messager messager = processingEnvironment.getMessager();
log = RouterLog.newLog(messager);
Map<String, String> options = processingEnvironment.getOptions();
//type(类信息)工具类
typeUtils = processingEnvironment.getTypeUtils();
//参数是模块名 为了防止多模块/组件化开发的时候 生成相同的编译文件 xx$$ROOT$$文件
if (!RouterUtils.isEmpty(options)) {
moduleName = options.get(RouterConstants.ARGUMENTS_NAME);
}
if (RouterUtils.isEmpty(moduleName)) {
throw new EmptyException("RouterProcessor Not set processor moduleName option !");
}
log.i("RouterProcessor init RouterProcessor " + moduleName + " success !");
}
@Before
public void setUp() {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement = elements.getTypeElement(TestSpec.class.getCanonicalName());
mSpecModel =
mLayoutSpecModelFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
EventDeclarationModel eventDeclarationModel =
new EventDeclarationModel(
ClassName.OBJECT,
ClassName.OBJECT,
ImmutableList.of(
new FieldModel(
FieldSpec.builder(TypeName.INT, "field1", Modifier.PUBLIC).build(),
new Object()),
new FieldModel(
FieldSpec.builder(TypeName.INT, "field2", Modifier.PUBLIC).build(),
new Object())),
new Object());
when(mMockSpecModel.getEventDeclarations()).thenReturn(ImmutableList.of(eventDeclarationModel));
when(mMockSpecModel.getContextClass()).thenReturn(ClassNames.COMPONENT_CONTEXT);
when(mMockSpecModel.getComponentName()).thenReturn("Test");
when(mMockSpecModel.getScopeMethodName()).thenReturn("getComponentScope");
}
@Test
public void testMethodExtraction() {
Elements elements = mCompilationRule.getElements();
TypeElement typeElement = elements.getTypeElement(TestClass.class.getCanonicalName());
List<Class<? extends Annotation>> permittedParamAnnotations = new ArrayList<>();
ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>> methods =
EventMethodExtractor.getOnEventMethods(
elements,
typeElement,
permittedParamAnnotations,
mock(Messager.class),
RunMode.normal());
EventMethodExtractorTestHelper.assertMethodExtraction(methods);
}
@Test
public void testMethodExtraction() {
Elements elements = mCompilationRule.getElements();
TypeElement typeElement = elements.getTypeElement(TestClass.class.getCanonicalName());
List<Class<? extends Annotation>> permittedParamAnnotations = new ArrayList<>();
permittedParamAnnotations.add(Event.class);
ImmutableList<SpecMethodModel<DelegateMethod, Void>> delegateMethods =
DelegateMethodExtractor.getDelegateMethods(
typeElement,
new ArrayList<>(DelegateMethodDescriptions.LAYOUT_SPEC_DELEGATE_METHODS_MAP.keySet()),
permittedParamAnnotations,
ImmutableList.<Class<? extends Annotation>>of(),
mock(Messager.class));
DelegateMethodExtractorTestHelper.assertDelegateMethodExtraction(delegateMethods);
}
@Test
public void testMethodExtraction() {
Elements elements = mCompilationRule.getElements();
TypeElement typeElement = elements.getTypeElement(TestClass.class.getCanonicalName());
List<Class<? extends Annotation>> permittedParamAnnotations = new ArrayList<>();
ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>> methods =
TriggerMethodExtractor.getOnTriggerMethods(
elements,
typeElement,
permittedParamAnnotations,
mock(Messager.class),
RunMode.normal());
ClassName eventClassName =
ClassName.bestGuess(
"com.facebook.litho.specmodels.processor.TriggerMethodExtractorTest.TestEvent");
TriggerMethodExtractorTestHelper.assertMethodExtraction(methods, eventClassName);
}
@Test
public void testDuplicatePropValidationError() {
final Elements elements = mCompilationRule.getElements();
final Types types = mCompilationRule.getTypes();
final TypeElement typeElement = elements.getTypeElement(DupeMountSpec.class.getCanonicalName());
final MountSpecModel mountSpecModel =
mFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
final List<SpecModelValidationError> specModelValidationErrors =
SpecModelValidation.validateMountSpecModel(mountSpecModel, RunMode.normal());
assertThat(specModelValidationErrors)
.extracting("message")
.contains(
"The prop prop1 is defined differently in different methods. "
+ "Ensure that each instance of this prop is declared in the same way "
+ "(this means having the same type, resType and values for isOptional, "
+ "isCommonProp and overrideCommonPropBehavior).");
}
@Before
public void setUp() {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement =
elements.getTypeElement(MountSpecModelFactoryTest.TestMountSpec.class.getCanonicalName());
mMountSpecModel =
mFactory.create(
elements,
types,
typeElement,
mock(Messager.class),
RunMode.normal(),
mDependencyInjectionHelper,
null);
}
private static MethodSpec.Builder generateConstructorBuilder(
HashMap<String, BarricadeResponseSet> values, Messager messager) {
MethodSpec.Builder methodBuilder = MethodSpec.constructorBuilder().addModifiers(PUBLIC);
methodBuilder.addStatement("configs = new HashMap<>()");
for (Map.Entry<String, BarricadeResponseSet> entry : values.entrySet()) {
BarricadeResponseSet barricadeResponseSet = entry.getValue();
String listName = "barricadeResponsesFor" + entry.getKey();
methodBuilder.addStatement("$T<$T> " + listName + " = new $T<>()", List.class,
BarricadeResponse.class, ArrayList.class);
for (BarricadeResponse barricadeResponse : barricadeResponseSet.responses) {
methodBuilder.addStatement(listName + ".add(new $T($L, $S, $S))", BarricadeResponse.class,
barricadeResponse.statusCode, barricadeResponse.responseFileName,
barricadeResponse.contentType);
}
methodBuilder.addStatement(
"configs.put($S, new $T(" + listName + ", " + barricadeResponseSet.defaultIndex + "))",
entry.getKey(), TYPE_BARRICADE_RESPONSE_SET);
}
return methodBuilder;
}
public static Spec parse(Element element, ProcessingEnvironment processingEnv) {
Messager messager = processingEnv.getMessager();
if (element.getKind() != ElementKind.INTERFACE) {
messager.printMessage(
Diagnostic.Kind.ERROR, "@DataEnum can only be used on interfaces.", element);
return null;
}
TypeElement dataEnum = (TypeElement) element;
List<TypeVariableName> typeVariableNames = new ArrayList<>();
for (TypeParameterElement typeParameterElement : dataEnum.getTypeParameters()) {
typeVariableNames.add(TypeVariableName.get(typeParameterElement));
}
List<Value> values = ValuesParser.parse(dataEnum, processingEnv);
if (values == null) {
return null;
}
ClassName enumInterface = ClassName.get(dataEnum);
return new Spec(enumInterface, typeVariableNames, values);
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
for (Element e : roundEnv.getRootElements()) {
messager.printMessage(WARNING, WRN_NO_SOURCE);
messager.printMessage(WARNING, WRN_WITH_SOURCE, e);
messager.printMessage(WARNING, WRN_NO_SOURCE);
}
return false;
}
/**
* Create a new {@link FormattingJavaFileObject}.
*
* @param delegate {@link JavaFileObject} to decorate
* @param messager to log messages with.
*/
FormattingJavaFileObject(
JavaFileObject delegate, Formatter formatter, @Nullable Messager messager) {
super(checkNotNull(delegate));
this.formatter = checkNotNull(formatter);
this.messager = messager;
}
public void writeInto(final Filer pFiler, final Messager pMessager, final String lPackageName) {
//final GeneratedClass lGeneratedClass =
// new GeneratedClass(mEnclosingClass, lPackageName, mMethods, mFields);
TypeSpec lTypeSpecGeneratedClass =
new GeneratedBuilderClass(mEnclosingClass, lPackageName, mFields).buildFieldTypeSpec();
// create generated class to a file
try {
JavaFile.builder(lPackageName, lTypeSpecGeneratedClass)
.build()
.writeTo(pFiler);
} catch (IOException pE) {
logError(pMessager, mEnclosingClass, "error while writing generated class "+pE);
}
}
@Override
public DiffSectionSpecModel create(
Elements elements,
Types types,
TypeElement element,
Messager messager,
EnumSet<RunMode> runMode,
@Nullable DependencyInjectionHelper dependencyInjectionHelper,
@Nullable InterStageStore interStageStore) {
return createModel(elements, types, element, messager, dependencyInjectionHelper, runMode);
}
@Override
public GroupSectionSpecModel create(
Elements elements,
Types types,
TypeElement element,
Messager messager,
EnumSet<RunMode> runMode,
@Nullable DependencyInjectionHelper dependencyInjectionHelper,
@Nullable InterStageStore interStageStore) {
return createModel(elements, types, element, messager, dependencyInjectionHelper, runMode);
}
public GroupSectionSpecModel createModel(
Elements elements,
Types types,
TypeElement element,
Messager messager,
@Nullable DependencyInjectionHelper dependencyInjectionHelper,
EnumSet<RunMode> runMode) {
return new GroupSectionSpecModel(
element.getQualifiedName().toString(),
element.getAnnotation(GroupSectionSpec.class).value(),
DelegateMethodExtractor.getDelegateMethods(
element,
DELEGATE_METHOD_ANNOTATIONS,
INTER_STAGE_INPUT_ANNOTATIONS,
ImmutableList.<Class<? extends Annotation>>of(ShouldUpdate.class),
messager),
EventMethodExtractor.getOnEventMethods(
elements, element, INTER_STAGE_INPUT_ANNOTATIONS, messager, runMode),
TriggerMethodExtractor.getOnTriggerMethods(
elements, element, INTER_STAGE_INPUT_ANNOTATIONS, messager, runMode),
UpdateStateMethodExtractor.getOnUpdateStateMethods(
element, INTER_STAGE_INPUT_ANNOTATIONS, messager),
ImmutableList.copyOf(TypeVariablesExtractor.getTypeVariables(element)),
ImmutableList.copyOf(PropDefaultsExtractor.getPropDefaults(element)),
EventDeclarationsExtractor.getEventDeclarations(
elements, element, GroupSectionSpec.class, runMode),
AnnotationExtractor.extractValidAnnotations(element),
ImmutableList.of(BuilderMethodModel.KEY_BUILDER_METHOD, LOADING_EVENT_BUILDER_METHOD),
TagExtractor.extractTagsFromSpecClass(types, element, runMode),
JavadocExtractor.getClassJavadoc(elements, element),
JavadocExtractor.getPropJavadocs(elements, element),
element.getAnnotation(GroupSectionSpec.class).isPublic(),
SpecElementTypeDeterminator.determine(element),
dependencyInjectionHelper,
element,
mSpecGenerator,
FieldsExtractor.extractFields(element));
}
@Before
public void setUp() {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement = elements.getTypeElement(TestSpec.class.getCanonicalName());
mSpecModel =
mLayoutSpecModelFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
}
@Before
public void setUp() {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement =
elements.getTypeElement(WorkingRangeGeneratorTest.TestSpec.class.getCanonicalName());
mSpecModel =
mLayoutSpecModelFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
}
private LayoutSpecModel getSpecModel(Class specClass) {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement = elements.getTypeElement(specClass.getCanonicalName());
return mLayoutSpecModelFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
}
@Before
public void setUp() {
Elements elements = mCompilationRule.getElements();
Types types = mCompilationRule.getTypes();
TypeElement typeElement = elements.getTypeElement(TestSpec.class.getCanonicalName());
mSpecModel =
mLayoutSpecModelFactory.create(
elements, types, typeElement, mock(Messager.class), RunMode.normal(), null, null);
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
for (Element e : roundEnv.getRootElements()) {
messager.printMessage(WARNING, WRN_NO_SOURCE);
messager.printMessage(WARNING, WRN_WITH_SOURCE, e);
messager.printMessage(WARNING, WRN_NO_SOURCE);
}
return false;
}
@Test
public void testMethodExtraction() {
Elements elements = mCompilationRule.getElements();
TypeElement typeElement = elements.getTypeElement(TestClass.class.getCanonicalName());
List<Class<? extends Annotation>> permittedParamAnnotations = new ArrayList<>();
ImmutableList<SpecMethodModel<UpdateStateMethod, Void>> methods =
UpdateStateMethodExtractor.getOnUpdateStateMethods(
typeElement, permittedParamAnnotations, mock(Messager.class));
UpdateStateMethodExtractorTestHelper.assertMethodExtraction(methods);
}
/** Get the delegate methods from the given {@link TypeElement}. */
public static ImmutableList<SpecMethodModel<UpdateStateMethod, Void>> getOnUpdateStateMethods(
TypeElement typeElement,
List<Class<? extends Annotation>> permittedInterStageInputAnnotations,
Messager messager) {
return extractOnUpdateStateMethods(
typeElement, permittedInterStageInputAnnotations, messager, false);
}
/** Get the delegate methods from the given {@link TypeElement}. */
public static ImmutableList<SpecMethodModel<UpdateStateMethod, Void>>
getOnUpdateStateWithTransitionMethods(
TypeElement typeElement,
List<Class<? extends Annotation>> permittedInterStageInputAnnotations,
Messager messager) {
return extractOnUpdateStateMethods(
typeElement, permittedInterStageInputAnnotations, messager, true);
}
@Nullable
public static SpecMethodModel<EventMethod, Void> getRegisterMethod(
TypeElement typeElement,
List<Class<? extends Annotation>> permittedInterStageInputAnnotations,
Messager messager) {
for (Element enclosedElement : typeElement.getEnclosedElements()) {
if (enclosedElement.getKind() != ElementKind.METHOD) {
continue;
}
final ExecutableElement executableElement = (ExecutableElement) enclosedElement;
final Annotation registerRangesAnnotation =
enclosedElement.getAnnotation(OnRegisterRanges.class);
if (registerRangesAnnotation != null) {
final List<MethodParamModel> methodParams =
getMethodParams(
executableElement,
messager,
getPermittedMethodParamAnnotations(permittedInterStageInputAnnotations),
permittedInterStageInputAnnotations,
ImmutableList.of());
return SpecMethodModel.<EventMethod, Void>builder()
.annotations(ImmutableList.of())
.modifiers(ImmutableList.copyOf(new ArrayList<>(executableElement.getModifiers())))
.name(executableElement.getSimpleName())
.returnTypeSpec(generateTypeSpec(executableElement.getReturnType()))
.typeVariables(ImmutableList.copyOf(getTypeVariables(executableElement)))
.methodParams(ImmutableList.copyOf(methodParams))
.representedObject(executableElement)
.build();
}
}
return null;
}
@Nullable
private static SpecMethodModel<EventMethod, WorkingRangeDeclarationModel>
generateWorkingRangeMethod(
Elements elements,
ExecutableElement executableElement,
List<Class<? extends Annotation>> permittedInterStageInputAnnotations,
Messager messager,
Class<? extends Annotation> annotationType) {
final List<MethodParamModel> methodParams =
getMethodParams(
executableElement,
messager,
getPermittedMethodParamAnnotations(permittedInterStageInputAnnotations),
permittedInterStageInputAnnotations,
ImmutableList.of());
final String nameInAnnotation =
ProcessorUtils.getAnnotationParameter(
elements, executableElement, annotationType, "name", String.class);
List<? extends AnnotationMirror> annotationMirrors = executableElement.getAnnotationMirrors();
AnnotationMirror mirror = null;
for (AnnotationMirror m : annotationMirrors) {
if (m.getAnnotationType().toString().equals(annotationType.getCanonicalName())) {
mirror = m;
break;
}
}
return SpecMethodModel.<EventMethod, WorkingRangeDeclarationModel>builder()
.annotations(ImmutableList.of())
.modifiers(ImmutableList.copyOf(new ArrayList<>(executableElement.getModifiers())))
.name(executableElement.getSimpleName())
.returnTypeSpec(generateTypeSpec(executableElement.getReturnType()))
.typeVariables(ImmutableList.copyOf(getTypeVariables(executableElement)))
.methodParams(ImmutableList.copyOf(methodParams))
.representedObject(executableElement)
.typeModel(new WorkingRangeDeclarationModel(nameInAnnotation, mirror))
.build();
}
/**
* Create a {@link SpecModel} from the given {@link TypeElement} and an optional {@link
* DependencyInjectionHelper}. The optional {@link InterStageStore} can be used to augment name
* lookups in Java 7.
*/
T create(
Elements elements,
Types types,
TypeElement element,
Messager messager,
EnumSet<RunMode> runMode,
@Nullable DependencyInjectionHelper dependencyInjectionHelper,
@Nullable InterStageStore propNameInterStageStore);
/**
* Create a new {@link FormattingJavaFileObject}.
*
* @param delegate {@link JavaFileObject} to decorate
* @param messager to log messages with.
*/
FormattingJavaFileObject(
JavaFileObject delegate, Formatter formatter, @Nullable Messager messager) {
super(checkNotNull(delegate));
this.formatter = checkNotNull(formatter);
this.messager = messager;
}
/**
* Generates the code for the Barricade configuration based on the annotations found.
*
* @param processingEnv Processing environment
* @param configs Configuration detected by annotation processing
* @param messager Messager to print logs
* @throws IOException
*/
static void generateClass(ProcessingEnvironment processingEnv,
HashMap<String, BarricadeResponseSet> configs, Messager messager) throws IOException {
messager.printMessage(Diagnostic.Kind.NOTE, "Generating configuration code...");
TypeSpec.Builder classBuilder = classBuilder(CLASS_NAME).addModifiers(PUBLIC, FINAL);
FieldSpec valuesField = FieldSpec.builder(TYPE_CONFIG, "configs").addModifiers(PRIVATE).build();
FieldSpec instanceField =
FieldSpec.builder(ClassName.get(PACKAGE_NAME, CLASS_NAME), "barricadeConfig")
.addModifiers(PRIVATE, STATIC)
.build();
MethodSpec.Builder instanceMethodBuilder = generateGetInstanceMethodBuilder();
MethodSpec.Builder constructorMethodBuilder = generateConstructorBuilder(configs, messager);
MethodSpec.Builder valuesMethod = generateGetConfigsMethodBuilder();
MethodSpec.Builder getResponseMethodBuilder = generateGetResponseMethodBuilder();
classBuilder.addType(generateEndpointsInnerClass(configs.keySet()));
classBuilder.addType(generateResponsesInnerClass(configs));
classBuilder.addField(instanceField);
classBuilder.addField(valuesField);
classBuilder.addMethod(instanceMethodBuilder.build());
classBuilder.addMethod(constructorMethodBuilder.build());
classBuilder.addMethod(valuesMethod.build());
classBuilder.addMethod(getResponseMethodBuilder.build());
classBuilder.addSuperinterface(IBarricadeConfig.class);
JavaFile.Builder javaFileBuilder = builder(PACKAGE_NAME, classBuilder.build());
JavaFile javaFile = javaFileBuilder.build();
javaFile.writeTo(processingEnv.getFiler());
messager.printMessage(Diagnostic.Kind.NOTE, "Code generation complete!");
}
private static Iterable<AnnotationSpec> parseMethodAnnotations(
ExecutableElement methodElement, Messager messager) {
ArrayList<AnnotationSpec> annotations = new ArrayList<>();
for (AnnotationMirror annotationMirror : methodElement.getAnnotationMirrors()) {
TypeName annotationTypeName =
ClassName.get(annotationMirror.getAnnotationType().asElement().asType());
if (!(annotationTypeName instanceof ClassName)) {
messager.printMessage(
Kind.ERROR,
"Annotation is not a class; this shouldn't happen",
methodElement,
annotationMirror);
continue;
}
Builder builder = AnnotationSpec.builder(((ClassName) annotationTypeName));
for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
annotationMirror.getElementValues().entrySet()) {
builder.addMember(entry.getKey().getSimpleName().toString(), entry.getValue().toString());
}
annotations.add(builder.build());
}
return annotations;
}