Formatter.Format does not expand empty constructor body to Allman style when constructor initializer is present
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
**Version Used**: Microsoft.CodeAnalysis.CSharp.Workspaces 5.0.0 (net9.0)
**Steps to Reproduce**:
```csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.Formatting;
var source = """
class MyException : Exception
{
public MyException() : base(){}
public MyException(string m) : base(m){}
}
""";
var tree = CSharpSyntaxTree.ParseText(source);
var root = tree.GetRoot();
using var workspace = new AdhocWorkspace();
var options = workspace.Options
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, true)
.WithChangedOption(CSharpFormattingOptions.WrappingPreserveSingleLine, false)
.WithChangedOption(CSharpFormattingOptions.WrappingKeepStatementsOnSingleLine, false);
var formatted = Formatter.Format(root, workspace, options).ToFullString();
Console.WriteLine(formatted);
// For comparison:
var normalized = root.NormalizeWhitespace().ToFullString();
Console.WriteLine("--- NormalizeWhitespace ---");
Console.WriteLine(normalized);
```
**Diagnostic Id**: N/A (formatting API, not analyzer)
**Expected Behavior**:
`Formatter.Format` with `NewLinesForBracesInMethods=true` and `WrappingPreserveSingleLine=false` should place the opening brace of an empty constructor body on a new line (Allman style), matching what `NormalizeWhitespace()` produces:
```csharp
class MyException : Exception
{
public MyException() : base()
{
}
public MyException(string m) : base(m)
{
}
}
```
**Actual Behavior**:
`Formatter.Format` keeps empty constructor bodies on one line when a constructor initializer (`: base(...)`) is present. No combination of formatting options changes this:
```csharp
class MyException : Exception
{
public MyException() : base() { }
public MyException(string m) : base(m) { }
}
```
`NormalizeWhitespace()` correctly produces multi-line Allman-style braces for the same input.
**Additional context**:
This was tested exhaustively with every `NewLinesForBraces*` and `Wrapping*` option — individually and in combination — none cause the formatter to expand empty constructor bodies when a constructor initializer is present. Constructors without an initializer (e.g. `public Foo(){}`) are expanded correctly by `NewLinesForBracesInMethods=true`.
Contributor guide
Research direction
Run the supplied C# reproduction with Formatter.Format, AdhocWorkspace, and the listed CSharpFormattingOptions, then trace how formatting handles constructors with initializer clauses. Done means empty constructor bodies with initializers expand to separate Allman-style brace lines when NewLinesForBracesInMethods and the wrapping options are enabled, without regressing constructors that already format correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100