groovy
  1. groovy
  2. GROOVY-4339

Compiler first allows an annotation on a statement, then fails with a weird error message

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 3.0
    • Component/s: class generator
    • Labels:
      None
    • Number of attachments :
      0

      Description

      int i
      
      @Deprecated
      i = 2
      

      Snippet above fails with

      _.groovy: 4: The current scope already contains a variable of the name i
       @ line 4, column 1.
         i = 2
      

      It should better say that an annotation is not allowed/handled where it is specified.

        Activity

        Hide
        Paul King added a comment -

        Two additional issues sounds good to me. Even though some of these aspects have been discussed before, I don't recall either (2) or (3) having specific Jira issues.

        Show
        Paul King added a comment - Two additional issues sounds good to me. Even though some of these aspects have been discussed before, I don't recall either (2) or (3) having specific Jira issues.
        Hide
        blackdrag blackdrag added a comment -

        The examples you have discussed till now are all centered about scripts, buttry to think about it in the context of a class. Afaik that is the only context this is used like this. But of course once the user knows, the user may choose to use it in a script context as well. The class context is also where it is possible t get the information if the rentention policy is set accordingly. Anyway...

        If we, at one time, really want to support annotations evrywhere, then this is in the way for the script context. There is no JIRA for this, but we discussed it several times and seem to want to have it. So I agree with Roshan on this one...

        For (1)... I can imagine Doug Lea wanting something like a @UnchangedFromHere annotation on a variable, without declaration.

        All in all I am in favor for no longer allowing this. Arguably we can allow it in the class context.

        Show
        blackdrag blackdrag added a comment - The examples you have discussed till now are all centered about scripts, buttry to think about it in the context of a class. Afaik that is the only context this is used like this. But of course once the user knows, the user may choose to use it in a script context as well. The class context is also where it is possible t get the information if the rentention policy is set accordingly. Anyway... If we, at one time, really want to support annotations evrywhere, then this is in the way for the script context. There is no JIRA for this, but we discussed it several times and seem to want to have it. So I agree with Roshan on this one... For (1)... I can imagine Doug Lea wanting something like a @UnchangedFromHere annotation on a variable, without declaration. All in all I am in favor for no longer allowing this. Arguably we can allow it in the class context.
        Hide
        Paul King added a comment -

        Some interesting (2008 vintage) presentations:

        http://www.cs.rice.edu/~mgricken/research/xajavac/download/annotation-poster-2008.pdf
        http://www.cs.rice.edu/~mgricken/research/xajavac/download/Java%20Annotations%20for%20Types%20and%20Expressions.ppt

        The ppt has a summary of the new annotation targets in JSR-308.
        Of particular interest is some proposed extensions beyond JSR-308, e.g.:

        @Contained {
          // block annotation
          // block of code that does not spawn async. tasks
        }
        int i = -5;
        int j = @AlwaysPositive (i*i); // paren. expression annotation
        

        And also some suggestions for removing ambiguities that arise when applying annotations to more targets.

        Show
        Paul King added a comment - Some interesting (2008 vintage) presentations: http://www.cs.rice.edu/~mgricken/research/xajavac/download/annotation-poster-2008.pdf http://www.cs.rice.edu/~mgricken/research/xajavac/download/Java%20Annotations%20for%20Types%20and%20Expressions.ppt The ppt has a summary of the new annotation targets in JSR-308. Of particular interest is some proposed extensions beyond JSR-308, e.g.: @Contained { // block annotation // block of code that does not spawn async. tasks } int i = -5; int j = @AlwaysPositive (i*i); // paren. expression annotation And also some suggestions for removing ambiguities that arise when applying annotations to more targets.
        Hide
        Paul King added a comment - - edited

        Also, an example which currently runs which we can use to discuss which bits (if any) we would like to make no longer valid:

        import java.lang.annotation.*
        import groovy.transform.*
        
        @Retention(RetentionPolicy.SOURCE)
        @Target(ElementType.LOCAL_VARIABLE)
        public @interface NonNegative {}
        
        @Retention(RetentionPolicy.SOURCE)
        // ElementType.BINARY_EXPRESSION is hypothetical extension
        @Target([ElementType.LOCAL_VARIABLE/*, ElementType.BINARY_EXPRESSION*/])
        public @interface Trace {}
        
        class Foo {
          def items = []
          def bar() {
            @Lazy a = 1
            @PackageScope b = 2
            @NonNegative c = 3
            @Trace d = 4
            //@Trace d = 5
            items += [a, b, c, d]
          }
        }
        
        @Lazy u = 6
        @PackageScope v = 7
        @ScriptField w = 8
        @NonNegative x = 9
        @Trace y = 10
        //@Trace y = 11
        @Grab('com.google.collections:google-collections:1.0')
        z = new com.google.common.collect.HashBiMap(a:1)
        
        assert u == 6
        assert v == 7
        assert w == 8
        assert x == 9
        assert y == 10 // 11
        assert z.inverse()[1] == 'a'
        
        def f = new Foo()
        f.bar()
        assert f.items == [1, 2, 3, 4 /* 5 */]
        

        Notes:

        • ElementType.BINARY_EXPRESSION is just one possible suggestion. Might be better to be more specific, e.g. just on assignment or more general, e.g. on any expression.
        • @Trace is made up and intended to log or print output similar to what PowerAssert gives us but without comparing two sides - just the result of the expression
        • @NonNegative is made up here but JSR-305 and many other packages already have similar annotations. It might indicate that a local variable or field will only contain zero or positive values. It might be used for optimisation or runtime validation checks.
        • @PackageScope is a bit of an outlier - shouldn't be controversial, it is highlighting that we aren't picking up that it is placed on a LOCAL_VARIABLE instead of a FIELD
        • @Lazy is also a bit odd. Hard to tell what it might mean for a local variable but in theory we might have some AST transforms that are applicable to LOCAL_VARIABLEs.
        • @Grab currently works on LOCAL_VARIABLEs (among other things).
        Show
        Paul King added a comment - - edited Also, an example which currently runs which we can use to discuss which bits (if any) we would like to make no longer valid: import java.lang.annotation.* import groovy.transform.* @Retention(RetentionPolicy.SOURCE) @Target(ElementType.LOCAL_VARIABLE) public @ interface NonNegative {} @Retention(RetentionPolicy.SOURCE) // ElementType.BINARY_EXPRESSION is hypothetical extension @Target([ElementType.LOCAL_VARIABLE/*, ElementType.BINARY_EXPRESSION*/]) public @ interface Trace {} class Foo { def items = [] def bar() { @Lazy a = 1 @PackageScope b = 2 @NonNegative c = 3 @Trace d = 4 //@Trace d = 5 items += [a, b, c, d] } } @Lazy u = 6 @PackageScope v = 7 @ScriptField w = 8 @NonNegative x = 9 @Trace y = 10 //@Trace y = 11 @Grab('com.google.collections:google-collections:1.0') z = new com.google.common.collect.HashBiMap(a:1) assert u == 6 assert v == 7 assert w == 8 assert x == 9 assert y == 10 // 11 assert z.inverse()[1] == 'a' def f = new Foo() f.bar() assert f.items == [1, 2, 3, 4 /* 5 */] Notes: ElementType.BINARY_EXPRESSION is just one possible suggestion. Might be better to be more specific, e.g. just on assignment or more general, e.g. on any expression. @Trace is made up and intended to log or print output similar to what PowerAssert gives us but without comparing two sides - just the result of the expression @NonNegative is made up here but JSR-305 and many other packages already have similar annotations. It might indicate that a local variable or field will only contain zero or positive values. It might be used for optimisation or runtime validation checks. @PackageScope is a bit of an outlier - shouldn't be controversial, it is highlighting that we aren't picking up that it is placed on a LOCAL_VARIABLE instead of a FIELD @Lazy is also a bit odd. Hard to tell what it might mean for a local variable but in theory we might have some AST transforms that are applicable to LOCAL_VARIABLEs. @Grab currently works on LOCAL_VARIABLEs (among other things).
        Hide
        blackdrag blackdrag added a comment -

        I changed the fix target of this to 2.0 with the intention to make an annotation on an assignment not be a declaration. Since that is a breaking change the only scope this can be done is Groovy 2.0

        Show
        blackdrag blackdrag added a comment - I changed the fix target of this to 2.0 with the intention to make an annotation on an assignment not be a declaration. Since that is a breaking change the only scope this can be done is Groovy 2.0

          People

          • Assignee:
            Unassigned
            Reporter:
            Roshan Dawrani
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: