When running annotation processing in the IDE, the annotation information defined by @Retention (RetentionPolicy.SOURCE)
may not be obtained under certain conditions.
OS
Windows 10
Java
openjdk 10.0.2
Eclipse
Photon (4.8.0)
※Pleiades
IntelliJ
IntelliJ IDEA 2018.2.3 (Community Edition)
Gradle
Gradle 4.10
Project structure
|-foo/
| `-src/main/java/
| `-sample/foo/
| |-Fizz.java
| `-Buzz.java
|
|-bar/
| |-src/main/java/
| | `-sample/bar/
| | |-MyRuntimeRetention.java
| | |-MyClassRetention.java
| | |-MySourceRetention.java
| | `-MyProcessor.java
| |
| `-src/main/resources/
| `-META-INF/services
| `-javax.annotation.processing.Processor
|
|-build.gradle
`-settings.gradle
--Multi-project of foo
, bar
--The project where bar
implements annotation processing
--foo
is a project that uses bar
annotation processing
--MyRuntimeRetention.java
, MyClassRetention.java
, MySourceRetention.java
set the value corresponding to the name in Retention
in their own annotations.
MyRuntimeRetention.java
package sample.bar;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeRetention {
}
MyClassRetention.java
package sample.bar;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MyClassRetention {
}
MySourceRetention.java
package sample.bar;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface MySourceRetention {
}
--Class in which MyProcessor.java
implements annotation processing
MyProcessor.java
package sample.bar;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic.Kind;
public class MyProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Elements elements = this.processingEnv.getElementUtils();
if (!annotations.isEmpty()) {
this.printAnnotations(elements.getTypeElement("sample.foo.Fizz"));
this.printAnnotations(elements.getTypeElement("sample.foo.Buzz"));
}
return true;
}
private void printAnnotations(TypeElement element) {
element.getAnnotationMirrors().forEach(annotation -> {
this.processingEnv.getMessager().printMessage(Kind.NOTE, element.getSimpleName() + " : " + annotation);
});
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_10;
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Set.of(MySourceRetention.class.getCanonicalName());
}
}
--Getting the TypeElement
of the Fizz
, Buzz
class and outputting the annotations set in the class in a list.
Fizz.java
package sample.foo;
import sample.bar.MyClassRetention;
import sample.bar.MyRuntimeRetention;
import sample.bar.MySourceRetention;
@MyRuntimeRetention
@MyClassRetention
@MySourceRetention
public class Fizz {
}
Buzz.java
package sample.foo;
import sample.bar.MyClassRetention;
import sample.bar.MyRuntimeRetention;
import sample.bar.MySourceRetention;
@MyRuntimeRetention
@MyClassRetention
@MySourceRetention
public class Buzz {
}
--The foo
project Fizz
, Buzz
sets three self-made annotations in the class.
In this state, modify only the ** Fizz
class and execute ** compilation.
Then, the result will be different when running in Gradle and when running in IDE (Eclipse, IntelliJ).
> gradle :foo:compileJava
Caution:Fizz : @sample.bar.MyRuntimeRetention
Caution:Fizz : @sample.bar.MyClassRetention
Caution:Fizz : @sample.bar.MySourceRetention
Caution:Buzz : @sample.bar.MyRuntimeRetention
Caution:Buzz : @sample.bar.MyClassRetention
Caution:Buzz : @sample.bar.MySourceRetention
--You can get the information of all annotations normally.
--All annotations of Fizz
class have been acquired
--However, @MySourceRetention
cannot get the annotation of the Buzz
class.
--This is also the same as Eclipse, and @MySourceRetention
cannot be obtained from the annotation information of the Buzz
class.
--Modify not only the Fizz
class but also the Buzz
class and then run the build to run the annotation process.
--Then, the result is as follows.
Eclipse
--You can also get the @MySourceRetention
set in Buzz
.
IntelliJ
--The same is true here, and you can get @MySourceRetention
.
--When Retention
is set to SOURCE
, annotation information does not remain in the class file /RetentionPolicy.html#SOURCE)
--In view of the fact that only the information of the specified annotation could not be obtained if it was not modified, probably if the annotation processing works in the IDE (Eclipse, IntelliJ), the class without modification I feel that the information is based on the previous compilation result (class file).
--By the way, I haven't tried NetBeans
--When annotation processing works in IDE (Eclipse, IntelliJ), it seems that you cannot get the annotation information of Retention
set to SOURCE
in the class without modification.
--The reason is probably that the IDE seems to get the information of the unmodified class from the previous compilation result (class file).
--When writing annotation processing by yourself, be careful when handling annotations with Retention
of SOURCE
.
--If you are making your own annotations, it is a good idea to set Retention
to CLASS
or higher.
Recommended Posts