I'm working on an annotation which aims to it mandatory for a class to be immutable. Here the code of the processor:
@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
                    }
                }
            }
        }
    }
}
The annotation itself is trivial, of course:
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface IsImmutable {
}
And I compile it with a 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>
Problem is, something must be missing, because when I try to use the resulting annotation, provided by the resulting 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);
    }
}
Obviousy, this class is not final, and the class should signal an error in Eclipse. But it's not.
Any idea?
Edit: The jar file I built with my build.xml seems correct: It contains the class files, and also a META-INF/services/javax.annotation.processing.Processor file, which contains archipel.immutability.IsImmutableProcessor. I import this jar file in my test project, and when I use the annotation in my Immut class (which is only a rough test), nothing happens.
An annotation is a construct associated with Java source code elements such as classes, methods, and variables. Annotations provide information to a program at compile time or at runtime based on which the program can take further action.
The @interface element is used to declare an annotation. For example: @interface MyAnnotation{}
Annotation processing by default is disabled in eclipse. in order to enable it you need to open project properties and then 1. Java Compiler -> Annotation processing: enable annotation processing 2. Java Compiler -> Annotation processing -> factory path: add jar with factories
if you need some more information take a look at: getting started with AP in eclipse
Edited:
take a look at this tutorial. It explains in details how to set up eclipse to use custom annotation processors.
Important: when printing errors use this method:  javax.annotation.processing.Messager.printMessage(Kind, CharSequence, Element)
instead of:javax.annotation.processing.Messager.printMessage(Kind, CharSequence). 
messages from the first one are visible in Problems view and most source-related views while messages from the second one are visible only in ErrorLog view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With