Skip to content

Commit c27eebc

Browse files
C#: Add .editorconfig-based formatting style detection for RoslynFormatter (#7194)
* C#: Add .editorconfig-based formatting style detection for RoslynFormatter Replace the runtime source-text heuristic (FormatStyle.DetectStyle) with a proper .editorconfig-based style resolver. A new CSharpFormatStyle marker is attached to each CompilationUnit during parsing and flows through RPC to the Java side. - Add CSharpFormatStyle marker (C# + Java) with RPC codecs carrying all Roslyn formatting options: tabs/spaces, indent size, newline style, 10 brace placement options, 3 keyword newline options, 2 wrapping options - Add EditorConfigResolver that walks .editorconfig files hierarchically from file directory up to project root, layering child over parent, stopping at root=true. Caches resolved styles per directory. - SolutionParser attaches the resolved CSharpFormatStyle to each CU - RoslynFormatter reads the marker instead of detecting at format time and wires all brace/keyword options into CSharpFormattingOptions - Delete dead FormatStyle class superseded by EditorConfigResolver * Move CSharpFormatStyle from marker to style package, extend NamedStyles Follow the established convention where style markers extend NamedStyles (like PrettierStyle, Autodetect) and live in a .style package rather than .marker. The CSharpFormatStyle now extends NamedStyles and stores its configuration directly (empty styles collection), matching the PrettierStyle pattern for formatters that delegate to a single external tool. - Move Java class from csharp.marker to csharp.style package - Extend NamedStyles instead of implementing Marker directly - Update RPC type name to org.openrewrite.csharp.style.CSharpFormatStyle - Add style package convention to RpcReceiveQueue type resolution * Strip :severity suffixes from .editorconfig values Real-world .editorconfig files use Roslyn severity suffixes like csharp_new_line_before_open_brace = all:error or csharp_new_line_before_else = true:suggestion. Strip the :suffix before processing so these values are correctly recognized. * Cover all 47 Roslyn CSharpFormattingOptions in CSharpFormatStyle Expand CSharpFormatStyle to carry every option that Roslyn's CSharpFormattingOptions exposes, and wire them all through BuildOptions. Added options: - Indentation: IndentBlock, IndentBraces, IndentSwitchCaseSection, IndentSwitchCaseSectionWhenBlock, IndentSwitchSection, LabelPositioning - New lines: NewLineForClausesInQuery, NewLineForMembersInAnonymousTypes, NewLineForMembersInObjectInit - Spacing: all 24 Space* options including SpacingAroundBinaryOperator (enum mapped as int: 0=before_and_after, 1=ignore, 2=none) EditorConfigResolver now parses .editorconfig keys for all of these, including csharp_indent_labels (flush_left/one_less_than_current/no_change), csharp_space_around_binary_operators (before_and_after/ignore/none), and csharp_space_around_declaration_statements (ignore/false). * Pack 47 boolean flags into a single long for compact RPC Replace 47 individual boolean fields with bit-packed long storage. Public API is unchanged — all boolean properties remain as computed accessors (e.g., style.SpaceAfterCast reads bit 22 from the packed long). RPC now sends 6 fields instead of 52. Bit positions are assigned in declaration order and are append-only to maintain wire compatibility. Both C# and Java sides use matching bit position constants. * Add DefaultFlags constant for Roslyn default boolean flag values The packed long has 27 of 47 bits set by default (Allman style, standard spacing). Making this an explicit constant (0x600033BFFFFAL) documents the defaults, simplifies the Default instance construction, and protects against accidental zero-initialization. * Cache Roslyn OptionSet on CSharpFormatStyle marker instance The OptionSet built from 51 WithChangedOption calls is now lazily cached as a transient field on the immutable CSharpFormatStyle marker. Since markers are shared across files in the same directory, the cached OptionSet is reused for all format calls on those files. The field is volatile for safe publication and excluded from RPC serialization and equality — it's rebuilt on demand after deserialization. * Add tests verifying Roslyn respects brace placement and spacing options Two new tests confirm that CSharpFormatStyle options flow through to Roslyn's formatter correctly: - K&R brace style (NewLinesForBracesInTypes/Methods=false) produces braces on same line as declaration - SpaceAfterCast=true inserts a space after cast expressions * Default all convenience constructor parameters to Roslyn defaults All boolean, int, and string parameters in the convenience constructor now have default values matching Roslyn/VS defaults. Callers only need to specify the values they want to override, e.g.: new CSharpFormatStyle(id, newLinesForBracesInTypes: false) * WhitespaceReconciler: skip mismatched subtrees instead of aborting When a subtree has a structural mismatch (e.g., a recipe constructed a J.Identifier where the parser would produce J.Primitive), the reconciler now skips that subtree — keeping its original whitespace — and continues reconciling the rest of the tree. Previously, any mismatch aborted the entire reconciliation and returned the original tree unchanged. - StructureMismatch now records the mismatch count but does not abort - Remove all early-exit guards that checked _compatible flag - Add MismatchCount property and MaxMismatches limit (throws when exceeded, intended for test assertions) - RoslynFormatter no longer discards reconciled results on mismatch The skipped test (SkipsMismatchedSubtreeAndReconcilesSurroundingCode) demonstrates the intended behavior but needs investigation — the result propagation doesn't update surrounding whitespace as expected. * Fix WhitespaceReconciler to continue past mismatches in lists The last remaining early-exit guard (inside VisitList's for loop) was preventing siblings from being reconciled after a mismatch in an earlier sibling. Removing it allows the reconciler to process all list elements, skipping only the subtrees that actually mismatch. The new test verifies this: when a recipe replaces J.Primitive("int") with J.Identifier("int") on the first method's return type, the second method and its body still get proper indentation from Roslyn. * Add Validations class for controlling test invariant checks Introduce Validations as a centralized way to enable/disable test invariant checks in RewriteRun, following the Java-side TypeValidation pattern. Tests configure it via RecipeSpec: spec.SetValidations(new Validations { WhitespaceInSpaces = false }) Current flags: - WhitespaceInSpaces: validate Space fields contain only whitespace - PrintEqualsInput: validate round-trip fidelity - PrintIdempotence: validate re-parse produces identical output - MaxWhitespaceMismatches: limit for reconciler structural mismatches All enabled by default. Validations.None disables everything. * Wire Validations.MaxWhitespaceMismatches through to WhitespaceReconciler RewriteRun now sets WhitespaceReconciler.DefaultMaxMismatches from the Validations config before running recipes and restores it after. The static field defaults to 0 which maps to int.MaxValue (unlimited) in production. Tests get the Validations.All default of 5. * Simplify mismatch validation to a boolean AllowWhitespaceMismatches Replace MaxWhitespaceMismatches (int) with AllowWhitespaceMismatches (bool). The reconciler now collects mismatches during the full walk and throws after completion with a report of the first 5 — no early abort. Tests get ThrowOnMismatch=true by default (via Validations.All). Production gets ThrowOnMismatch=false (static default). Tests that expect mismatches disable throwing: spec.SetValidations(new Validations { AllowWhitespaceMismatches = true }) * Rename AllowWhitespaceMismatches to FormattingReconciliation Better describes what's being validated: structural compatibility between recipe output and Roslyn-formatted output during reconciliation.
1 parent 816f6f3 commit c27eebc

