Groovy annotation processing skips fields

I found a serious problem with the new Groovy annotation processing feature.

Let’s say we have the following Groovy class:

@CompileStatic
@EActivity(R.layout.main)
public class HelloAndroidActivity extends Activity {
   @StringRes
   String hello

   @ViewById
   TextView helloTextView

   @UiThread
   @AfterViews
   void afterViews() {
      Date now = new Date();
      String helloMessage = String.format(hello, now.toString())
      helloTextView.setText(helloMessage)
   }
}

From this class, the following Groovy stub is generated:

@groovy.transform.CompileStatic() @org.androidannotations.annotations.EActivity(value=org.androidannotations.gradle.R.layout.main) public class HelloAndroidActivity
  extends android.app.Activity  implements
    groovy.lang.GroovyObject {
;
public  groovy.lang.MetaClass getMetaClass() { return (groovy.lang.MetaClass)null;}
public  void setMetaClass(groovy.lang.MetaClass mc) { }
public  java.lang.Object invokeMethod(java.lang.String method, java.lang.Object arguments) { return null;}
public  java.lang.Object getProperty(java.lang.String property) { return null;}
public  void setProperty(java.lang.String property, java.lang.Object value) { }
public  java.lang.String getHello() { return (java.lang.String)null;}
public  void setHello(java.lang.String value) { }
public  android.widget.TextView getHelloTextView() { return (android.widget.TextView)null;}
public  void setHelloTextView(android.widget.TextView value) { }
@org.androidannotations.annotations.UiThread() @org.androidannotations.annotations.AfterViews() public  void afterViews() { }
}

As you can see, getters and setters are generated for the fields, but the fields are not themselves. And this way all the annotations on the fields are list, and will be skipped during annotation processing.

I know this problem is originated from the Groovy stub generator, and not Gradle. I really do not know the stub generator, but i guess fields are not generated for a reason. So if this must be fixed in Groovy, the Gradle team should explain it to them.

I created an example project, it uses the AndroidAnnotations processor. You can observe in the build log, that the processor only finds 3 annotations instead of 5, and you can also check out the generated Java stub (which is copied above).

UPDATE: I created a smaller test project here.

This is indeed a Groovy “problem” and not a Gradle one. With the annotation processing feature, we’re actually “abusing” an implementation detail of Groovy (stubs). In your case, you are annotating properties (not fields), and for properties, the annotation is actually carried by the field. Stubs are meant for joint compilation, which doesn’t need any field generation. In this case, I would suggest that you put this thread on the Groovy user mailing list.

Best regards,

Excellent point! Please note i am obviously not a Groovy expert, i am coming from the Java and annotation processing world. Actually i did not realize that i am using a property… This can be easily fixed: put the annotations on fields, and not properties.

@StringRes
protected String hello

Unfortunately @PackageScope is not working, i guess the transformation runs after the Java stub generation (or the generation is buggy in case of @PackageScope?). So it means only private, public or protected fields can be used.