[
https://issues.apache.org/jira/browse/GROOVY-12723?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18140185#comment-18140185
]
ASF GitHub Bot commented on GROOVY-12723:
-----------------------------------------
codeconsole opened a new pull request, #3258:
URL: https://github.com/apache/groovy/pull/3258
https://issues.apache.org/jira/browse/GROOVY-12723
`ModifiesASTTransformation` rejected a bare `@Modifies` ("@Modifies requires
a closure listing the modifiable targets; use @Modifies({}) to declare that
nothing is modified") but took any other value that is not a closure, a list of
strings for one, as an empty frame: `extractFromAnnotation` returned on a
non-closure member, and `visit` then replaced the member with a class
reference, so the annotation verifier never saw the original value. With
`ModifiesChecker` on, `@Modifies(['this.stock', 'this.log'])` on a method that
assigns `stock` was reported as "@Modifies violation: assignment to 'stock' but
'stock' is not declared in @Modifies", the opposite of what the source says;
without the checker it compiled with a frame that declared nothing.
Every value that is not a `ClosureExpression` now gets the bare form's
error, at the annotation, with the value found appended ("; found [this.stock,
this.log]").
Test:
`ModifiesTests.modifies_with_a_list_of_strings_is_rejected_like_a_bare_modifies`,
beside the existing bare-annotation test. `ModifiesTests` (16) and
`ModifiesCheckerTest` (26) pass locally.
> @Modifies with a value that is not a closure is silently an empty frame,
> which ModifiesChecker then reports as violated
> -----------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12723
> URL: https://issues.apache.org/jira/browse/GROOVY-12723
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> {{ModifiesASTTransformation}} rejects a bare {{@Modifies}} ("@Modifies
> requires a closure listing the modifiable targets; use @Modifies({}) to
> declare that nothing is modified") but accepts any other value that is not a
> closure in silence: {{extractFromAnnotation}} returns when the member is not
> a {{ClosureExpression}}, the frame stays empty, and {{visit}} then replaces
> the member with a class reference, so the annotation verifier never sees the
> original value either. With {{ModifiesChecker}} on, the method is checked
> against that empty frame:
> {code:groovy}
> import groovy.contracts.Modifies
> import groovy.transform.CompileStatic
> @CompileStatic(extensions = 'groovy.typecheckers.ModifiesChecker')
> class Inventory {
> int stock = 0
> List<String> log = []
> @Modifies(['this.stock', 'this.log'])
> void restock(int amount) {
> stock += amount
> log.add('restock ' + amount)
> }
> }
> {code}
> {noformat}
> [Static type checking] - @Modifies violation: assignment to 'stock' but
> 'stock' is not declared in @Modifies
> {noformat}
> The message says the opposite of what the source says, and without the
> checker the class compiles with a frame that declares nothing. Expected: the
> error a bare {{@Modifies}} gets, at the annotation, naming what was found.
> A list of strings is the first thing a language model writes for this
> annotation (three of three runs, with the contracts documentation summarised
> in front of it, in the seventh live run of the groovyai eval). The fix is one
> condition in {{visit}}: a value that is not a {{ClosureExpression}} gets the
> existing message plus "; found ['this.stock', 'this.log']".
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)