Forward compatible Java 6 annotation processor and SupportedSourceVersion

bernie picture bernie · Nov 18, 2011 · Viewed 7.4k times · Source

I am trying out Java 7 for one project and getting warnings from annotation processors (Bindgen and Hibernate JPA modelgen) of this sort:

warning: Supported source version 'RELEASE_6' from annotation processor 'org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor' less than -source '1.7'

This is caused by the @SupportedSourceVersion(SourceVersion.RELEASE_6) annotation on the annotation processor classes. Since they are compiled with Java 6, the highest value of SourceVersion available to them is RELEASE_6. The Java 7 version of SourceVersion introduces RELEASE_7.

My questions: How are annotation processors supposed to handle forward compatibility? Will there have to be separate jdk6 and jdk7 binary versions of them? Am I not understanding something else here?

I only found the following information regarding this concern:

Querdydsl bug report which used

@Override
public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latest();
}

Oracle blog in which a commentor recommends supporting latest source version

Answer

kapex picture kapex · Nov 18, 2011

Forward compatibility is handled by processing unknown language constructs appropriately, for example by implementing ElementVisitor.visitUnknown.

There is another entry in the mentioned Oracle blog, which suggests two policies regarding forward compatibility:

  • Write the processor to only work with the current language version.
  • Write the processor to cope with unknown future constructs.

The second one is done by returning SourceVersion.latest() as already posted in the question.

I think it's ok to do this in most cases, when you are sure additional language elements won't break anything. Of course you shouldn't just assume that everything will be fine even with newer versions, you should test it too.


Ok, I guess processing unknown language constructs appropriately sounds a bit vague, so here are some examples.

Supposed you have a processor that checks for a custom type of annotations on known language constructs (annotations on a class for example) and creates a simple documentation of what it has found. You are probably safe to assume it will also work in newer versions. Restricting it to a particular version would not be a good decision in my opinion.

Supposed you have a processor that checks every element it can find and analyses the code structure to generate a graph out of it. You may get problems with newer versions. You may be able to handle unknown language constructs somehow (like by adding a unknown node to the graph) but only do this if that makes sense - and if it's worth the trouble. If the processor just wouldn't be useful any more when confronted with something unknown, it should probably stick to a particular java version.

Regardless of the policy used, the best way in my opinion would be to monitor upcoming changes to the language and update the processor accordingly. In Java 7 for example, project coin introduced some new language features, which are most likely not even visible to a processor. Java 8 on the other hand does have new constructs that will affect processing, for example type annotations. New language features don't happen that often though, so Chances are that you don't even need to change anything for a long time.