14 files changed

Lines changed: 1674 additions & 201 deletions

File tree

rewrite-csharp/csharp/OpenRewrite/CSharp/CSharpFormatStyle.cs

Lines changed: 292 additions & 0 deletions
Large diffs are not rendered by default.

rewrite-csharp/csharp/OpenRewrite/CSharp/Format/EditorConfigResolver.cs

Lines changed: 395 additions & 0 deletions
Large diffs are not rendered by default.

rewrite-csharp/csharp/OpenRewrite/CSharp/Format/FormatStyle.cs

Lines changed: 0 additions & 113 deletions
This file was deleted.

rewrite-csharp/csharp/OpenRewrite/CSharp/Format/RoslynFormatter.cs

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ public static CompilationUnit Format(CompilationUnit cu, J? targetSubtree, J? st
7474
source = printer.Print(mvsCu);
7575
}
7676

77-
// 3. Detect style
78-
var style = FormatStyle.DetectStyle(source);
77+
// 3. Get style from marker (attached during parsing) or fall back to defaults
78+
var style = cu.Markers.FindFirst<CSharpFormatStyle>() ?? CSharpFormatStyle.Default;
7979

8080
// 4. Format with Roslyn (scoped to the target span when available)
8181
var formattedSource = FormatWithRoslyn(source, style, formatSpan);
@@ -91,8 +91,6 @@ public static CompilationUnit Format(CompilationUnit cu, J? targetSubtree, J? st
9191
// MVS made changes — reconcile them within the target subtree
9292
var mvsReconciler = new WhitespaceReconciler();
9393
var mvsResult = mvsReconciler.Reconcile(originalCu, mvsCu, targetSubtree, stopAfter);
94-
if (!mvsReconciler.IsCompatible)
95-
return originalCu;
9694
return mvsResult as CompilationUnit ?? originalCu;
9795
}
9896

