Groovy
  1. Groovy
  2. GROOVY-2827

org.codehaus.groovy.ast.expr.PropertyExpression when using external constants in annotations

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 1.5.6
    • Fix Version/s: None
    • Component/s: ast builder
    • Labels:
      None

      Description

      On annotation attributes, when assigning a constant with a "." in its name (as is the case when the constant is defined in a different class than the one being compiled), groovy generates org.codehaus.groovy.ast.expr.PropertyExpression.

      See simple test case below.

      — Tag.java

      package pkg;
      
      import java.lang.annotation.Target;
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.METHOD,ElementType.FIELD})
      public @interface Tag {
              String value() default "";
      }
      

      — TagType.java

      package pkg;
      
      import org.apache.log4j.Logger;
      
      public class TagType {
              private final static Logger theLogger = Logger.getLogger(TagType.class);
              public static final String TAG_1 = "tag_1";
              public static final String TAG_2 = "tag_2";
      }
      

      — GroovyClassWithAnnotationsAndConstants.groovy

      package pkg;
      
      import pkg.Tag;
      import pkg.TagType
      
      class GroovyClassWithAnnotationsAndConstants {
      
              int myIntField;
      
              @Tag( value = TagType.TAG_1) // this will not compile and generate org.codehaus.groovy.ast.expr.PropertyExpression
              //@Tag( value = "tag_1") //the commented version, which uses a string literal does compile
              public int getIntField() {
                      return myIntField;
              }
      
              public void setIntField(int value) {
                      myIntField = value;
              }
      }
      

        Issue Links

          Activity

          Transition Time In Source Status Execution Times Last Executer Last Execution Date
          Open Open Resolved Resolved
          397d 2h 3m 1 Paul King 16/Jun/09 07:21
          Resolved Resolved Closed Closed
          121d 9h 58m 1 Paul King 15/Oct/09 17:19
          Mark Thomas made changes -
          Workflow jira [ 12973421 ] Default workflow, editable Closed status [ 12980648 ]
          Mark Thomas made changes -
          Project Import Mon Apr 06 02:11:23 UTC 2015 [ 1428286283443 ]
          Mark Thomas made changes -
          Workflow jira [ 12731847 ] Default workflow, editable Closed status [ 12743762 ]
          Mark Thomas made changes -
          Project Import Sun Apr 05 13:32:57 UTC 2015 [ 1428240777691 ]
          Paul King made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Paul King made changes -
          Resolution Duplicate [ 3 ]
          Status Open [ 1 ] Resolved [ 5 ]
          Hide
          Paul King added a comment -

          Checked into it further and this is indeed a duplicate of GROOVY-3278. Other notes in that issue.

          Show
          Paul King added a comment - Checked into it further and this is indeed a duplicate of GROOVY-3278 . Other notes in that issue.
          Paul King made changes -
          Link This issue is duplicated by GROOVY-3278 [ GROOVY-3278 ]
          Hide
          Guillaume Delcroix added a comment -

          Additional test we could add to AnnotationTest and improve:

              void testUsingClassStaticPublicFieldsAsAnnotationParameterValue() {
                  assertScript """
                      import java.lang.annotation.*
          
                      @Retention(RetentionPolicy.RUNTIME)
                      @Target([ElementType.METHOD, ElementType.FIELD])
                      @interface Tag {
                          String value() default ""
                          String[] array() default []
                      }
          
                      class TagType {
                          public static final String TAG_ONE = "1"
                          public static final String[] TAG_TWO = ["2a", "2b"]
                      }
          
                      class GroovyClassWithAnnotationsAndConstants {
          
                          @Tag(TagType.TAG_ONE)
                          private String annotatedField
          
                          @Tag(value = TagType.TAG_ONE)
                          void annotatedMethod() { }
          
                          @Tag(array = TagType.TAG_TWO)
                          String annotatedProperty
          
                          @Tag(array = TagType.TAG_TWO)
                          int otherAnnotatedMethod(int i) { i }
          
                          @Tag(array = TagType.TAG_ONE)
                          String helloAnnotatedMethod() { "hello" }
          
                          @Tag(array = [TagType.TAG_ONE])
                          String hiAnnotatedMethod() { "hi" }
          
                          @Tag(array = [TagType.TAG_ONE, TagType.TAG_ONE])
                          String byeAnnotatedMethod() { "bye" }
                      }
          
                      assertEquals TagType.TAG_ONE, GroovyClassWithAnnotationsAndConstants.class.getDeclaredField('annotatedField').annotations[0].value()
                      // more asserts here
                  """
              }
          
          
          Show
          Guillaume Delcroix added a comment - Additional test we could add to AnnotationTest and improve: void testUsingClassStaticPublicFieldsAsAnnotationParameterValue() { assertScript """ import java.lang.annotation.* @Retention(RetentionPolicy.RUNTIME) @Target([ElementType.METHOD, ElementType.FIELD]) @ interface Tag { String value() default "" String [] array() default [] } class TagType { public static final String TAG_ONE = "1" public static final String [] TAG_TWO = [ "2a" , "2b" ] } class GroovyClassWithAnnotationsAndConstants { @Tag(TagType.TAG_ONE) private String annotatedField @Tag(value = TagType.TAG_ONE) void annotatedMethod() { } @Tag(array = TagType.TAG_TWO) String annotatedProperty @Tag(array = TagType.TAG_TWO) int otherAnnotatedMethod( int i) { i } @Tag(array = TagType.TAG_ONE) String helloAnnotatedMethod() { "hello" } @Tag(array = [TagType.TAG_ONE]) String hiAnnotatedMethod() { "hi" } @Tag(array = [TagType.TAG_ONE, TagType.TAG_ONE]) String byeAnnotatedMethod() { "bye" } } assertEquals TagType.TAG_ONE, GroovyClassWithAnnotationsAndConstants.class.getDeclaredField('annotatedField').annotations[0].value() // more asserts here """ }
          Guillaume Delcroix made changes -
          Field Original Value New Value
          Description On annotation attributes, when assigning a constant with a "." in its name (as is the case when the constant is defined in a different class than the one being compiled), groovy generates org.codehaus.groovy.ast.expr.PropertyExpression.

          See simple test case below.

          --- Tag.java
          package pkg;

          import java.lang.annotation.Target;
          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;


          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.METHOD,ElementType.FIELD})
          public @interface Tag {
                  String value() default "";
          }
          --- TagType.java
          package pkg;

          import org.apache.log4j.Logger;

          public class TagType {
                  private final static Logger theLogger = Logger.getLogger(TagType.class);
                  public static final String TAG_1 = "tag_1";
                  public static final String TAG_2 = "tag_2";
          }
          --- GroovyClassWithAnnotationsAndConstants.groovy
          package pkg;

          import pkg.Tag;
          import pkg.TagType

          class GroovyClassWithAnnotationsAndConstants {

                  int myIntField;

                  @Tag( value = TagType.TAG_1) // this will not compile and generate org.codehaus.groovy.ast.expr.PropertyExpression
                  //@Tag( value = "tag_1") //the commented version, which uses a string literal does compile
                  public int getIntField() {
                          return myIntField;
                  }

                  public void setIntField(int value) {
                          myIntField = value;
                  }
          }
          On annotation attributes, when assigning a constant with a "." in its name (as is the case when the constant is defined in a different class than the one being compiled), groovy generates org.codehaus.groovy.ast.expr.PropertyExpression.

          See simple test case below.

          --- Tag.java
          {code}
          package pkg;

          import java.lang.annotation.Target;
          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;


          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.METHOD,ElementType.FIELD})
          public @interface Tag {
                  String value() default "";
          }
          {code}
          --- TagType.java
          {code}
          package pkg;

          import org.apache.log4j.Logger;

          public class TagType {
                  private final static Logger theLogger = Logger.getLogger(TagType.class);
                  public static final String TAG_1 = "tag_1";
                  public static final String TAG_2 = "tag_2";
          }
          {code}
          --- GroovyClassWithAnnotationsAndConstants.groovy
          {code}
          package pkg;

          import pkg.Tag;
          import pkg.TagType

          class GroovyClassWithAnnotationsAndConstants {

                  int myIntField;

                  @Tag( value = TagType.TAG_1) // this will not compile and generate org.codehaus.groovy.ast.expr.PropertyExpression
                  //@Tag( value = "tag_1") //the commented version, which uses a string literal does compile
                  public int getIntField() {
                          return myIntField;
                  }

                  public void setIntField(int value) {
                          myIntField = value;
                  }
          }
          {code}
          Xavier Sautejeau created issue -

            People

            • Assignee:
              Guillaume Delcroix
              Reporter:
              Xavier Sautejeau
            • Votes:
              1 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development