[
https://issues.apache.org/jira/browse/GROOVY-12701?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King resolved GROOVY-12701.
--------------------------------
Fix Version/s: 7.0.0-alpha-1
6.0.1
Resolution: Fixed
> @ASTTest on a declaration with several declarators fails with "BUG! ... Tried
> to overwrite existing meta data"
> --------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12701
> URL: https://issues.apache.org/jira/browse/GROOVY-12701
> Project: Groovy
> Issue Type: Bug
> Components: Compiler
> Affects Versions: 4.0.32, 5.1.3, 6.0.0
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
> Fix For: 7.0.0-alpha-1, 6.0.1
>
>
> h3. Description
> {{@ASTTest}} on a local variable declaration or field declaration with more
> than one declarator makes the compiler fail with a {{GroovyBugError}},
> whatever the test closure does:
> {code:groovy}
> import groovy.transform.ASTTest
> import org.codehaus.groovy.ast.expr.DeclarationExpression
> def m() {
> @ASTTest(value={
> assert node instanceof DeclarationExpression
> })
> def a = 1, b = 2
> a + b
> }
> println m()
> {code}
> {noformat}
> BUG! exception in phase 'semantic analysis' in source unit '...' Tried to
> overwrite existing meta data
> org.codehaus.groovy.ast.AnnotationNode@...[@groovy.transform.ASTTest(phase=...,
> value={ ... })].
> {noformat}
> The same happens for fields:
> {code:groovy}
> import groovy.transform.ASTTest
> class F {
> @ASTTest(value={
> assert node.name in ['x', 'y']
> })
> int x = 1, y = 2
> }
> {code}
> and for any {{phase}}. A single declarator ({{def a = 1}}) and a multiple
> assignment ({{def (a, b) = [1, 2]}}) work.
> Expected: the test closure runs once for each declared variable or field,
> with {{node}} bound to that declaration, as other local AST transformations
> are invoked for each declarator.
> Reproduced with 4.0.32, 5.1.3, 6.0.0 and master.
> h3. Cause
> The parser attaches the same {{AnnotationNode}} instance to every declarator
> of the declaration ({{def a = 1, b = 2}} becomes two
> {{DeclarationExpression}}s, {{int x = 1, y = 2}} two {{FieldNode}}s, sharing
> the annotation). {{ASTTransformationVisitor}} therefore calls
> {{ASTTestTransformation#visit}} once per declarator with the same annotation
> node.
> On the first call, {{ASTTestTransformation}} moves the test closure out of
> the annotation into node metadata and replaces the {{value}} member with an
> empty closure:
> {code:groovy}
> annotationNode.setNodeMetaData(ASTTestTransformation, member)
> annotationNode.setMember('value', new
> ClosureExpression(Parameter.EMPTY_ARRAY, EmptyStatement.INSTANCE))
> {code}
> On the second call {{setNodeMetaData}} finds the key already set and throws.
> Even if it did not, it would store the empty replacement closure as the test.
> h3. Suggested fix
> In {{ASTTestTransformation#visit}}, do the conversion only the first time an
> annotation node is seen: if the node metadata is already set, reuse the
> stored test closure, skip the {{value}} checks and the replacement, and
> register an {{ASTTester}} for the current node ({{nodes[1]}}). The {{phase}}
> member is already rewritten into a form that the second call reads correctly.
> This is a general hazard for local transformations that keep state on the
> annotation node: with several declarators, the same annotation node is passed
> for each annotated node.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)