C#: Parse attribute lists on type declarations#6971
Merged
knutwannheden merged 5 commits intomainfrom Mar 12, 2026
Merged
Conversation
…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
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
node.AttributeListsinVisitTypeDeclaration,VisitEnumDeclaration,VisitStructDeclaration, andVisitRecordDeclaration— previously attributes on type declarations were silently absorbed into whitespaceAnnotatedStatementwhen attributes are presentSpace.FormatWithCommentsto parse/* */and//comments into structuredCommententriesExtractPrefix,ExtractSpaceBefore, andExtractRemainingto useFormatWithCommentsso allSpaceobjects in the tree have structured commentsVisitSpaceprint order to emitWhitespacebeforeComments(matching Java'sJavaPrinterconvention)DirectiveBoundaryInjectorto scanSpace.Commentsfor ghost comment text instead of regex onSpace.WhitespaceConcurrentDictionary) for commentlessSpaceobjects with whitespace ≤ 50 chars, matching Java's approachDictionarycache to skip re-parsing repeated whitespace patterns (same indentation on every line)Test plan
CSharpRpcTesttests pass (including 8 directive-related tests that exercise the updatedDirectiveBoundaryInjector)[Serializable] class,[Obsolete("msg")] public class,[Serializable] struct,[Flags] enum[Serializable(/*bar*/)]producesCommentwithMultiline=true, Text="bar"ClassDeclarationTestswith extra whitespace and attributes continue to pass