Skip to content

Walk JavaType refs embedded in annotation element values#7426

Merged
knutwannheden merged 1 commit intomainfrom
visit-annotation-element-values
Apr 19, 2026
Merged

Walk JavaType refs embedded in annotation element values#7426
knutwannheden merged 1 commit intomainfrom
visit-annotation-element-values

Conversation

@knutwannheden
Copy link
Copy Markdown
Contributor

@knutwannheden knutwannheden commented Apr 19, 2026

What's changed?

JavaTypeVisitor.visitAnnotation only visited annotation.getType(), leaving the refs inside element values untouched: the element meta-variable and SingleElementValue.referenceValue / ArrayElementValue.referenceValues. Any downstream visitor that relies on the full-graph walk (dedup, type remappers, serializers, …) sees non-canonical instances inside annotation values while the rest of the type graph is consistent.

Adds visitAnnotationElementValue, which visits the element meta-variable and the reference-value branch, and reconstructs the ElementValue only when a returned instance changed identity. UnsafeJavaTypeVisitor inherits the new behaviour through the default visitAnnotation.

Constant values are deliberately not visited: SingleElementValue.from / ArrayElementValue.from route any JavaType-valued argument into the reference branch, so constants only ever hold primitives, strings, and enums in parser-produced LSTs.

What's your motivation?

Downstream at Moderne, a recipe run against a large multi-module LST failed deserializing a method's annotations — the meta.bin type table referenced an index past its own end. Root cause was our JavaTypeDeduplicationVisitor inheriting this visit gap: annotation-value refs stayed as pre-canonical instances while the rest of the type graph was deduped, so the writer's identity-keyed map treated them as fresh types after the offset table had already been sized.

Fixing only in our downstream visitor leaves the gap in every other JavaTypeVisitor subclass, which is why this PR is here.

Anything in particular you'd like reviewers to focus on?

  • Whether the "no constants" decision matches your understanding of the from(...) factories.
  • The ArrayElementValue reference-values loop returns the same array when every visited element is identity-equal, and only clones when at least one changed.

JavaTypeVisitor.visitAnnotation only visited annotation.getType(),
leaving any JavaType refs in element values untouched: the element
meta-variable, SingleElementValue.referenceValue,
SingleElementValue.constantValue (when it's a JavaType), and
ArrayElementValue's referenceValues / JavaType-valued constantValues.

Downstream visitors that rely on the full-graph walk (dedup, type
remappers, serializers) silently see non-canonical instances inside
annotation values while the rest of the type graph is consistent.

Adds visitAnnotationElementValue, which visits every ref kind and
reconstructs the ElementValue only when a returned instance differs.
UnsafeJavaTypeVisitor inherits this via the default visitAnnotation.
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Apr 19, 2026
@knutwannheden knutwannheden changed the title Walk JavaType refs embedded in annotation element values Walk JavaType refs embedded in annotation element values Apr 19, 2026
@knutwannheden knutwannheden merged commit fd8e2bf into main Apr 19, 2026
1 check passed
@knutwannheden knutwannheden deleted the visit-annotation-element-values branch April 19, 2026 19:17
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant