Annotations do not work

I am working on an annotation whose purpose is mandatory for the class to be immutable. Here is the processor code:

@SupportedAnnotationTypes("archipel.immutability.IsImmutable") @SupportedSourceVersion(SourceVersion.RELEASE_6) public class IsImmutableProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (TypeElement type : annotations) { processMustBeImmutable(roundEnv, type); } return true; } private void processMustBeImmutable(RoundEnvironment env, TypeElement type) { for (Element element : env.getElementsAnnotatedWith(type)) { processClass(element); } } private void processClass(Element element) { boolean isFinal=false; for(Modifier modifier : element.getModifiers()) { if (modifier.equals(Modifier.FINAL)) { isFinal=true; break; } } if (!isFinal) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Class "+element+" is not immutable because it is not final"); } else { for (Element subElement : element.getEnclosedElements()) { if (subElement.getKind()==ElementKind.FIELD) { isFinal=false; for(Modifier modifier : subElement.getModifiers()) { if (modifier.equals(Modifier.FINAL)) { isFinal=true; break; } } if (!isFinal) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Field "+element+" is not immutable because it is not final"); } else { Element superElement = subElement.getEnclosingElement(); // TODO } } } } } } 

Of course, the annotation itself is trivial:

 @Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface IsImmutable { } 

And I will compile it with Ant script:

 <project name="immutability" basedir="." default="main"> <property name="lib.dir" value="lib"/> <property name="src.dir" value="src"/> <property name="build.dir" value="build"/> <property name="classes.dir" value="${build.dir}/classes"/> <property name="meta.dir" value="${build.dir}/META-INF"/> <property name="jar.dir" value="${build.dir}/jar"/> <property name="processor-package" value="archipel.immutability" /> <property name="processor" value="${processor-package}.IsImmutableProcessor"/> <path id="classpath"> <fileset dir="${lib.dir}" includes="**/*.jar"/> <fileset dir="${classes.dir}"/> </path> <target name="clean"> <delete dir="${build.dir}"/> </target> <target name="compile" description="Compiles the code."> <mkdir dir="${classes.dir}"/> <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" /> </target> <target name="jar" depends="compile"> <mkdir dir="${jar.dir}"/> <jar destfile="${jar.dir}/${ant.project.name}.jar"> <fileset dir="${classes.dir}"/> <service type="javax.annotation.processing.Processor" provider="archipel.immutability.IsImmutableProcessor"/> </jar> </target> <target name="main" depends="clean,jar"/> </project> 

The problem is that something must be missing, because when I try to use the received annotation provided by the received jar file, like the following, nothing happens:

 @IsImmutable public class Immut { private int toto; public int getToto() { return toto; } public void setToto(int toto) { this.toto = toto; } public final static void main(String args[]) { Immut truc = new Immut(); truc.setToto(5); truc.setToto(6); } } 

Obviously, this class is not final, and the class should signal an error in Eclipse. But this is not so.

Any idea?

Change The jar file that I created with my build.xml seems to be correct: it contains class files, as well as a META-INF/services/javax.annotation.processing.Processor containing archipel.immutability.IsImmutableProcessor . I import this jar file into my test project, and when I use the annotation in my Immut class (this is just a rough test), nothing happens.

+6
source share
2 answers

Annotation processing is disabled by default in eclipse. to enable it, you need to open the project properties, and then 1. Java compiler → Annotation processing: enable annotation processing 2. Java compiler → Annotation processing → factory path: add a jar with factories

if you need more information, check out: getting started with AP in eclipse

Edited by:

take a look at this tutorial . It explains in detail how to configure eclipse to use custom annotation processors.

Important: when printing errors, use this method: javax.annotation.processing.Messager.printMessage(Kind, CharSequence, Element) instead:
javax.annotation.processing.Messager.printMessage(Kind, CharSequence).

messages from the first are visible in the "Problems" view and most of the views associated with the source, while messages from the second are displayed only in the "ErrorLog" view.

+10
source

it might be worth using cglib to make the object immutable. because imagine that you have a collection inside your class and collection fields. You also have a collector for this collection. Does this mean that the collection cannot be changed outside the class? not really. Only if this collection has been wrapped using the Collections.unmodifiedCollection method. Or if you use the guava permanent collections http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained

The fact is, do not try to do this only by checking if the fields are final - it will not process all the scripts. use cglib proxy instead, like spring and sleep

0
source

Source: https://habr.com/ru/post/921033/


All Articles