@@ -110,13 +108,12 @@ public static CompilationUnit Format(CompilationUnit cu, J? targetSubtree, J? st
110108
}
111109

112110
// 7. Reconcile whitespace against the original CU so MVS artifacts
113-
// outside the target subtree are discarded.
111+
// outside the target subtree are discarded. Mismatched subtrees
112+
// (e.g., recipe-constructed nodes with different types than the parser
113+
// would produce) are skipped — they keep their original whitespace.
114114
var reconciler = new WhitespaceReconciler();
115115
var result = reconciler.Reconcile(originalCu, formattedCu, targetSubtree, stopAfter);
116116

117-
if (!reconciler.IsCompatible)
118-
return originalCu;
119-
120117
return result as CompilationUnit ?? originalCu;
121118
}
122119

@@ -251,8 +248,8 @@ public static CompilationUnit FormatSpans(CompilationUnit cu, HashSet<Guid> node
251248
if (spans.Count == 0)
252249
return originalCu;
253250

254-
// 3. Detect style
255-
var style = FormatStyle.DetectStyle(source);
251+
// 3. Get style from marker (attached during parsing) or fall back to defaults
252+
var style = cu.Markers.FindFirst<CSharpFormatStyle>() ?? CSharpFormatStyle.Default;
256253

257254
// 4. Format with Roslyn, scoped to all target spans
258255
var formattedSource = FormatWithRoslyn(source, style, spans);
@@ -268,8 +265,6 @@ public static CompilationUnit FormatSpans(CompilationUnit cu, HashSet<Guid> node
268265
// MVS made changes — reconcile them within the target subtrees
269266
var mvsReconciler = new WhitespaceReconciler();
270267
var mvsResult = mvsReconciler.Reconcile(originalCu, mvsCu, nodeIds);
271-
if (!mvsReconciler.IsCompatible)
272-
return originalCu;
273268
cu = mvsResult as CompilationUnit ?? originalCu;
274269

275270
// Restore preserved prefixes
@@ -300,9 +295,6 @@ public static CompilationUnit FormatSpans(CompilationUnit cu, HashSet<Guid> node
300295
var reconciler = new WhitespaceReconciler();
301296
var result = reconciler.Reconcile(originalCu, formattedCu, nodeIds);
302297

303-
if (!reconciler.IsCompatible)
304-
return originalCu;
305-
306298
cu = result as CompilationUnit ?? originalCu;
307299

308300
// 8. Restore preserved prefixes
@@ -512,27 +504,27 @@ public override J VisitBlock(Block block, int ctx)
512504
}
513505
}
514506

515-
internal static string FormatWithRoslyn(string source, FormatStyle style, TextSpan? span = null)
507+
internal static string FormatWithRoslyn(string source, CSharpFormatStyle style, TextSpan? span = null)
516508
{
517509
var syntaxTree = CSharpSyntaxTree.ParseText(source);
518510
var root = syntaxTree.GetRoot();
519511

520512
using var workspace = CreateWorkspace();
521-
var options = BuildOptions(workspace, style);
513+
var options = style.GetOrBuildOptionSet(workspace.Options);
522514

523515
var formatted = span != null
524516
? Formatter.Format(root, span.Value, workspace, options)
525517
: Formatter.Format(root, workspace, options);
526518
return formatted.ToFullString();
527519
}
528520

529-
internal static string FormatWithRoslyn(string source, FormatStyle style, IEnumerable<TextSpan> spans)
521+
internal static string FormatWithRoslyn(string source, CSharpFormatStyle style, IEnumerable<TextSpan> spans)
530522
{
531523
var syntaxTree = CSharpSyntaxTree.ParseText(source);
532524
var root = syntaxTree.GetRoot();
533525

534526
using var workspace = CreateWorkspace();
535-
var options = BuildOptions(workspace, style);
527+
var options = style.GetOrBuildOptionSet(workspace.Options);
536528

537529
var formatted = Formatter.Format(root, spans, workspace, options);
538530
return formatted.ToFullString();
@@ -565,13 +557,64 @@ internal static string FormatWithRoslyn(string source, FormatStyle style, IEnume
565557

566558
private static AdhocWorkspace CreateWorkspace() => new(HostServices);
567559

568-
private static Microsoft.CodeAnalysis.Options.OptionSet BuildOptions(AdhocWorkspace workspace, FormatStyle style)
560+
internal static Microsoft.CodeAnalysis.Options.OptionSet BuildOptions(Microsoft.CodeAnalysis.Options.OptionSet baseOptions, CSharpFormatStyle style)
569561
{
570-
return workspace.Options
562+
return baseOptions
571563
.WithChangedOption(FormattingOptions.UseTabs, LanguageNames.CSharp, style.UseTabs)
572-
.WithChangedOption(FormattingOptions.IndentationSize, LanguageNames.CSharp, style.IndentationSize)
573-
.WithChangedOption(FormattingOptions.TabSize, LanguageNames.CSharp, style.IndentationSize)
564+
.WithChangedOption(FormattingOptions.IndentationSize, LanguageNames.CSharp, style.IndentSize)
565+
.WithChangedOption(FormattingOptions.TabSize, LanguageNames.CSharp, style.TabSize)
574566
.WithChangedOption(FormattingOptions.NewLine, LanguageNames.CSharp, style.NewLine)
567+
// Indentation
568+
.WithChangedOption(CSharpFormattingOptions.IndentBlock, style.IndentBlock)
569+
.WithChangedOption(CSharpFormattingOptions.IndentBraces, style.IndentBraces)
570+
.WithChangedOption(CSharpFormattingOptions.IndentSwitchCaseSection, style.IndentSwitchCaseSection)
571+
.WithChangedOption(CSharpFormattingOptions.IndentSwitchCaseSectionWhenBlock, style.IndentSwitchCaseSectionWhenBlock)
572+
.WithChangedOption(CSharpFormattingOptions.IndentSwitchSection, style.IndentSwitchSection)
573+
.WithChangedOption(CSharpFormattingOptions.LabelPositioning, (LabelPositionOptions)style.LabelPositioning)
574+
// Brace placement
575+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, style.NewLinesForBracesInTypes)
576+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, style.NewLinesForBracesInMethods)
577+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInProperties, style.NewLinesForBracesInProperties)
578+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, style.NewLinesForBracesInAccessors)
579+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousMethods, style.NewLinesForBracesInAnonymousMethods)
580+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAnonymousTypes, style.NewLinesForBracesInAnonymousTypes)
581+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, style.NewLinesForBracesInControlBlocks)
582+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInLambdaExpressionBody, style.NewLinesForBracesInLambdaExpressionBody)
583+
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers, style.NewLinesForBracesInObjectCollectionArrayInitializers)
584+
// Note: NewLinesForBracesInLocalFunctions is stored in the marker for .editorconfig fidelity
585+
// but Roslyn 5.0's CSharpFormattingOptions does not expose this option.
586+
// New line before keywords / members
587+
.WithChangedOption(CSharpFormattingOptions.NewLineForElse, style.NewLineBeforeElse)
588+
.WithChangedOption(CSharpFormattingOptions.NewLineForCatch, style.NewLineBeforeCatch)
589+
.WithChangedOption(CSharpFormattingOptions.NewLineForFinally, style.NewLineBeforeFinally)
590+
.WithChangedOption(CSharpFormattingOptions.NewLineForClausesInQuery, style.NewLineForClausesInQuery)
591+
.WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, style.NewLineForMembersInAnonymousTypes)
592+
.WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, style.NewLineForMembersInObjectInit)
593+
// Spacing
594+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterCast, style.SpaceAfterCast)
595+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterColonInBaseTypeDeclaration, style.SpaceAfterColonInBaseTypeDeclaration)
596+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterComma, style.SpaceAfterComma)
597+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterControlFlowStatementKeyword, style.SpaceAfterControlFlowStatementKeyword)
598+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterDot, style.SpaceAfterDot)
599+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterMethodCallName, style.SpaceAfterMethodCallName)
600+
.WithChangedOption(CSharpFormattingOptions.SpaceAfterSemicolonsInForStatement, style.SpaceAfterSemicolonsInForStatement)
601+
.WithChangedOption(CSharpFormattingOptions.SpaceBeforeColonInBaseTypeDeclaration, style.SpaceBeforeColonInBaseTypeDeclaration)
602+
.WithChangedOption(CSharpFormattingOptions.SpaceBeforeComma, style.SpaceBeforeComma)
603+
.WithChangedOption(CSharpFormattingOptions.SpaceBeforeDot, style.SpaceBeforeDot)
604+
.WithChangedOption(CSharpFormattingOptions.SpaceBeforeOpenSquareBracket, style.SpaceBeforeOpenSquareBracket)
605+
.WithChangedOption(CSharpFormattingOptions.SpaceBeforeSemicolonsInForStatement, style.SpaceBeforeSemicolonsInForStatement)
606+
.WithChangedOption(CSharpFormattingOptions.SpaceBetweenEmptyMethodCallParentheses, style.SpaceBetweenEmptyMethodCallParentheses)
607+
.WithChangedOption(CSharpFormattingOptions.SpaceBetweenEmptyMethodDeclarationParentheses, style.SpaceBetweenEmptyMethodDeclarationParentheses)
608+
.WithChangedOption(CSharpFormattingOptions.SpaceBetweenEmptySquareBrackets, style.SpaceBetweenEmptySquareBrackets)
609+
.WithChangedOption(CSharpFormattingOptions.SpacesIgnoreAroundVariableDeclaration, style.SpacesIgnoreAroundVariableDeclaration)
610+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinCastParentheses, style.SpaceWithinCastParentheses)
611+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinExpressionParentheses, style.SpaceWithinExpressionParentheses)
612+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinMethodCallParentheses, style.SpaceWithinMethodCallParentheses)
613+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinMethodDeclarationParenthesis, style.SpaceWithinMethodDeclarationParenthesis)
614+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinOtherParentheses, style.SpaceWithinOtherParentheses)
615+
.WithChangedOption(CSharpFormattingOptions.SpaceWithinSquareBrackets, style.SpaceWithinSquareBrackets)
616+
.WithChangedOption(CSharpFormattingOptions.SpacingAfterMethodDeclarationName, style.SpacingAfterMethodDeclarationName)
617+
.WithChangedOption(CSharpFormattingOptions.SpacingAroundBinaryOperator, (BinaryOperatorSpacingOptions)style.SpacingAroundBinaryOperator)
575618
// Don't preserve single-line formatting — synthesized nodes may have no newlines,
576619
// and Roslyn must insert structural newlines (after {, before }, before else, etc.)
577620
.WithChangedOption(CSharpFormattingOptions.WrappingPreserveSingleLine, false)

