Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0b91ca4
perf: use overload for `Any( SyntaxTriviaList` to prevent allocations…
TimothyMakkison Dec 25, 2025
39f1620
perf: add `Doc.Null` check to `Argument` avoids `Concat` creation (#1…
TimothyMakkison Dec 25, 2025
5fe3925
perf: use `Stack.Peek` to reduce `Pop` and `Push` churn (#1708)
TimothyMakkison Dec 25, 2025
ebc893f
perf: set capacity of `List` in `MembersForcedLine` (#1709)
TimothyMakkison Dec 25, 2025
e9b9c64
perf: optimise `SyntaxNodeComparer` (#1730)
TimothyMakkison Dec 25, 2025
af32124
perf: fast comparison using `FullSpan` and source code (#1737)
TimothyMakkison Dec 25, 2025
7b06c03
perf: cache `IgnoreWithBasePath` (#1758)
TimothyMakkison Dec 25, 2025
8b1c0b1
Adding the xml whitespace options (#1793)
belav Dec 25, 2025
6a952cf
Implement global setting for run on save (#1798)
belav Jan 1, 2026
c8358b4
Update bug report template with playground link
belav Jan 19, 2026
52f7f6f
Add axaml to VS. Bump up version number on all plugins to try to help…
belav Jan 19, 2026
e0d12d9
Fix formatting in bug issue template
belav Jan 19, 2026
2fe085f
Improve version check formatting in bug.yml
belav Jan 19, 2026
26f02bd
Revise bug report template for clarity and versioning
belav Jan 19, 2026
4c5aa5e
Make sure we update bug template when we release
belav Jan 19, 2026
544934f
formatting + updating rider thing
belav Jan 31, 2026
a047a24
disable Q&A
belav Feb 9, 2026
148711f
Working on adding xml whitespace ignore.
belav Dec 29, 2025
93c8caf
Getting the basics of ignore whitespace in xml working.
belav Dec 31, 2025
06a9bef
Adding some tests to figure out how to format things with whitespace …
belav Jan 2, 2026
394fb1a
Possibly have the tests set up how we want them to be formatted
belav Jan 2, 2026
2d48adb
Fixing some more issues with ignoring whitespace in xml
belav Jan 9, 2026
42fc013
Ditching XAML xml sensitivity, add support for xml:space so "ignore" …
belav Feb 20, 2026
7dd8e76
Defaulting xaml and axaml to xml ignore whitespace
belav Feb 22, 2026
8cbcbb4
Merge branch '1.3.0-dev' into xml-ignore-whitespace
belav Apr 4, 2026
68f85fc
fixing merge issues
belav Apr 4, 2026
e93c53a
fixing an edge case
belav Apr 4, 2026
26c263d
fixing mode edge cases
belav Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CSharpier.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/AddImportsToDeepestScope/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EUnitTestFramework_002EMigrations_002EEnableDisabledProvidersMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=Testing_0020Platform/@EntryIndexedValue">False</s:Boolean>

<s:Boolean x:Key="/Default/UserDictionary/Words/=Concated/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=csharpier/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=csharpierignore/@EntryIndexedValue">True</s:Boolean>
Expand Down
3 changes: 2 additions & 1 deletion Shell/UpdateCSharpierRepos.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function CSH-UpdateCSharpierRepos()
$repositories += "https://github.com/dotnet/runtime.git"
$repositories += "https://github.com/mono/mono.git"
$repositories += "https://github.com/increase-POS/Res-Server.git"
$repositories += "https://github.com/stride3d/stride.git"

$tempLocation = "c:\temp\UpdateRepos"

Expand Down Expand Up @@ -46,7 +47,7 @@ function CSH-UpdateCSharpierRepos()
Set-Location $destination
& git checkout main

$extensions = (".csproj", ".props", ".targets", ".xml", ".config", ".cs")
$extensions = (".csproj", ".props", ".targets", ".xml", ".config", ".cs", ".xaml", ".axaml")

foreach ($extension in $extensions)
{
Expand Down
16 changes: 13 additions & 3 deletions Src/CSharpier.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public void XDocument_Parse()
[Benchmark]
public void CustomParser_Parse()
{
_ = RawNodeReader.ParseXml(this.largeXmlCode, Environment.NewLine);
_ = RawNodeReader.ParseXml(
this.largeXmlCode,
Environment.NewLine,
XmlWhitespaceSensitivity.Strict
);
}

[Benchmark]
Expand All @@ -49,7 +53,10 @@ public void XmlReader_Parse()
public void Default_CodeFormatter_Tests()
{
CSharpFormatter
.FormatAsync(this.largeTestCode, new PrinterOptions(Formatter.CSharp))
.FormatAsync(
this.largeTestCode,
new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict)
)
.GetAwaiter()
.GetResult();
}
Expand All @@ -58,7 +65,10 @@ public void Default_CodeFormatter_Tests()
public void Default_CodeFormatter_Complex()
{
CSharpFormatter
.FormatAsync(this.largeComplexCode, new PrinterOptions(Formatter.CSharp))
.FormatAsync(
this.largeComplexCode,
new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict)
)
.GetAwaiter()
.GetResult();
}
Expand Down
5 changes: 4 additions & 1 deletion Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ internal class EditorConfigSections
return null;
}

var printerOptions = new PrinterOptions(parsedFormatter);
var printerOptions = new PrinterOptions(
parsedFormatter,
PrinterOptions.GetXmlWhitespaceSensitivity(filePath)
);

if (resolvedConfiguration.MaxLineLength is { } maxLineLength)
{
Expand Down
20 changes: 12 additions & 8 deletions Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ internal class ConfigurationFileOptions
public bool UseTabs { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<XmlWhitespaceSensitivity>))]
public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } =
XmlWhitespaceSensitivity.Strict;
public XmlWhitespaceSensitivity? XmlWhitespaceSensitivity { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<EndOfLine>))]
public EndOfLine EndOfLine { get; init; }
Expand All @@ -36,26 +35,32 @@ out var parsedFormatter
return null;
}

return new PrinterOptions(parsedFormatter)
return new PrinterOptions(
parsedFormatter,
matchingOverride.XmlWhitespaceSensitivity
?? PrinterOptions.GetXmlWhitespaceSensitivity(filePath)
)
{
IndentSize = matchingOverride.IndentSize,
UseTabs = matchingOverride.UseTabs,
Width = matchingOverride.PrintWidth,
EndOfLine = matchingOverride.EndOfLine,
XmlWhitespaceSensitivity = matchingOverride.XmlWhitespaceSensitivity,
};
}

var formatter = PrinterOptions.GetFormatter(filePath);
if (formatter != Formatter.Unknown)
{
return new PrinterOptions(formatter)
return new PrinterOptions(
formatter,
this.XmlWhitespaceSensitivity
?? PrinterOptions.GetXmlWhitespaceSensitivity(filePath)
)
{
IndentSize = this.IndentSize ?? (formatter == Formatter.XML ? 2 : 4),
UseTabs = this.UseTabs,
Width = this.PrintWidth,
EndOfLine = this.EndOfLine,
XmlWhitespaceSensitivity = this.XmlWhitespaceSensitivity,
};
}

Expand All @@ -80,8 +85,7 @@ internal class Override
public bool UseTabs { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<XmlWhitespaceSensitivity>))]
public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } =
XmlWhitespaceSensitivity.Strict;
public XmlWhitespaceSensitivity? XmlWhitespaceSensitivity { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<EndOfLine>))]
public EndOfLine EndOfLine { get; init; }
Expand Down
4 changes: 3 additions & 1 deletion Src/CSharpier.Cli/Options/OptionsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ CancellationToken cancellationToken
}

var formatter = PrinterOptions.GetFormatter(filePath);
return formatter != Formatter.Unknown ? new PrinterOptions(formatter) : null;
return formatter != Formatter.Unknown
? new PrinterOptions(formatter, PrinterOptions.GetXmlWhitespaceSensitivity(filePath))
: null;
}

private Task<CSharpierConfigData?> FindCSharpierConfigAsync(string directoryName)
Expand Down
2 changes: 2 additions & 0 deletions Src/CSharpier.Core/CSharp/CSharpFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
LineEnding = lineEnding,
IndentSize = printerOptions.IndentSize,
UseTabs = printerOptions.UseTabs,
XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict,
},
};
var document = Node.Print(rootNode, printingContext);
Expand All @@ -181,6 +182,7 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
LineEnding = lineEnding,
IndentSize = printerOptions.IndentSize,
UseTabs = printerOptions.UseTabs,
XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict,
},
};
document = Node.Print(
Expand Down
1 change: 1 addition & 0 deletions Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class PrintingContextOptions
public required string LineEnding { get; init; }
public required int IndentSize { get; init; }
public required bool UseTabs { get; init; }
public required XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; }
}

public class PrintingContextState
Expand Down
1 change: 1 addition & 0 deletions Src/CSharpier.Core/CSharpier.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PublicKey>002400000480000094000000060200000024000052534131000400000100010049d266ea1aeae09c0abfce28b8728314d4e4807126ee8bc56155a7ddc765997ed3522908b469ae133fc49ef0bfa957df36082c1c2e0ec8cdc05a4ca4dbd4e1bea6c17fc1008555e15af13a8fc871a04ffc38f5e60e6203bfaf01d16a2a283b90572ade79135801c1675bf38b7a5a60ec8353069796eb53a26ffdddc9ee1273be</PublicKey>
<LangVersion>13</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Tester>One</Tester>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LovettSoftware.XmlDiff" />
Expand Down
4 changes: 3 additions & 1 deletion Src/CSharpier.Core/CodeFormatterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ public class CodeFormatterOptions
public int IndentSize { get; init; } = 4;
public EndOfLine EndOfLine { get; init; } = EndOfLine.Auto;
public bool IncludeGenerated { get; init; }
public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } =
XmlWhitespaceSensitivity.Strict;

internal PrinterOptions ToPrinterOptions()
{
return new(Formatter.CSharp)
return new(Formatter.CSharp, this.XmlWhitespaceSensitivity)
{
Width = this.Width,
UseTabs = this.IndentStyle == IndentStyle.Tabs,
Expand Down
115 changes: 86 additions & 29 deletions Src/CSharpier.Core/DocTypes/Doc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ public static implicit operator Doc(string value)
return StringDoc.Create(value);
}

public static NullDoc Null => NullDoc.Instance;
public static NullDoc Null
{
get { return NullDoc.Instance; }
}

public static Doc BreakParent => new BreakParent();
public static Doc BreakParent
{
get { return new BreakParent(); }
}

public static readonly HardLine HardLine = new();

Expand All @@ -39,19 +45,33 @@ public static implicit operator Doc(string value)

public static readonly Trim Trim = new();

public static LeadingComment LeadingComment(string comment, CommentType commentType) =>
new() { Type = commentType, Comment = comment };
public static LeadingComment LeadingComment(string comment, CommentType commentType)
{
return new LeadingComment { Type = commentType, Comment = comment };
}

public static TrailingComment TrailingComment(string comment, CommentType commentType) =>
new() { Type = commentType, Comment = comment };
public static TrailingComment TrailingComment(string comment, CommentType commentType)
{
return new TrailingComment { Type = commentType, Comment = comment };
}

public static Doc Concat(List<Doc> contents) =>
contents.Count == 1 ? contents[0] : new Concat(contents);
public static Doc Concat(List<Doc> contents)
{
return contents.Count == 0 ? Doc.Null
: contents.Count == 1 ? contents[0]
: new Concat(contents);
}

// prevents allocating an array if there is only a single parameter
public static Doc Concat(Doc contents) => contents;
public static Doc Concat(Doc contents)
{
return contents;
}

public static Doc Concat(params Doc[] contents) => new Concat(contents);
public static Doc Concat(params Doc[] contents)
{
return new Concat(contents);
}

public static Doc Concat(ref DocListBuilder contents)
{
Expand Down Expand Up @@ -82,14 +102,20 @@ public static Doc Join(Doc separator, IEnumerable<Doc> enumerable)
return docs.Count == 1 ? docs[0] : Concat(docs);
}

public static ForceFlat ForceFlat(List<Doc> contents) =>
new() { Contents = contents.Count == 0 ? contents[0] : Concat(contents) };
public static ForceFlat ForceFlat(List<Doc> contents)
{
return new ForceFlat { Contents = contents.Count == 0 ? contents[0] : Concat(contents) };
}

public static ForceFlat ForceFlat(params Doc[] contents) =>
new() { Contents = contents.Length == 0 ? contents[0] : Concat(contents) };
public static ForceFlat ForceFlat(params Doc[] contents)
{
return new ForceFlat { Contents = contents.Length == 0 ? contents[0] : Concat(contents) };
}

public static Group Group(List<Doc> contents) =>
new() { Contents = contents.Count == 1 ? contents[0] : Concat(contents) };
public static Group Group(List<Doc> contents)
{
return new Group { Contents = contents.Count == 1 ? contents[0] : Concat(contents) };
}

public static Group GroupWithId(string groupId, List<Doc> contents)
{
Expand Down Expand Up @@ -124,45 +150,76 @@ public static Group GroupWithId(string groupId, params Doc[] contents)
}

// prevents allocating an array if there is only a single parameter
public static Group Group(Doc contents) => new() { Contents = contents };
public static Group Group(Doc contents)
{
return new Group { Contents = contents };
}

public static Group Group(params Doc[] contents) => new() { Contents = Concat(contents) };
public static Group Group(params Doc[] contents)
{
return new Group { Contents = Concat(contents) };
}

// prevents allocating an array if there is only a single parameter
public static IndentDoc Indent(Doc contents) => new() { Contents = contents };
public static IndentDoc Indent(Doc contents)
{
return new IndentDoc { Contents = contents };
}

public static IndentDoc Indent(params Doc[] contents) => new() { Contents = Concat(contents) };
public static IndentDoc Indent(params Doc[] contents)
{
return new IndentDoc { Contents = Concat(contents) };
}

public static IndentDoc Indent(List<Doc> contents) => new() { Contents = Concat(contents) };
public static IndentDoc Indent(List<Doc> contents)
{
return new IndentDoc { Contents = Concat(contents) };
}

public static Doc IndentIf(bool condition, Doc contents)
{
return condition ? Indent(contents) : contents;
}

public static IfBreak IfBreak(Doc breakContents, Doc flatContents, string? groupId = null) =>
new()
public static IfBreak IfBreak(Doc breakContents, Doc flatContents, string? groupId = null)
{
return new IfBreak
{
FlatContents = flatContents,
BreakContents = breakContents,
GroupId = groupId,
};
}

public static IndentIfBreak IndentIfBreak(Doc contents, string groupId) =>
new(contents, groupId);
public static IndentIfBreak IndentIfBreak(Doc contents, string groupId)
{
return new IndentIfBreak(contents, groupId);
}

public static Doc Directive(string value) => new StringDoc(value, true);
public static Doc Directive(string value)
{
return new StringDoc(value, true);
}

public static ConditionalGroup ConditionalGroup(params Doc[] options) => new(options);
public static ConditionalGroup ConditionalGroup(params Doc[] options)
{
return new ConditionalGroup(options);
}

public static AlwaysFits AlwaysFits(Doc printedTrivia)
{
return new AlwaysFits(printedTrivia);
}

public static Region BeginRegion(string text) => new(text);
public static Region BeginRegion(string text)
{
return new Region(text);
}

public static Region EndRegion(string text) => new(text) { IsEnd = true };
public static Region EndRegion(string text)
{
return new Region(text) { IsEnd = true };
}
}

internal enum CommentType
Expand Down
Loading
Loading