Skip to content

Fix Java parser for annotated varargs by adding marker on J.ArrayType, as opposed to field on J.VariableDeclarations#6098

Open
knutwannheden wants to merge 17 commits intomainfrom
java-varargs-annotations
Open

Fix Java parser for annotated varargs by adding marker on J.ArrayType, as opposed to field on J.VariableDeclarations#6098
knutwannheden wants to merge 17 commits intomainfrom
java-varargs-annotations

Conversation

@knutwannheden
Copy link
Copy Markdown
Contributor

@knutwannheden knutwannheden commented Oct 1, 2025

Using a new Varargs marker.

TODO:

  • Fix all parsers
  • Phase out varargs field

Using a new `Varargs` marker.
@timtebeek
Copy link
Copy Markdown
Member

Let me know if you'd like help replicating this pattern to the Java 8, 11, 17 and 25 parsers. Would be good to see this resolved.

@timtebeek timtebeek added the bug Something isn't working label Dec 24, 2025
Copy link
Copy Markdown
Member

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved from my side; anything that had made you held off on merging?

I'd seen this fail in a number of projects, including when serializing the LST, so figured good to clear out.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Dec 24, 2025
@timtebeek timtebeek marked this pull request as ready for review December 31, 2025 10:14
"""
class Test {
void method(String first, int... values) {}
void method(String first, int ... values) {}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above we had two spaces; after normalization we are now left with one instead of zero. I think that's fine?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, intentional — SpacesVisitor doesn't have a rule that strips the space, just normalizes it. Going from two spaces to one is the expected behavior.

Comment on lines +6112 to 6114
@Deprecated
@ToBeRemoved(after = "2026-04-01")
Space varargs;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still used once with a non-null value in the Groovy parser, but figured we can revise that if/when we decide to drop the field. Most other cases it's null already, and then there will be the long tail of deserialization support.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated based on the cross-language audit (see main thread comment): keeping @Deprecated (right signal for Java recipe authors — use the marker), but removed @ToBeRemoved since JS/TS, Python, and Go are all actively using the field for their own native varargs syntax. Removal needs the cross-language migration tracked above.

@timtebeek timtebeek changed the title Parse Java varargs annotations Fix Java parser for annotated varargs by adding marker on J.ArrayType, as opposed to field on J.VariableDeclarations Jan 5, 2026
@timtebeek timtebeek requested a review from jkschneider January 5, 2026 11:49
@timtebeek
Copy link
Copy Markdown
Member

Tagging Jonathan for review since we're adding a marker to the LST model, and deprecating a field (not yet removed).

Comment on lines +25 to +33
* Indicates that a {@link org.openrewrite.java.tree.J.ArrayType} represents a varargs parameter type.
* When present, the array type should be printed using {@code ...} syntax instead of {@code []}.
* <p>
* For example, {@code String...} instead of {@code String[]}.
*/
@Value
@With
public class Varargs implements Marker {
UUID id;
Copy link
Copy Markdown
Member

@timtebeek timtebeek Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This marker could use a review before we merge, since we're adding a marker for what used to be a field.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sam reviewed on Apr 1 — marking resolved.

Copy link
Copy Markdown
Member

@sambsnyd sambsnyd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically all languages have some concept of varargs. Can we standardize this across all of them? Assuming it's agreed this is the way to go.

@greg-at-moderne
Copy link
Copy Markdown
Contributor

greg-at-moderne commented Apr 8, 2026

all languages have some concept of varargs. Can we standardize this across all of them?

Just to help with the discussion, I think below is a fair description of current state of affairs. TLDR: it's fairly consistent.

  • Java: varargs field of type Space on J.VariableDeclarations, this PR aims to change it to a marker
  • JS/TS: same varargs field of type Space on J.VariableDeclarations, plus custom JS.Spread for ... call-site syntax
  • Python: same varargs field of type Space on J.VariableDeclarations (*args, **kwargs), plus custom Py.Star for call-sites
  • C#: the language has different syntax: params, stored as a J.Modifier
  • Go: same varargs field of type Space on J.VariableDeclarations
  • Scala: not implemented yet (?)
  • Kotlin: the language has different syntax: vararg, stored as a J.Modifier
  • Groovy: varargs field of type Space on J.VariableDeclarations

Comment:

  • I think it's fair to call it fairly consistent, even if not ideal
  • I understand Sam's comment as a call for changing other parsers to be in line with Java, if we decide to make the change for Java

JS/TS, Python, and Go all use this field for their own native
varargs/star-args syntax (rest parameters, `*args`/`**kwargs`,
variadic types). Removing the field requires coordinated migration
across all five frontends, so a fixed removal date isn't realistic.
The `@Deprecated` annotation remains.
@knutwannheden
Copy link
Copy Markdown
Contributor Author

Thanks @greg-at-moderne for the survey — couple of corrections after digging into each.

Scala is implemented, but not using the varargs field for varargs. It repurposes the Space slot to store whitespace before the colon in field type ascription (ScalaTreeVisitor.scala:2772, e.g. given IntSchema : SchemaFor[Int]). Cleaning that up is independent of varargs and can be its own small PR (probably an S.SpaceBeforeColon marker on J.VariableDeclarations).

The other languages share a more interesting pattern: JS/TS, Python, and Go all actively read/write this same field for their own native varargs syntax, not just relay it over RPC:

  • JS/TS prints ...args rest parameters (print.ts:497-499)
  • Python prints *args/**kwargs (printer.py:1852-1854 — the Space is the whitespace before *)
  • Go prints variadic ...T (go_printer.go:332-334)

So this isn't a Java field that other languages happen to relay — it's a shared whitespace bucket every variable-declaration-having frontend is squatting on. Only C# is pure relay (it uses a params modifier natively).

That reshapes the plan. I think the right path is: land this PR as Java-only now, then track the cross-language work separately:

  1. Java (this PR) — Varargs marker on J.ArrayType
  2. Groovy — same pattern (also String... syntax)
  3. JS/TS — marker on the rest-parameter representation
  4. Python — dedicated field/marker for * / **
  5. Go — marker on variadic-param representation
  6. Scala — orthogonal: stop misusing the field for : whitespace

Once 1–5 land we can drop the field; until then it stays. I've also dropped the @ToBeRemoved(after = "2026-04-01") annotation in the latest push — no realistic removal date until the cross-language migration completes, and a stale date is worse than none. I'll open a tracking issue for 2–6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working java parser

Projects

Status: Ready to Review

Development

Successfully merging this pull request may close these issues.

Parse error in Java parser when using type annotation with varags Parser: not idempotent on annotated varargs

4 participants