我正在研究一个注释,它旨在强制一个类是不可变的.这里是处理器的代码:
@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 } } } } } }
当然,注释本身是微不足道的:
@Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface IsImmutable { }
我用Ant脚本编译它:
<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>
问题是,必须缺少某些东西,因为当我尝试使用由生成的jar文件提供的结果注释时,如下所示,没有任何反应:
@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); } }
显然,这个类不是最终的,并且该类应该在Eclipse中发出错误信号.但事实并非如此.
任何的想法?
编辑:我使用build.xml构建的jar文件似乎是正确的:它包含类文件,还包含Meta-INF / services / javax.annotation.processing.Processor文件,其中包含archipel.immutability.IsImmutableProcessor.我在我的测试项目中导入了这个jar文件,当我在我的Immut类中使用注释时(这只是一个粗略的测试),没有任何反应.
解决方法
默认情况下,在eclipse中禁用注释处理.为了启用它,您需要打开项目属性然后
1. Java编译器 – >注释处理:启用注释处理
2. Java编译器 – >注释处理 – >工厂路径:用工厂添加jar
1. Java编译器 – >注释处理:启用注释处理
2. Java编译器 – >注释处理 – >工厂路径:用工厂添加jar
如果您需要更多信息,请查看:getting started with AP in eclipse
编辑:
看看这个tutorial.它详细解释了如何设置eclipse以使用自定义注释处理器.
重要:打印错误时使用此方法:javax.annotation.processing.Messager.printMessage(Kind,CharSequence,Element)
代替:
javax.annotation.processing.Messager.printMessage(Kind,CharSequence).
来自第一个的消息在“问题”视图和大多数与源相关的视图中可见,而来自第二个的消息仅在“错误日志”视图中可见.