rewrite-csharp/csharp/OpenRewrite/CSharp/Format/WhitespaceReconciler.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ namespace OpenRewrite.CSharp.Format;
2626
/// from the formatted tree to the original. Preserves the original tree's IDs,
2727
/// types, and all non-whitespace state.
2828
///
29-
/// If the trees diverge structurally, returns the original unchanged and sets
30-
/// <see cref="IsCompatible"/> to false.
29+
/// When a subtree diverges structurally (e.g., a recipe used J.Identifier where
30+
/// the parser produces J.Primitive), that subtree is skipped — the original is
31+
/// kept unchanged — and reconciliation continues with the remaining siblings.
32+
/// <see cref="IsCompatible"/> is set to false to signal that mismatches occurred.
3133
/// </summary>
3234
public class WhitespaceReconciler
3335
{
@@ -131,7 +133,7 @@ private string CurrentPath()
131133

132134
private object? VisitProperty(object? original, object? formatted)
133135
{
134-
if (!_compatible && !_throwOnMismatch) return original;
136+
135137

136138
// Handle null: if one is null and the other isn't, check whether it's a
137139
// structural type (J, padded wrapper, list) where a mismatch is fatal.
@@ -203,7 +205,7 @@ nonNull is IList ||
203205

204206
private object? VisitTree(J original, J formatted)
205207
{
206-
if (!_compatible && !_throwOnMismatch) return original;
208+
207209

208210
// Check structural type compatibility
209211
if (original.GetType() != formatted.GetType())
@@ -244,7 +246,7 @@ nonNull is IList ||
244246

245247
var visited = VisitProperty(origVal, fmtVal);
246248
PopPath();
247-
if (!_compatible && !_throwOnMismatch) return original;
249+
248250

249251
if (!ReferenceEquals(visited, origVal))
250252
{
@@ -275,7 +277,7 @@ nonNull is IList ||
275277

276278
private object? VisitRightPadded(object original, object formatted)
277279
{
278-
if (!_compatible && !_throwOnMismatch) return original;
280+
279281

280282
var origType = original.GetType();
281283
var fmtType = formatted.GetType();
@@ -290,7 +292,7 @@ nonNull is IList ||
290292
PushPath("Element");
291293
var visitedElement = VisitProperty(origElement, fmtElement);
292294
PopPath();
293-
if (!_compatible && !_throwOnMismatch) return original;
295+
294296

295297
var origAfter = afterProp.GetValue(original) as Space;
296298
var fmtAfter = afterProp.GetValue(formatted) as Space;
@@ -326,7 +328,7 @@ nonNull is IList ||
326328

327329
private object? VisitLeftPadded(object original, object formatted)
328330
{
329-
if (!_compatible && !_throwOnMismatch) return original;
331+
330332

331333
var origType = original.GetType();
332334
var fmtType = formatted.GetType();
@@ -346,7 +348,7 @@ nonNull is IList ||
346348
PushPath("Element");
347349
var visitedElement = VisitProperty(origElement, fmtElement);
348350
PopPath();
349-
if (!_compatible && !_throwOnMismatch) return original;
351+
350352

351353
if (ReferenceEquals(visitedBefore, origBefore) &&
352354
ReferenceEquals(visitedElement, origElement))
@@ -366,7 +368,7 @@ nonNull is IList ||
366368

367369
private object? VisitContainer(object original, object formatted)
368370
{
369-
if (!_compatible && !_throwOnMismatch) return original;
371+
370372

371373
var origType = original.GetType();
372374
var fmtType = formatted.GetType();
@@ -387,7 +389,7 @@ nonNull is IList ||
387389
PushPath("Elements");
388390
var visitedElements = VisitList(origElements!, fmtElements!);
389391
PopPath();
390-
if (!_compatible && !_throwOnMismatch) return original;
392+
391393

392394
var origMarkers = markersProp.GetValue(original) as Markers;
393395
var fmtMarkers = markersProp.GetValue(formatted) as Markers;
@@ -428,7 +430,7 @@ nonNull is IList ||
428430
PushPath($"[{i}]");
429431
var visited = VisitProperty(original[i], formatted[i]);
430432
PopPath();
431-
if (!_compatible && !_throwOnMismatch) return original;
433+
432434
newList.Add(visited);
433435
if (!ReferenceEquals(visited, original[i]))
434436
changed = true;

rewrite-csharp/csharp/OpenRewrite/CSharp/Rpc/RewriteRpcServer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ public RewriteRpcServer(RecipeMarketplace marketplace)
124124
"org.openrewrite.java.marker.OmitParentheses");
125125
RpcSendQueue.RegisterJavaTypeName(typeof(AnonymousMethod),
126126
"org.openrewrite.csharp.marker.AnonymousMethod");
127+
RpcSendQueue.RegisterJavaTypeName(typeof(CSharpFormatStyle),
128+
"org.openrewrite.csharp.style.CSharpFormatStyle");
127129
RpcSendQueue.RegisterJavaTypeName(typeof(ConditionalBranchMarker),
128130
"org.openrewrite.csharp.marker.ConditionalBranchMarker");
129131
RpcSendQueue.RegisterJavaTypeName(typeof(DirectiveBoundaryMarker),

0 commit comments

Comments
 (0)