Skip to content

C#: Parse attribute lists on type declarations#6971

Merged
knutwannheden merged 5 commits intomainfrom
fix-csharp-parser-type-declaration-attributes
Mar 12, 2026
Merged

C#: Parse attribute lists on type declarations#6971
knutwannheden merged 5 commits intomainfrom
fix-csharp-parser-type-declaration-attributes

Conversation

@knutwannheden
Copy link
Contributor

@knutwannheden knutwannheden commented Mar 12, 2026

Summary

  • Parse node.AttributeLists in VisitTypeDeclaration, VisitEnumDeclaration, VisitStructDeclaration, and VisitRecordDeclaration — previously attributes on type declarations were silently absorbed into whitespace
  • Wrap type declarations in AnnotatedStatement when attributes are present
  • Add Space.FormatWithComments to parse /* */ and // comments into structured Comment entries
  • Switch ExtractPrefix, ExtractSpaceBefore, and ExtractRemaining to use FormatWithComments so all Space objects in the tree have structured comments
  • Fix VisitSpace print order to emit Whitespace before Comments (matching Java's JavaPrinter convention)
  • Update DirectiveBoundaryInjector to scan Space.Comments for ghost comment text instead of regex on Space.Whitespace
  • Add flyweight cache (ConcurrentDictionary) for commentless Space objects with whitespace ≤ 50 chars, matching Java's approach
  • Add parser-local Dictionary cache to skip re-parsing repeated whitespace patterns (same indentation on every line)

Test plan

  • All 72 Java-side CSharpRpcTest tests pass (including 8 directive-related tests that exercise the updated DirectiveBoundaryInjector)
  • New roundtrip tests: [Serializable] class, [Obsolete("msg")] public class, [Serializable] struct, [Flags] enum
  • Structured comment assertion: [Serializable(/*bar*/)] produces Comment with Multiline=true, Text="bar"
  • Existing ClassDeclarationTests with extra whitespace and attributes continue to pass

…space handling

- Parse `node.AttributeLists` in `VisitTypeDeclaration` and wrap the
  `ClassDeclaration` in an `AnnotatedStatement` when attributes are present.
  Previously, attribute text was absorbed into whitespace prefixes.
- Parse `node.AttributeLists` in `VisitEnumDeclaration` and pass them to
  the `EnumDeclaration` constructor.
- Handle `AnnotatedStatement` wrapping in `VisitStructDeclaration` and
  `VisitRecordDeclaration` when adding Struct/RecordClass markers.
- Add `VisitAnnotatedStatement` to `CSharpPrinter` so attributed type
  declarations print correctly.
- Fix `VisitAttributeList` to capture space before closing `]` in the
  last attribute's `JRightPadded.After`, and print it in the printer.
- Preserve comments inside empty attribute argument lists (e.g.
  `[Foo(/*bar*/)]`) by creating a `J.Empty` element in the `JContainer`.
- Add `Space.FormatWithComments` to parse `/* */` and `//` comments into
  structured `Comment` entries rather than raw whitespace.
…ting

- Fix crash in FormatWithComments on consecutive multiline comments
  (e.g. /*a*//*b*/) by resetting `last` to '\0' after closing a comment
- Fix standalone '*' outside comment context being routed to comment
  buffer instead of prefix
- Mark unterminated multiline comments as multiline in the Comment entry
- Add explanatory comment for the suffix/prefix rotation loop
- Print attribute lists in VisitEnumDeclaration in the printer
- Add roundtrip tests for attributes on struct and enum declarations
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Mar 12, 2026
@knutwannheden knutwannheden changed the title C#: Parse AttributeLists on type declarations C#: Parse attribute lists on type declarations Mar 12, 2026
@knutwannheden knutwannheden marked this pull request as draft March 12, 2026 20:50
Switch ExtractPrefix, ExtractSpaceBefore, and ExtractRemaining from
Space.Format to Space.FormatWithComments so all spaces in the tree have
structured Comment entries instead of raw comment text in Whitespace.

Fix VisitSpace to print Whitespace before Comments (matching Java's
JavaPrinter convention) — previously reversed, which was invisible when
Comments was always empty.

Update DirectiveBoundaryInjector to scan Space.Comments for ghost
comment text instead of regex on Space.Whitespace.
Reuse identical Space instances for common whitespace patterns (indentation,
newlines) to reduce memory allocation, matching Java's ConcurrentHashMap approach.
Caches commentless spaces with whitespace up to 50 characters.
Same indentation patterns repeat on nearly every line. Cache the input
string → Space mapping in the parser so FormatWithComments is only called
once per unique whitespace string. Only commentless results are cached.
@knutwannheden knutwannheden marked this pull request as ready for review March 12, 2026 21:21
@knutwannheden knutwannheden merged commit 8330e37 into main Mar 12, 2026
1 check passed
@knutwannheden knutwannheden deleted the fix-csharp-parser-type-declaration-attributes branch March 12, 2026 21:21
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant