Skip to content

C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline#7062

Merged
knutwannheden merged 1 commit intomainfrom
minimum-viable-spacing
Mar 19, 2026
Merged

C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline#7062
knutwannheden merged 1 commit intomainfrom
minimum-viable-spacing

Conversation

@knutwannheden
Copy link
Contributor

Summary

  • Adds MinimumViableSpacingVisitor that ensures minimum token separation in the C# LST so printed output is parseable
  • Hooks it into RoslynFormatter.Format() as the first pipeline step, before printing
  • Recipes can now use Space.Empty everywhere when synthesizing new nodes — the visitor ensures publicvoid becomes public void, newSystem.Exception becomes new System.Exception, etc.

Token separation handled:

  • Modifier chains (public static final not publicstaticfinal)
  • Class/struct/record keyword + name
  • Method return type + name, constructor initializer (: base())
  • Variable/property type + name
  • Keywords: return, throw, new, await, yield return/yield break
  • using/namespace directives
  • foreach in + iterable

Design:

  • Only modifies Space when IsEmpty — never touches existing whitespace
  • Identity-preserving: returns same object reference when nothing changes
  • Does NOT do indentation or stylistic formatting — Roslyn handles that

Test plan

  • 21 new tests in MinimumViableSpacingTests covering all handled cases
  • All 1406 existing tests pass (including AutoFormat referential identity test)
  • Integration test: strip → MVS → AutoFormat pipeline produces properly formatted code

…ormat pipeline

Recipes that synthesize new AST nodes with Space.Empty everywhere produce
unparseable printed output (e.g. "publicMyException():base(){}"), causing
the WhitespaceReconciler to bail and return unformatted trees.

The MinimumViableSpacingVisitor runs as the first step of RoslynFormatter.Format()
and inserts the minimum whitespace needed to keep tokens separated:
- Modifiers: public static → not publicstatic
- Keywords + identifiers: class Foo, void Bar, return expr, throw expr, etc.
- using/namespace directives
- Property declarations
- new + type, await + expr, yield return/break + expr
- foreach in + iterable
- Constructor initializer (: base/this)
- Class extends/implements (: BaseClass)

It does NOT handle indentation or stylistic formatting — Roslyn handles that.
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Mar 19, 2026
@knutwannheden knutwannheden changed the title C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline Mar 19, 2026
@knutwannheden knutwannheden changed the title C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline C#: Add MinimumViableSpacingVisitor for AutoFormat pipeline Mar 19, 2026
@knutwannheden knutwannheden merged commit 4d5bb65 into main Mar 19, 2026
1 check passed
@knutwannheden knutwannheden deleted the minimum-viable-spacing branch March 19, 2026 16:43
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 19, 2026
knutwannheden added a commit that referenced this pull request Mar 19, 2026
…ormat pipeline (#7062)

Recipes that synthesize new AST nodes with Space.Empty everywhere produce
unparseable printed output (e.g. "publicMyException():base(){}"), causing
the WhitespaceReconciler to bail and return unformatted trees.

The MinimumViableSpacingVisitor runs as the first step of RoslynFormatter.Format()
and inserts the minimum whitespace needed to keep tokens separated:
- Modifiers: public static → not publicstatic
- Keywords + identifiers: class Foo, void Bar, return expr, throw expr, etc.
- using/namespace directives
- Property declarations
- new + type, await + expr, yield return/break + expr
- foreach in + iterable
- Constructor initializer (: base/this)
- Class extends/implements (: BaseClass)

It does NOT handle indentation or stylistic formatting — Roslyn handles that.
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