下面列出了怎么用javax.annotation.processing.AbstractProcessor的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Test that the ijar tool preserves EnclosingMethod attributes and doesn't prevent annotation
* processors from accessing all the elements in a package.
*/
@Test
public void testEnclosingMethod() throws IOException {
JavaCompiler.CompilationTask task =
makeCompilationTask("third_party/ijar/test/package-info.java");
task.setProcessors(
Arrays.asList(
new AbstractProcessor() {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public boolean process(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
roundEnv.getElementsAnnotatedWith(java.lang.Override.class);
return true;
}
}));
if (!task.call()) {
fail(getFailedCompilationMessage());
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
private void processAnnotations(RoundEnvironment roundEnv) {
TypeElement processor =
processingEnv.getElementUtils().getTypeElement(Processor.class.getCanonicalName());
TypeElement abstractProcessor =
processingEnv.getElementUtils().getTypeElement(AbstractProcessor.class.getCanonicalName());
for (Element e : roundEnv.getElementsAnnotatedWith(IncrementalAnnotationProcessor.class)) {
if (!checkAnnotatedElement(e, processor)) {
continue;
}
IncrementalAnnotationProcessorType processorType =
e.getAnnotation(IncrementalAnnotationProcessor.class).value();
if (processorType == IncrementalAnnotationProcessorType.DYNAMIC
&& processingEnv.getTypeUtils().isSubtype(e.asType(), abstractProcessor.asType())) {
Element getSupportedOptions =
processingEnv.getElementUtils().getAllMembers((TypeElement) e).stream()
.filter(
method ->
method.getKind() == ElementKind.METHOD
&& method.getSimpleName().contentEquals(GET_SUPPORTED_OPTIONS)
&& ((ExecutableElement) method).getParameters().isEmpty())
.findFirst()
.orElseThrow(AssertionError::new);
if (abstractProcessor.equals(getSupportedOptions.getEnclosingElement())) {
warning(
"Dynamic incremental annotation processor should override "
+ GET_SUPPORTED_OPTIONS
+ "()",
e);
}
}
processors.put(
processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString(), processorType);
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"--should-stop:at=ATTR",
"--debug:verboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
protected void check() throws Exception {
String[] options = {
"-XDshouldStopPolicy=ATTR",
"-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef"
};
AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
@SuppressWarnings("unchecked")
DiagnosticListener<? super JavaFileObject>[] diagListeners =
new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
for (int i = 0 ; i < options.length ; i ++) {
JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
Arrays.asList(options[i]), null, Arrays.asList(jfo));
if (processors[i] != null) {
ct.setProcessors(Collections.singleton(processors[i]));
}
ct.analyze();
}
//check diags
for (Diagnostic<? extends JavaFileObject> diag : diags) {
for (DiagnosticProcessor proc : diagProcessors) {
if (proc.matches(diag)) {
proc.process(diag);
break;
}
}
}
//check all candidates have been used up
for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
if (!seenCandidates.contains(entry.getKey())) {
error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType());
}
}
}
private static AbstractProcessor createWrappedInstance() {
ClassLoader cl = Main.createShadowClassLoader();
try {
Class<?> mc = cl.loadClass("lombok.core.AnnotationProcessor");
return (AbstractProcessor) mc.newInstance();
} catch (Throwable t) {
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
throw new RuntimeException(t);
}
}
public static void assertProcess(BiConsumer<ProcessingEnvironment, RoundEnvironment> test) {
File f = null;
try {
f = Files.createTempFile("test", ".java").toFile();
try (PrintWriter writer = new PrintWriter(f)) {
writer.print("class Empty {}");
}
} catch (IOException e) {
throw new AssertionError(e);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, Locale.getDefault(), Charset.defaultCharset());
JavaCompiler.CompilationTask task = compiler.getTask(new PrintWriter(System.out),
fileManager,
diagnostics,
Collections.singletonList("-proc:only"),
Collections.emptyList(),
fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(f)));
task.setLocale(Locale.getDefault());
task.setProcessors(Collections.singleton(new AbstractProcessor() {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
test.accept(processingEnv, roundEnv);
return true;
}
}));
assertTrue(task.call());
}
@Test
public void testGen() throws Exception {
AtomicInteger count = new AtomicInteger();
AbstractProcessor proc = new AbstractProcessor() {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (count.getAndIncrement() == 0) {
try {
Filer filer = processingEnv.getFiler();
Element elt = processingEnv.getElementUtils().getTypeElement("gen.GeneratedClass");
JavaFileObject src = filer.createSourceFile("io.vertx.test.gen.GeneratedClass", elt);
try (Writer writer = src.openWriter()) {
writer.append("package io.vertx.test.gen;\npublic class GeneratedClass {\n}");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
};
Compiler<TestGenProcessor> compiler = buildCompiler(new TestGenProcessor(), "io.vertx.test.gen");
compiler.addProcessor(proc);
compiler.assertCompile();
assertEquals(3, count.get());
}
@Test
public void testCallbackIssuedAfterEnterWithAPs() throws IOException {
// We add an unrelated source file here to make the compiler do something
compiler.addSourceFileContents("Bar.java", "class Bar { }");
compiler.setProcessors(
ImmutableList.of(
new AbstractProcessor() {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public boolean process(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
Filer filer = processingEnv.getFiler();
// We wait until the last possible moment to generate Foo; if the callback is able
// to get an element for it, that means it ran after the enter phase
try (OutputStream outputStream =
filer.createSourceFile("Foo").openOutputStream()) {
outputStream.write("class Foo { }".getBytes());
} catch (IOException e) {
throw new AssertionError(e);
}
}
return false;
}
}));
addCallback("callback");
compiler.compile();
assertThat(callbacksIssued, Matchers.contains("callback: Bar, Foo"));
}
@Test public void errorTypes() {
JavaFileObject hasErrorTypes =
JavaFileObjects.forSourceLines(
"com.squareup.tacos.ErrorTypes",
"package com.squareup.tacos;",
"",
"@SuppressWarnings(\"hook-into-compiler\")",
"class ErrorTypes {",
" Tacos tacos;",
" Ingredients.Guacamole guacamole;",
"}");
Compilation compilation = javac().withProcessors(new AbstractProcessor() {
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
TypeElement classFile =
processingEnv.getElementUtils().getTypeElement("com.squareup.tacos.ErrorTypes");
List<VariableElement> fields = fieldsIn(classFile.getEnclosedElements());
ErrorType topLevel = (ErrorType) fields.get(0).asType();
ErrorType member = (ErrorType) fields.get(1).asType();
assertThat(TypeName.get(topLevel)).isEqualTo(ClassName.get("", "Tacos"));
assertThat(TypeName.get(member)).isEqualTo(ClassName.get("Ingredients", "Guacamole"));
return false;
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
}).compile(hasErrorTypes);
assertThat(compilation).failed();
}
private void runTest(TestRunnable r) throws Exception {
testCompiler.addSourceFile(getSourceFile("Foo.java"));
if (testMode == WITH_DEPS) {
testCompiler.addClasspathSourceFile(getSourceFile("Dependency.java"));
testCompiler.addClasspathSourceFile(getSourceFile("DependencyException.java"));
testCompiler.addClasspathSourceFile(getSourceFile("DependencyInterface.java"));
} else {
testCompiler.useFrontendOnlyJavacTask();
}
testCompiler.setProcessors(
Collections.singletonList(
new AbstractProcessor() {
@Override
public Set<String> getSupportedOptions() {
return Collections.emptySet();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_8;
}
@Override
public boolean process(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
try {
r.run();
} catch (Exception e) {
throw new AssertionError(e);
}
}
return false;
}
}));
elements = testCompiler.getElements();
testCompiler.enter();
}
@Test
public void testAnnotationProcessorGetsNewElementsEachRound() throws Exception {
AtomicBoolean processorRan = new AtomicBoolean(false);
initCompiler(ImmutableMap.of("Foo.java", "public class Foo { }"));
testCompiler.setProcessors(
ImmutableList.of(
new AbstractProcessor() {
private Filer filer;
private Elements elementsFromEnvironment;
private TypeElement element;
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filer = processingEnv.getFiler();
elementsFromEnvironment = processingEnv.getElementUtils();
}
@Override
public boolean process(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
TypeElement newElement = elementsFromEnvironment.getTypeElement("Foo");
assertNotNull(newElement);
if (elementsFromEnvironment.getTypeElement("Bar") == null) {
assertNotSame(newElement, element);
element = newElement;
try {
JavaFileObject fileObject = filer.createSourceFile("Bar", newElement);
try (Writer writer = fileObject.openWriter()) {
writer.write("public class Bar { }");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
processorRan.set(roundEnv.processingOver());
return false;
}
}));
testCompiler.compile();
assertTrue(processorRan.get());
}
@Test
public void testTypeParametersWithAnnotationsOnBounds() {
@SupportedAnnotationTypes("*")
class CompilerBugProcessor extends AbstractProcessor {
boolean checkedAnnotationsOnTypeBounds;
boolean reportsAnnotationsOnTypeBounds;
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
TypeElement test = processingEnv.getElementUtils().getTypeElement("com.example.Test");
TypeParameterElement t = test.getTypeParameters().get(0);
this.checkedAnnotationsOnTypeBounds = true;
this.reportsAnnotationsOnTypeBounds =
!t.getBounds().get(0).getAnnotationMirrors().isEmpty();
}
return false;
}
}
CompilerBugProcessor compilerBugProcessor = new CompilerBugProcessor();
JavaFileObject nullableTypeFileObject =
JavaFileObjects.forSourceLines(
"foo.bar.NullableType",
"package foo.bar;",
"",
"import java.lang.annotation.ElementType;",
"import java.lang.annotation.Target;",
"",
"@Target(ElementType.TYPE_USE)",
"public @interface NullableType {}");
JavaFileObject autoValueFileObject =
JavaFileObjects.forSourceLines(
"com.example.Test",
"package com.example;",
"",
"import com.google.auto.value.AutoValue;",
"import foo.bar.NullableType;",
"",
"@AutoValue",
"abstract class Test<T extends @NullableType Object & @NullableType Cloneable> {}");
Compilation compilation =
javac()
.withProcessors(new AutoValueProcessor(), compilerBugProcessor)
.withOptions("-Xlint:-processing", "-implicit:none")
.compile(nullableTypeFileObject, autoValueFileObject);
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilerBugProcessor.checkedAnnotationsOnTypeBounds).isTrue();
if (compilerBugProcessor.reportsAnnotationsOnTypeBounds) {
assertThat(compilation)
.generatedSourceFile("com.example.AutoValue_Test")
.contentsAsUtf8String()
.contains(
"class AutoValue_Test<T extends @NullableType Object & @NullableType Cloneable>"
+ " extends Test<T> {");
}
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override public void evaluate() throws Throwable {
final AtomicReference<Throwable> thrown = new AtomicReference<>();
boolean successful = compile(ImmutableList.of(new AbstractProcessor() {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return ImmutableSet.of("*");
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
elements = processingEnv.getElementUtils();
types = processingEnv.getTypeUtils();
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// just run the test on the last round after compilation is over
if (roundEnv.processingOver()) {
try {
base.evaluate();
} catch (Throwable e) {
thrown.set(e);
}
}
return false;
}
}));
checkState(successful);
Throwable t = thrown.get();
if (t != null) {
throw t;
}
}
};
}
/**
* 为生成代码的注解处理器创建一个通用注解
*
* @param processorType 注解处理器
* @return 代码生成信息注解
*/
public static AnnotationSpec newProcessorInfoAnnotation(Class<? extends AbstractProcessor> processorType) {
return AnnotationSpec.builder(Generated.class)
.addMember("value", "$S", processorType.getCanonicalName())
.build();
}