diff --git a/CSharpier.sln.DotSettings b/CSharpier.sln.DotSettings index 176f4143d..0c7f8f6fb 100644 --- a/CSharpier.sln.DotSettings +++ b/CSharpier.sln.DotSettings @@ -1,5 +1,8 @@  False + True + False + True True True diff --git a/Shell/UpdateCSharpierRepos.psm1 b/Shell/UpdateCSharpierRepos.psm1 index b72b809a1..cf6618c0c 100644 --- a/Shell/UpdateCSharpierRepos.psm1 +++ b/Shell/UpdateCSharpierRepos.psm1 @@ -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" @@ -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) { diff --git a/Src/CSharpier.Benchmarks/Program.cs b/Src/CSharpier.Benchmarks/Program.cs index e86c5b63d..d929eb8c3 100644 --- a/Src/CSharpier.Benchmarks/Program.cs +++ b/Src/CSharpier.Benchmarks/Program.cs @@ -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] @@ -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(); } @@ -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(); } diff --git a/Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs b/Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs index bd7e33ec4..058807dd8 100644 --- a/Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs +++ b/Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs @@ -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) { diff --git a/Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs b/Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs index a83508c02..73b4c10d3 100644 --- a/Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs +++ b/Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs @@ -11,8 +11,7 @@ internal class ConfigurationFileOptions public bool UseTabs { get; init; } [JsonConverter(typeof(CaseInsensitiveEnumConverter))] - public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } = - XmlWhitespaceSensitivity.Strict; + public XmlWhitespaceSensitivity? XmlWhitespaceSensitivity { get; init; } [JsonConverter(typeof(CaseInsensitiveEnumConverter))] public EndOfLine EndOfLine { get; init; } @@ -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, }; } @@ -80,8 +85,7 @@ internal class Override public bool UseTabs { get; init; } [JsonConverter(typeof(CaseInsensitiveEnumConverter))] - public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } = - XmlWhitespaceSensitivity.Strict; + public XmlWhitespaceSensitivity? XmlWhitespaceSensitivity { get; init; } [JsonConverter(typeof(CaseInsensitiveEnumConverter))] public EndOfLine EndOfLine { get; init; } diff --git a/Src/CSharpier.Cli/Options/OptionsProvider.cs b/Src/CSharpier.Cli/Options/OptionsProvider.cs index 6ff67d7c8..da223bbf8 100644 --- a/Src/CSharpier.Cli/Options/OptionsProvider.cs +++ b/Src/CSharpier.Cli/Options/OptionsProvider.cs @@ -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 FindCSharpierConfigAsync(string directoryName) diff --git a/Src/CSharpier.Core/CSharp/CSharpFormatter.cs b/Src/CSharpier.Core/CSharp/CSharpFormatter.cs index 984a53912..162d17550 100644 --- a/Src/CSharpier.Core/CSharp/CSharpFormatter.cs +++ b/Src/CSharpier.Core/CSharp/CSharpFormatter.cs @@ -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); @@ -181,6 +182,7 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult) LineEnding = lineEnding, IndentSize = printerOptions.IndentSize, UseTabs = printerOptions.UseTabs, + XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict, }, }; document = Node.Print( diff --git a/Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs b/Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs index e0f5176d4..dcac53eae 100644 --- a/Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs +++ b/Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs @@ -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 diff --git a/Src/CSharpier.Core/CSharpier.Core.csproj b/Src/CSharpier.Core/CSharpier.Core.csproj index eb67d0e95..9edf84f98 100644 --- a/Src/CSharpier.Core/CSharpier.Core.csproj +++ b/Src/CSharpier.Core/CSharpier.Core.csproj @@ -9,6 +9,7 @@ 002400000480000094000000060200000024000052534131000400000100010049d266ea1aeae09c0abfce28b8728314d4e4807126ee8bc56155a7ddc765997ed3522908b469ae133fc49ef0bfa957df36082c1c2e0ec8cdc05a4ca4dbd4e1bea6c17fc1008555e15af13a8fc871a04ffc38f5e60e6203bfaf01d16a2a283b90572ade79135801c1675bf38b7a5a60ec8353069796eb53a26ffdddc9ee1273be 13 true + One diff --git a/Src/CSharpier.Core/CodeFormatterOptions.cs b/Src/CSharpier.Core/CodeFormatterOptions.cs index 8246d8b61..5f123d9c8 100644 --- a/Src/CSharpier.Core/CodeFormatterOptions.cs +++ b/Src/CSharpier.Core/CodeFormatterOptions.cs @@ -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, diff --git a/Src/CSharpier.Core/DocTypes/Doc.cs b/Src/CSharpier.Core/DocTypes/Doc.cs index 4cf0170bb..a66874763 100644 --- a/Src/CSharpier.Core/DocTypes/Doc.cs +++ b/Src/CSharpier.Core/DocTypes/Doc.cs @@ -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(); @@ -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 contents) => - contents.Count == 1 ? contents[0] : new Concat(contents); + public static Doc Concat(List 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) { @@ -82,14 +102,20 @@ public static Doc Join(Doc separator, IEnumerable enumerable) return docs.Count == 1 ? docs[0] : Concat(docs); } - public static ForceFlat ForceFlat(List contents) => - new() { Contents = contents.Count == 0 ? contents[0] : Concat(contents) }; + public static ForceFlat ForceFlat(List 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 contents) => - new() { Contents = contents.Count == 1 ? contents[0] : Concat(contents) }; + public static Group Group(List contents) + { + return new Group { Contents = contents.Count == 1 ? contents[0] : Concat(contents) }; + } public static Group GroupWithId(string groupId, List contents) { @@ -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 contents) => new() { Contents = Concat(contents) }; + public static IndentDoc Indent(List 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 diff --git a/Src/CSharpier.Core/PrinterOptions.cs b/Src/CSharpier.Core/PrinterOptions.cs index e47d92496..6f31acb68 100644 --- a/Src/CSharpier.Core/PrinterOptions.cs +++ b/Src/CSharpier.Core/PrinterOptions.cs @@ -2,7 +2,10 @@ namespace CSharpier.Core; -internal class PrinterOptions(Formatter formatter) +internal class PrinterOptions( + Formatter formatter, + XmlWhitespaceSensitivity xmlWhitespaceSensitivity +) { public bool IncludeAST { get; init; } public bool IncludeDocTree { get; init; } @@ -26,9 +29,9 @@ public int IndentSize public EndOfLine EndOfLine { get; set; } = EndOfLine.Auto; public bool TrimInitialLines { get; init; } = true; public bool IncludeGenerated { get; set; } - public Formatter Formatter { get; set; } = formatter; + public Formatter Formatter { get; } = formatter; public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; set; } = - XmlWhitespaceSensitivity.Strict; + xmlWhitespaceSensitivity; public const int WidthUsedByTests = 100; @@ -62,7 +65,7 @@ public static Formatter GetFormatter(string filePath) var extension = possibleExtension[1..].ToLower(CultureInfo.InvariantCulture); - var formatter = extension switch + return extension switch { "cs" => Formatter.CSharp, "csx" => Formatter.CSharpScript, @@ -70,7 +73,23 @@ public static Formatter GetFormatter(string filePath) Formatter.XML, _ => Formatter.Unknown, }; - return formatter; + } + + public static XmlWhitespaceSensitivity GetXmlWhitespaceSensitivity(string filePath) + { + var possibleExtension = Path.GetExtension(filePath); + if (possibleExtension == string.Empty) + { + return XmlWhitespaceSensitivity.Strict; + } + + var extension = possibleExtension[1..].ToLower(CultureInfo.InvariantCulture); + + return extension switch + { + "xaml" or "axaml" => XmlWhitespaceSensitivity.Ignore, + _ => XmlWhitespaceSensitivity.Strict, + }; } } diff --git a/Src/CSharpier.Core/PublicAPI.Unshipped.txt b/Src/CSharpier.Core/PublicAPI.Unshipped.txt index 5f282702b..f02a42556 100644 --- a/Src/CSharpier.Core/PublicAPI.Unshipped.txt +++ b/Src/CSharpier.Core/PublicAPI.Unshipped.txt @@ -1 +1,5 @@ - \ No newline at end of file +CSharpier.Core.CodeFormatterOptions.XmlWhitespaceSensitivity.get -> CSharpier.Core.XmlWhitespaceSensitivity +CSharpier.Core.CodeFormatterOptions.XmlWhitespaceSensitivity.init -> void +CSharpier.Core.XmlWhitespaceSensitivity +CSharpier.Core.XmlWhitespaceSensitivity.Ignore = 1 -> CSharpier.Core.XmlWhitespaceSensitivity +CSharpier.Core.XmlWhitespaceSensitivity.Strict = 0 -> CSharpier.Core.XmlWhitespaceSensitivity \ No newline at end of file diff --git a/Src/CSharpier.Core/Xml/RawNode.cs b/Src/CSharpier.Core/Xml/RawNode.cs index 8642cf2b9..2cca831fd 100644 --- a/Src/CSharpier.Core/Xml/RawNode.cs +++ b/Src/CSharpier.Core/Xml/RawNode.cs @@ -21,6 +21,7 @@ internal class RawNode public RawAttribute[] Attributes { get; set; } = []; public List Nodes { get; set; } = []; public string Value { get; set; } = string.Empty; + public required XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; set; } public bool IsTextLike() { diff --git a/Src/CSharpier.Core/Xml/RawNodeReader.cs b/Src/CSharpier.Core/Xml/RawNodeReader.cs index e9cdd56db..676e7dbfd 100644 --- a/Src/CSharpier.Core/Xml/RawNodeReader.cs +++ b/Src/CSharpier.Core/Xml/RawNodeReader.cs @@ -12,6 +12,7 @@ class RawNodeReader { private readonly string originalXml; private readonly string lineEnding; + private XmlWhitespaceSensitivity currentXmlWhitespaceSensitivity; private int position; private readonly Stack elementStack = new(); @@ -22,7 +23,11 @@ class RawNodeReader private static readonly Regex NewlineRegex = new(@"\r\n|\n|\r", RegexOptions.Compiled); #endif - private RawNodeReader(string xml, string lineEnding) + private RawNodeReader( + string xml, + string lineEnding, + XmlWhitespaceSensitivity xmlWhitespaceSensitivity + ) { this.originalXml = NewlineRegex #if !NETSTANDARD2_0 @@ -30,17 +35,26 @@ private RawNodeReader(string xml, string lineEnding) #endif .Replace(xml, "\n"); this.lineEnding = lineEnding; + this.currentXmlWhitespaceSensitivity = xmlWhitespaceSensitivity; } - public static RawNode ParseXml(string originalXml, string lineEnding) + public static RawNode ParseXml( + string originalXml, + string lineEnding, + XmlWhitespaceSensitivity xmlWhitespaceSensitivity + ) { - var reader = new RawNodeReader(originalXml, lineEnding); + var reader = new RawNodeReader(originalXml, lineEnding, xmlWhitespaceSensitivity); return reader.ParseXml(); } private RawNode ParseXml() { - var rootNode = new RawNode { NodeType = XmlNodeType.Document }; + var rootNode = new RawNode + { + NodeType = XmlNodeType.Document, + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + }; this.elementStack.Push(rootNode); while (this.position < this.originalXml.Length) { @@ -63,7 +77,14 @@ private RawNode ParseXml() // we turn all whitespace into a single new line if it has more than a single newline in it // then we remove the leading/trailing whitespace nodes from a nodes child nodes before sending it to printing // then during printing when we find this we add a new line - this.AddNode(new RawNode { NodeType = XmlNodeType.Whitespace, Value = "\n" }); + this.AddNode( + new RawNode + { + NodeType = XmlNodeType.Whitespace, + Value = "\n", + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + } + ); } this.SkipWhitespace(); @@ -169,7 +190,12 @@ private void ParseComment() this.position++; } - var node = new RawNode { NodeType = XmlNodeType.Comment, Value = $"" }; + var node = new RawNode + { + NodeType = XmlNodeType.Comment, + Value = $"", + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + }; this.AddNode(node); } @@ -198,7 +224,12 @@ private void ParseCData() this.position++; } - var node = new RawNode { NodeType = XmlNodeType.CDATA, Value = $"" }; + var node = new RawNode + { + NodeType = XmlNodeType.CDATA, + Value = $"", + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + }; this.AddNode(node); } @@ -235,6 +266,7 @@ private void ParseProcessingInstruction() Name = name, NodeType = XmlNodeType.ProcessingInstruction, Value = $"", + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, }; this.AddNode(node); @@ -250,6 +282,7 @@ private void ParseEndElement() if (this.elementStack.Count > 0) { var element = this.elementStack.Pop(); + this.currentXmlWhitespaceSensitivity = element.XmlWhitespaceSensitivity; // we don't want to keep around any leading or trailing newlines in an elements children // it is easier to remove them here instead of dealing with it in the printer for (var x = element.Nodes.Count - 1; x >= 0; x--) @@ -296,12 +329,24 @@ private void ParseStartElement() this.SkipToChar('>'); + var xmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity; + + var spaceAttribute = attributes.FirstOrDefault(o => o.Name == "xml:space"); + if (spaceAttribute != null) + { + xmlWhitespaceSensitivity = + spaceAttribute.Value == "preserve" + ? XmlWhitespaceSensitivity.Strict + : XmlWhitespaceSensitivity.Ignore; + } + var node = new RawNode { Name = name, NodeType = XmlNodeType.Element, IsEmpty = isEmpty, Attributes = attributes.ToArray(), + XmlWhitespaceSensitivity = xmlWhitespaceSensitivity, }; this.AddNode(node); @@ -309,6 +354,7 @@ private void ParseStartElement() if (!isEmpty) { this.elementStack.Push(node); + this.currentXmlWhitespaceSensitivity = xmlWhitespaceSensitivity; } } @@ -339,7 +385,12 @@ private void ParseText() { return; } - var node = new RawNode { NodeType = XmlNodeType.Text, Value = text }; + var node = new RawNode + { + NodeType = XmlNodeType.Text, + Value = text, + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + }; this.AddNode(node); } @@ -516,7 +567,12 @@ private void ParseDocType() this.position++; } - var node = new RawNode { NodeType = XmlNodeType.DocumentType, Value = content.ToString() }; + var node = new RawNode + { + NodeType = XmlNodeType.DocumentType, + Value = content.ToString(), + XmlWhitespaceSensitivity = this.currentXmlWhitespaceSensitivity, + }; this.AddNode(node); } diff --git a/Src/CSharpier.Core/Xml/XNodePrinters/Attributes.cs b/Src/CSharpier.Core/Xml/XNodePrinters/Attributes.cs index 2f1a8d5ae..4120605e6 100644 --- a/Src/CSharpier.Core/Xml/XNodePrinters/Attributes.cs +++ b/Src/CSharpier.Core/Xml/XNodePrinters/Attributes.cs @@ -42,7 +42,7 @@ public static Doc Print(RawNode rawNode, PrintingContext context) */ ( rawNode.Nodes.Count != 0 - && Tag.NeedsToBorrowParentOpeningTagEndMarker(rawNode.Nodes.First()) + && Tag.NeedsToBorrowParentOpeningTagEndMarker(rawNode.Nodes.First(), context) ) || doNotBreakAttributes ) { diff --git a/Src/CSharpier.Core/Xml/XNodePrinters/Element.cs b/Src/CSharpier.Core/Xml/XNodePrinters/Element.cs index 8941a1811..2dd2124b9 100644 --- a/Src/CSharpier.Core/Xml/XNodePrinters/Element.cs +++ b/Src/CSharpier.Core/Xml/XNodePrinters/Element.cs @@ -34,19 +34,27 @@ Doc PrintLineBeforeChildren() } if ( - rawNode.Nodes.FirstOrDefault() is - { NodeType: XmlNodeType.Text, Value: ['\n', ..] or ['\r', ..] } + rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Strict + && rawNode.Nodes.FirstOrDefault() + is { NodeType: XmlNodeType.Text, Value: ['\n', ..] or ['\r', ..] } ) { return Doc.LiteralLine; } - if (rawNode.Attributes.Length == 0 && rawNode.Nodes is [{ NodeType: XmlNodeType.Text }]) + if ( + rawNode.Attributes.Length == 0 + && rawNode.Nodes is [{ NodeType: XmlNodeType.Text }] + && rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Strict + ) { return Doc.Null; } - if (rawNode.Nodes.Any(o => o.NodeType is XmlNodeType.Text && o.Value.Contains('\n'))) + if ( + rawNode.Nodes.Count > 1 + && rawNode.Nodes.Any(o => o.NodeType is XmlNodeType.Text && o.Value.Contains('\n')) + ) { return Doc.HardLine; } @@ -62,14 +70,19 @@ Doc PrintLineAfterChildren() return Doc.IfBreak(Doc.SoftLine, "", attrGroupId); } - if (rawNode.Attributes.Length == 0 && rawNode.Nodes is [{ NodeType: XmlNodeType.Text }]) + if ( + rawNode.Attributes.Length == 0 + && rawNode.Nodes is [{ NodeType: XmlNodeType.Text }] + && rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Strict + ) { return Doc.Null; } if ( - rawNode.Nodes is [{ NodeType: XmlNodeType.Text }] - && rawNode.Nodes[0].Value.TrimEnd(' ')[^1] is 'r' or '\n' + rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Strict + && rawNode.Nodes is [{ NodeType: XmlNodeType.Text }] + && rawNode.Nodes[0].Value.TrimEnd(' ')[^1] is '\r' or '\n' ) { return Doc.Null; diff --git a/Src/CSharpier.Core/Xml/XNodePrinters/ElementChildren.cs b/Src/CSharpier.Core/Xml/XNodePrinters/ElementChildren.cs index 0db54e9d4..6ef60d5ec 100644 --- a/Src/CSharpier.Core/Xml/XNodePrinters/ElementChildren.cs +++ b/Src/CSharpier.Core/Xml/XNodePrinters/ElementChildren.cs @@ -12,23 +12,27 @@ public static Doc Print(RawNode node, PrintingContext context) var groupIds = new List(); foreach (var _ in node.Nodes) { - groupIds.Add(context.GroupFor("symbol")); + groupIds.Add(context.GroupFor("children group")); } - var result = new DocListBuilder(node.Nodes.Count * 5); + var result = new List(); var x = 0; foreach (var childNode in node.Nodes) { if (childNode.NodeType is XmlNodeType.Whitespace) { - result.Add(Doc.HardLine); + if (childNode.NextNode is not { NodeType: XmlNodeType.Text }) + { + result.Add(Doc.HardLine); + } + continue; } - var prevParts = new DocListBuilder(2); - var leadingParts = new DocListBuilder(2); - var trailingParts = new DocListBuilder(2); - var nextParts = new DocListBuilder(2); + var prevParts = new List(); + var leadingParts = new List(); + var trailingParts = new List(); + var nextParts = new List(); var prevBetweenLine = childNode.PreviousNode is not null ? PrintBetweenLine(childNode.PreviousNode, childNode) @@ -50,7 +54,14 @@ public static Doc Print(RawNode node, PrintingContext context) } else { - leadingParts.Add(Doc.IfBreak(Doc.Null, Doc.SoftLine, groupIds[x - 1])); + if (groupIds.Count > 1) + { + leadingParts.Add(Doc.IfBreak(Doc.Null, Doc.SoftLine, groupIds[x - 1])); + } + else + { + leadingParts.Add(prevBetweenLine); + } } } @@ -69,22 +80,22 @@ public static Doc Print(RawNode node, PrintingContext context) } } - result.Add(prevParts.AsSpan()); + result.AddRange(prevParts); result.Add( Doc.Group( - Doc.Concat(ref leadingParts), + Doc.Concat(leadingParts), Doc.GroupWithId( groupIds[x], PrintChild(childNode, context), - Doc.Concat(ref trailingParts) + Doc.Concat(trailingParts) ) ) ); - result.Add(nextParts.AsSpan()); + result.AddRange(nextParts); x++; } - return Doc.Concat(ref result); + return Doc.Concat(result); } public static Doc PrintChild(RawNode child, PrintingContext context) @@ -113,7 +124,8 @@ public static Doc PrintChild(RawNode child, PrintingContext context) public static Doc PrintBetweenLine(RawNode prevNode, RawNode nextNode) { return - ( + (prevNode.NodeType is XmlNodeType.Whitespace && nextNode.NodeType is XmlNodeType.Text) + || ( prevNode.NodeType is XmlNodeType.Text or XmlNodeType.CDATA && nextNode.NodeType is XmlNodeType.Text or XmlNodeType.CDATA ) diff --git a/Src/CSharpier.Core/Xml/XNodePrinters/Node.cs b/Src/CSharpier.Core/Xml/XNodePrinters/Node.cs index 79436b939..e9660ad60 100644 --- a/Src/CSharpier.Core/Xml/XNodePrinters/Node.cs +++ b/Src/CSharpier.Core/Xml/XNodePrinters/Node.cs @@ -1,3 +1,4 @@ +using System.Text.RegularExpressions; using System.Xml; using CSharpier.Core.CSharp.SyntaxPrinter; using CSharpier.Core.DocTypes; @@ -5,8 +6,17 @@ namespace CSharpier.Core.Xml.XNodePrinters; -internal static class Node +internal static partial class Node { +#if NET6_0_OR_GREATER + [GeneratedRegex("\\s+")] + private static partial Regex WhitespaceRegexGenerator(); + + private static readonly Regex WhitespaceRegex = WhitespaceRegexGenerator(); +#else + private static readonly Regex WhitespaceRegex = new("\\s+"); +#endif + internal static Doc Print(RawNode node, PrintingContext context) { if (node.NodeType is XmlNodeType.Document) @@ -40,8 +50,8 @@ internal static Doc Print(RawNode node, PrintingContext context) { List doc = [ - Tag.PrintOpeningTagPrefix(node), - GetTextValue(node), + Tag.PrintOpeningTagPrefix(node, context), + GetTextValue(node, context), Tag.PrintClosingTagSuffix(node, context), ]; @@ -77,7 +87,7 @@ or XmlNodeType.CDATA throw new Exception("Need to handle + " + node.NodeType); } - private static Doc GetTextValue(RawNode rawNode) + private static Doc GetTextValue(RawNode rawNode, PrintingContext context) { var textValue = rawNode.Value; @@ -86,6 +96,29 @@ private static Doc GetTextValue(RawNode rawNode) return Doc.Null; } + if (rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Ignore) + { + if (rawNode.PreviousNode is null) + { + textValue = textValue.TrimStart(); + } + + if (rawNode.NextNode is null) + { + textValue = textValue.TrimEnd(); + } + + if (rawNode.Parent?.Nodes.Count == 1) + { + if (textValue.Length > 2) + { + var innerValue = textValue[1..^1]; + textValue = + textValue[0] + WhitespaceRegex.Replace(innerValue, " ") + textValue[^1]; + } + } + } + if (rawNode.Parent?.Nodes.First() == rawNode) { if (textValue[0] is '\r') diff --git a/Src/CSharpier.Core/Xml/XNodePrinters/Tag.cs b/Src/CSharpier.Core/Xml/XNodePrinters/Tag.cs index 1a0afb172..3532b57b1 100644 --- a/Src/CSharpier.Core/Xml/XNodePrinters/Tag.cs +++ b/Src/CSharpier.Core/Xml/XNodePrinters/Tag.cs @@ -11,7 +11,7 @@ public static Doc PrintOpeningTag(RawNode rawNode, PrintingContext context) return Doc.Concat( PrintOpeningTagStart(rawNode, context), Attributes.Print(rawNode, context), - rawNode.IsEmpty ? Doc.Null : PrintOpeningTagEnd(rawNode) + rawNode.IsEmpty ? Doc.Null : PrintOpeningTagEnd(rawNode, context) ); } @@ -22,23 +22,23 @@ rawNode.PreviousNode is not null && NeedsToBorrowNextOpeningTagStartMarker(rawNode.PreviousNode) ? Doc.Null : Doc.Concat( - PrintOpeningTagPrefix(rawNode), + PrintOpeningTagPrefix(rawNode, context), PrintOpeningTagStartMarker(rawNode, context) ); } - private static Doc PrintOpeningTagEnd(RawNode rawNode) + private static Doc PrintOpeningTagEnd(RawNode rawNode, PrintingContext context) { return rawNode.Nodes.FirstOrDefault() is { } firstNode - && NeedsToBorrowParentOpeningTagEndMarker(firstNode) + && NeedsToBorrowParentOpeningTagEndMarker(firstNode, context) ? Doc.Null : ">"; } - public static Doc PrintOpeningTagPrefix(RawNode rawNode) + public static Doc PrintOpeningTagPrefix(RawNode rawNode, PrintingContext context) { - return NeedsToBorrowParentOpeningTagEndMarker(rawNode) ? ">" : ""; + return NeedsToBorrowParentOpeningTagEndMarker(rawNode, context) ? ">" : ""; } public static Doc PrintClosingTag(RawNode rawNode, PrintingContext context) @@ -53,7 +53,7 @@ public static Doc PrintClosingTagStart(RawNode rawNode, PrintingContext context) { var lastChild = rawNode.Nodes.LastOrDefault(); - return lastChild is not null && PrintParentClosingTagStartWithContent(lastChild) + return lastChild is not null && PrintParentClosingTagStartWithContent(lastChild, context) ? Doc.Null : PrintClosingTagStartMarker(rawNode, context); } @@ -78,7 +78,7 @@ public static Doc PrintClosingTagEndMarker(RawNode rawNode) public static Doc PrintClosingTagSuffix(RawNode rawNode, PrintingContext context) { - return PrintParentClosingTagStartWithContent(rawNode) + return PrintParentClosingTagStartWithContent(rawNode, context) ? PrintClosingTagStartMarker(rawNode.Parent!, context) : NeedsToBorrowNextOpeningTagStartMarker(rawNode) ? PrintOpeningTagStartMarker(rawNode.NextNode!, context) @@ -87,11 +87,6 @@ public static Doc PrintClosingTagSuffix(RawNode rawNode, PrintingContext context private static Doc PrintOpeningTagStartMarker(RawNode rawNode, PrintingContext context) { - if (rawNode.NodeType != XmlNodeType.Element) - { - return "<" + rawNode.Name; - } - return $"<{rawNode.Name}"; } @@ -113,7 +108,10 @@ private static bool NeedsToBorrowNextOpeningTagStartMarker(RawNode rawNode) ; } - private static bool PrintParentClosingTagStartWithContent(RawNode rawNode) + private static bool PrintParentClosingTagStartWithContent( + RawNode rawNode, + PrintingContext context + ) { /* *

@@ -147,7 +145,8 @@ Life is demanding. */ - return rawNode.NextNode is null + return rawNode.XmlWhitespaceSensitivity is XmlWhitespaceSensitivity.Strict + && rawNode.NextNode is null && rawNode.IsTextLike() && rawNode.GetLastDescendant() is { NodeType: XmlNodeType.Text } textNode && ( @@ -157,7 +156,10 @@ Life is demanding. ); } - public static bool NeedsToBorrowParentOpeningTagEndMarker(RawNode rawNode) + public static bool NeedsToBorrowParentOpeningTagEndMarker( + RawNode rawNode, + PrintingContext context + ) { /* *

{ + window.sessionStorage.setItem("xmlWhitespaceSensitivity", value); + this.xmlWhitespaceSensitivity = value; + }; + setIndentSize = (value: number) => { window.sessionStorage.setItem("indentSize", value.toString(10)); this.indentSize = value; @@ -119,6 +125,7 @@ class AppState { this.indentSize, this.useTabs, this.formatter, + this.xmlWhitespaceSensitivity, ); runInAction(() => { diff --git a/Src/CSharpier.Playground/ClientApp/src/Controls.tsx b/Src/CSharpier.Playground/ClientApp/src/Controls.tsx index 3eec52dda..df906f932 100644 --- a/Src/CSharpier.Playground/ClientApp/src/Controls.tsx +++ b/Src/CSharpier.Playground/ClientApp/src/Controls.tsx @@ -13,6 +13,8 @@ export const Controls = observer(() => { setUseTabs, formatter, setFormatter, + xmlWhitespaceSensitivity, + setXmlWhitespaceSensitivity, showDoc, setShowDoc, hideNull, @@ -42,11 +44,43 @@ export const Controls = observer(() => { Use Tabs - + + + + {formatter === "XML" && ( + <> + + + + + )}

Debug

diff --git a/Src/CSharpier.Playground/ClientApp/src/FormatCode.ts b/Src/CSharpier.Playground/ClientApp/src/FormatCode.ts index 88b3c0af4..c74dfa8be 100644 --- a/Src/CSharpier.Playground/ClientApp/src/FormatCode.ts +++ b/Src/CSharpier.Playground/ClientApp/src/FormatCode.ts @@ -8,11 +8,12 @@ export const formatCode = async ( indentSize: number, useTabs: boolean, formatter: string, + xmlWhitespaceSensitivity: string, ) => { const makeRequest = async () => { const response = await fetch("/Format", { method: "POST", - body: JSON.stringify({ code, printWidth, indentSize, useTabs, formatter }), + body: JSON.stringify({ code, printWidth, indentSize, useTabs, formatter, xmlWhitespaceSensitivity }), headers: { "Content-Type": "application/json", "cache-control": "no-cache", diff --git a/Src/CSharpier.Playground/Controllers/FormatController.cs b/Src/CSharpier.Playground/Controllers/FormatController.cs index 8bf0bf7f1..d65f434af 100644 --- a/Src/CSharpier.Playground/Controllers/FormatController.cs +++ b/Src/CSharpier.Playground/Controllers/FormatController.cs @@ -32,6 +32,7 @@ public class PostModel public int IndentSize { get; set; } public bool UseTabs { get; set; } public string Formatter { get; set; } = string.Empty; + public string XmlWhitespaceSensitivity { get; set; } = string.Empty; } [HttpPost] @@ -47,7 +48,14 @@ CancellationToken cancellationToken var result = await CodeFormatter.FormatAsync( model.Code, - new PrinterOptions(parsedFormatter) + new PrinterOptions( + parsedFormatter, + model.XmlWhitespaceSensitivity switch + { + "Ignore" => XmlWhitespaceSensitivity.Ignore, + _ => XmlWhitespaceSensitivity.Strict, + } + ) { IncludeAST = true, IncludeDocTree = true, diff --git a/Src/CSharpier.Rider/CHANGELOG.md b/Src/CSharpier.Rider/CHANGELOG.md index 5c4b1942a..8496f9a45 100644 --- a/Src/CSharpier.Rider/CHANGELOG.md +++ b/Src/CSharpier.Rider/CHANGELOG.md @@ -1,6 +1,14 @@ # csharpier-rider Changelog +## [10.0.1] +- Re-add a global format on save option + +## 10.0.0 +- Make version a number that won't conflict with CSharpier itself. + +## [2.3.0] +- Add a global format on save option ## [10.0.5] - Re-add a global format on save option diff --git a/Src/CSharpier.Tests/CSharp/SyntaxPrinter/CSharpierIgnoreTests.cs b/Src/CSharpier.Tests/CSharp/SyntaxPrinter/CSharpierIgnoreTests.cs index 259a73b38..ffd281939 100644 --- a/Src/CSharpier.Tests/CSharp/SyntaxPrinter/CSharpierIgnoreTests.cs +++ b/Src/CSharpier.Tests/CSharp/SyntaxPrinter/CSharpierIgnoreTests.cs @@ -1,4 +1,5 @@ using AwesomeAssertions; +using CSharpier.Core; using CSharpier.Core.CSharp.SyntaxPrinter; namespace CSharpier.Tests.CSharp.SyntaxPrinter; @@ -71,6 +72,7 @@ private static string PrintWithoutFormatting(string code) LineEnding = Environment.NewLine, IndentSize = 4, UseTabs = false, + XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict, }, } ) diff --git a/Src/CSharpier.Tests/DeepRecursionTests.cs b/Src/CSharpier.Tests/DeepRecursionTests.cs index e8059a9c9..099bfcd9d 100644 --- a/Src/CSharpier.Tests/DeepRecursionTests.cs +++ b/Src/CSharpier.Tests/DeepRecursionTests.cs @@ -10,7 +10,10 @@ public class DeepRecursionTests public async Task Format_Should_Return_Error_For_Deep_Recursion() { var code = this.uglyLongConcatenatedString; - var result = await CSharpFormatter.FormatAsync(code, new PrinterOptions(Formatter.CSharp)); + var result = await CSharpFormatter.FormatAsync( + code, + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + ); result.FailureMessage.Should().Be("We can't handle this deep of recursion yet."); } diff --git a/Src/CSharpier.Tests/DocPrinterTests.cs b/Src/CSharpier.Tests/DocPrinterTests.cs index 4bbd22752..b02297275 100644 --- a/Src/CSharpier.Tests/DocPrinterTests.cs +++ b/Src/CSharpier.Tests/DocPrinterTests.cs @@ -728,7 +728,11 @@ public void Print_Should_Include_Single_NewLine_To_End_File(int instances, strin doc += endOfLine; } - var result = DocPrinter.Print(doc, new PrinterOptions(Formatter.CSharp), endOfLine); + var result = DocPrinter.Print( + doc, + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict), + endOfLine + ); result.Should().Be($"1{endOfLine}"); } @@ -786,7 +790,7 @@ private static string Print( return DocPrinter .Print( doc, - new PrinterOptions(Formatter.CSharp) + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) { Width = width, TrimInitialLines = trimInitialLines, diff --git a/Src/CSharpier.Tests/FormattingTests/BaseTest.cs b/Src/CSharpier.Tests/FormattingTests/BaseTest.cs index 339de10cd..a77c2cfe4 100644 --- a/Src/CSharpier.Tests/FormattingTests/BaseTest.cs +++ b/Src/CSharpier.Tests/FormattingTests/BaseTest.cs @@ -33,16 +33,41 @@ public void BuildTests(DynamicTestBuilderContext context, string folder) { var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file.Name); var useTabs = fileNameWithoutExtension.EndsWith("_Tabs", StringComparison.Ordinal); + var directoryName = file.Directory!.Name; + var xmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict; + if (directoryName.Contains('_')) + { + var parts = directoryName.Split('_'); + directoryName = parts[0]; + xmlWhitespaceSensitivity = parts[1] is "ignore" + ? XmlWhitespaceSensitivity.Ignore + : XmlWhitespaceSensitivity.Strict; + } + + var formatter = directoryName switch + { + "cs" => Formatter.CSharp, + "csx" => Formatter.CSharpScript, + "xml" => Formatter.XML, + _ => Formatter.Unknown, + }; + + var printerOptions = new PrinterOptions(formatter, xmlWhitespaceSensitivity) + { + UseTabs = useTabs, + Width = PrinterOptions.WidthUsedByTests, + IndentSize = formatter == Formatter.XML ? 2 : 4, + }; context.AddTest( new DynamicTest { - TestMethod = @class => @class.RunTest(string.Empty, string.Empty, false), + TestMethod = @class => @class.RunTest(string.Empty, string.Empty, null!), TestMethodArguments = [ fileNameWithoutExtension, file.Directory!.Name, - useTabs, + printerOptions, ], DisplayName = fileNameWithoutExtension, } @@ -51,13 +76,17 @@ public void BuildTests(DynamicTestBuilderContext context, string folder) } } - public async Task RunTest(string fileName, string fileExtensionWithoutDot, bool useTabs = false) + internal async Task RunTest( + string fileName, + string directoryName, + PrinterOptions printerOptions + ) { var filePath = Path.Combine( this.rootDirectory.FullName, "FormattingTests", "TestFiles", - fileExtensionWithoutDot, + directoryName, fileName + ".test" ); var fileReaderResult = await FileReader.ReadFileAsync( @@ -66,22 +95,9 @@ public async Task RunTest(string fileName, string fileExtensionWithoutDot, bool CancellationToken.None ); - var formatter = fileExtensionWithoutDot switch - { - "cs" => Formatter.CSharp, - "csx" => Formatter.CSharpScript, - "xml" => Formatter.XML, - _ => Formatter.Unknown, - }; - var result = await CodeFormatter.FormatAsync( fileReaderResult.FileContents, - new PrinterOptions(formatter) - { - Width = PrinterOptions.WidthUsedByTests, - UseTabs = useTabs, - IndentSize = formatter == Formatter.XML ? 2 : 4, - }, + printerOptions, CancellationToken.None ); diff --git a/Src/CSharpier.Tests/FormattingTests/LineEndingEdgeCase.cs b/Src/CSharpier.Tests/FormattingTests/LineEndingEdgeCase.cs index 137eedfdc..68a0af82c 100644 --- a/Src/CSharpier.Tests/FormattingTests/LineEndingEdgeCase.cs +++ b/Src/CSharpier.Tests/FormattingTests/LineEndingEdgeCase.cs @@ -32,7 +32,10 @@ void MethodName() var result = await CSharpFormatter.FormatAsync( unformattedCode, - new PrinterOptions(Formatter.CSharp) { EndOfLine = endOfLine }, + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + { + EndOfLine = endOfLine, + }, CancellationToken.None ); diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData_EdgeCase.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData_EdgeCase.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData_EdgeCase.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData_EdgeCase.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData_InText.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData_InText.test new file mode 100644 index 000000000..285e169af --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/CData_InText.test @@ -0,0 +1,4 @@ + + SomeText + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Comments.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Comments.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Comments.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Comments.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Conditions.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Conditions.test new file mode 100644 index 000000000..fea994830 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Conditions.test @@ -0,0 +1,11 @@ + + + + v4.5.2 + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/DoNotBreak.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/DoNotBreak.test new file mode 100644 index 000000000..56bfda863 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/DoNotBreak.test @@ -0,0 +1,8 @@ + + + + ..\..\packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.expected.test new file mode 100644 index 000000000..ccedaed25 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.expected.test @@ -0,0 +1,10 @@ + + + TextValue + + + TextValue + + TextValue + TextValue + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.test new file mode 100644 index 000000000..89f1ec8d6 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements.test @@ -0,0 +1,10 @@ + + TextValue + TextValue + + TextValue + + + TextValue + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.expected.test new file mode 100644 index 000000000..ccedaed25 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.expected.test @@ -0,0 +1,10 @@ + + + TextValue + + + TextValue + + TextValue + TextValue + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.test new file mode 100644 index 000000000..ccedaed25 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements2.test @@ -0,0 +1,10 @@ + + + TextValue + + + TextValue + + TextValue + TextValue + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_HtmlValues.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_HtmlValues.test new file mode 100644 index 000000000..5e89039bd --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_HtmlValues.test @@ -0,0 +1,12 @@ + + + Some text +
url.com + more text. + + + Some long text to make things break + url.com + more text. + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_MixedContent.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_MixedContent.test new file mode 100644 index 000000000..36662f7fa --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_MixedContent.test @@ -0,0 +1,5 @@ + + Text + + Text + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.expected.test new file mode 100644 index 000000000..265f2c726 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.expected.test @@ -0,0 +1,11 @@ + + + TextValue + + + + TextValue + + TextValue + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.test new file mode 100644 index 000000000..0da1bc645 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/Elements_XmlSpace.test @@ -0,0 +1,13 @@ + + + TextValue + + + + TextValue + + + TextValue + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines_RemoveSome.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines_RemoveSome.expected.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines_RemoveSome.expected.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines_RemoveSome.expected.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines_RemoveSome.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines_RemoveSome.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EmptyLines_RemoveSome.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EmptyLines_RemoveSome.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EncodedValues.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EncodedValues.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/EncodedValues.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/EncodedValues.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/LongAttributes.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/LongAttributes.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/LongAttributes.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/LongAttributes.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/NewLines.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/NewLines.test new file mode 100644 index 000000000..ae988fd5c --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/NewLines.test @@ -0,0 +1,6 @@ + + + Because whitespace is ignore The indentation of the closing element can change, and the newline above goes away + + Shorter Text with indentation that can change + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/PrefixedElementNames.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/PrefixedElementNames.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/PrefixedElementNames.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/PrefixedElementNames.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/RetainXmlElement.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/RetainXmlElement.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/RetainXmlElement.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/RetainXmlElement.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/StrictWhitespace.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/StrictWhitespace.test new file mode 100644 index 000000000..f658edcb4 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/StrictWhitespace.test @@ -0,0 +1,36 @@ + + + Because whitespace is strict The indentation of the closing element can't change + + Shorter Text with indentation that can't change + + + A + + containing a value that reflects the sort order of + + as compared to + + . The following table defines the conditions under which the returned + value is a negative number, zero, or a positive number. + + + Some text that ends with a space. + + Some loooooooooooooooooooooooooooooooooong text with this +
+ and a space after this. +
+ + The current instance is read-only and a set operation was attempted. + + + public void MethodName() { } + + + + + +
diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XProcessingInstruction.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XProcessingInstruction.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XProcessingInstruction.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XProcessingInstruction.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XmlDeclarationWorksWithMapping.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XmlDeclarationWorksWithMapping.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XmlDeclarationWorksWithMapping.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XmlDeclarationWorksWithMapping.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XmlDocumentType.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XmlDocumentType.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/XmlDocumentType.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_ignore/XmlDocumentType.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Attributes.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Attributes.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Attributes.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Attributes.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/BasicProject.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/BasicProject.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/BasicProject.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/BasicProject.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData.test new file mode 100644 index 000000000..687730eda --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData.test @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData_EdgeCase.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData_EdgeCase.test new file mode 100644 index 000000000..1878d288c --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData_EdgeCase.test @@ -0,0 +1,5 @@ + + + entryPointFullTypeName + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData_InText.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData_InText.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/CData_InText.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/CData_InText.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Comments.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Comments.test new file mode 100644 index 000000000..b6a2db72e --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Comments.test @@ -0,0 +1,12 @@ + + + + + CA1031; + IDE0005; + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Conditions.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Conditions.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Conditions.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Conditions.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoNotBreak.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoNotBreak.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoNotBreak.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoNotBreak.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoubleQuotesForced.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoubleQuotesForced.expected.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoubleQuotesForced.expected.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoubleQuotesForced.expected.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoubleQuotesForced.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoubleQuotesForced.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/DoubleQuotesForced.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/DoubleQuotesForced.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Element_DoesNotAddPrefix.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Element_DoesNotAddPrefix.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Element_DoesNotAddPrefix.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Element_DoesNotAddPrefix.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Elements.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Elements.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Elements.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Elements.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Elements_HtmlValues.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Elements_HtmlValues.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Elements_HtmlValues.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/Elements_HtmlValues.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines.test new file mode 100644 index 000000000..48a72189a --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines.test @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.expected.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.expected.test new file mode 100644 index 000000000..f7c26ecb7 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.expected.test @@ -0,0 +1,5 @@ + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.test new file mode 100644 index 000000000..7ac67cf30 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EmptyLines_RemoveSome.test @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EncodedValues.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EncodedValues.test new file mode 100644 index 000000000..5ad7a455f --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/EncodedValues.test @@ -0,0 +1,6 @@ + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/LongAttributes.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/LongAttributes.test new file mode 100644 index 000000000..6ef7a04ba --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/LongAttributes.test @@ -0,0 +1,98 @@ + + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/PrefixedElementNames.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/PrefixedElementNames.test new file mode 100644 index 000000000..6eed22404 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/PrefixedElementNames.test @@ -0,0 +1,6 @@ + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/RetainXmlElement.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/RetainXmlElement.test new file mode 100644 index 000000000..820a64750 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/RetainXmlElement.test @@ -0,0 +1,2 @@ + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml/StrictWhitespace.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/StrictWhitespace.test similarity index 100% rename from Src/CSharpier.Tests/FormattingTests/TestFiles/xml/StrictWhitespace.test rename to Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/StrictWhitespace.test diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XProcessingInstruction.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XProcessingInstruction.test new file mode 100644 index 000000000..692c52632 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XProcessingInstruction.test @@ -0,0 +1,3 @@ + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDeclarationWorksWithMapping.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDeclarationWorksWithMapping.test new file mode 100644 index 000000000..5e9f4ffe7 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDeclarationWorksWithMapping.test @@ -0,0 +1,6 @@ + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDocumentType.test b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDocumentType.test new file mode 100644 index 000000000..0f8095c88 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/TestFiles/xml_strict/XmlDocumentType.test @@ -0,0 +1,6 @@ + + + + + + diff --git a/Src/CSharpier.Tests/FormattingTests/XmlFormatting.cs b/Src/CSharpier.Tests/FormattingTests/XmlIgnoreFormatting.cs similarity index 56% rename from Src/CSharpier.Tests/FormattingTests/XmlFormatting.cs rename to Src/CSharpier.Tests/FormattingTests/XmlIgnoreFormatting.cs index 390d7f837..d45bc229d 100644 --- a/Src/CSharpier.Tests/FormattingTests/XmlFormatting.cs +++ b/Src/CSharpier.Tests/FormattingTests/XmlIgnoreFormatting.cs @@ -1,10 +1,10 @@ namespace CSharpier.Tests.FormattingTests; -public class XmlFormatting : BaseTest +public class XmlIgnoreFormatting : BaseTest { [DynamicTestBuilder] public void BuildTests(DynamicTestBuilderContext context) { - this.BuildTests(context, "xml"); + this.BuildTests(context, "xml_ignore"); } } diff --git a/Src/CSharpier.Tests/FormattingTests/XmlStrictFormatting.cs b/Src/CSharpier.Tests/FormattingTests/XmlStrictFormatting.cs new file mode 100644 index 000000000..d71d5a429 --- /dev/null +++ b/Src/CSharpier.Tests/FormattingTests/XmlStrictFormatting.cs @@ -0,0 +1,10 @@ +namespace CSharpier.Tests.FormattingTests; + +public class XmlStrictFormatting : BaseTest +{ + [DynamicTestBuilder] + public void BuildTests(DynamicTestBuilderContext context) + { + this.BuildTests(context, "xml_strict"); + } +} diff --git a/Src/CSharpier.Tests/LineEndingTests.cs b/Src/CSharpier.Tests/LineEndingTests.cs index 137896ff9..445b90bae 100644 --- a/Src/CSharpier.Tests/LineEndingTests.cs +++ b/Src/CSharpier.Tests/LineEndingTests.cs @@ -22,7 +22,7 @@ public async Task LineEndings_Should_Not_Affect_Printed_Output_With_Verbatim_Str var codeWithLf = code.Replace("\r\n", "\n"); var codeWithCrLf = codeWithLf.Replace("\n", "\r\n"); - var printerOptions = new PrinterOptions(Formatter.CSharp) + var printerOptions = new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) { EndOfLine = EndOfLine.Auto, Width = 80, @@ -49,7 +49,7 @@ public async Task LineEndings_Should_Not_Affect_Printed_Output_With_Interpolated var codeWithLf = code.Replace("\r\n", "\n"); var codeWithCrLf = codeWithLf.Replace("\n", "\r\n"); - var printerOptions = new PrinterOptions(Formatter.CSharp) + var printerOptions = new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) { EndOfLine = EndOfLine.Auto, Width = 80, @@ -74,7 +74,10 @@ EndOfLine endOfLine string value = @""one{newLine}two""; }} "; - var printerOptions = new PrinterOptions(Formatter.CSharp) { EndOfLine = endOfLine }; + var printerOptions = new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + { + EndOfLine = endOfLine, + }; var result = await CSharpFormatter.FormatAsync(code, printerOptions); result.Code.Should().NotContain($"one{newLine}two"); } @@ -93,7 +96,10 @@ EndOfLine endOfLine string value = @""one{escapedNewLine}two""; }} "; - var printerOptions = new PrinterOptions(Formatter.CSharp) { EndOfLine = endOfLine }; + var printerOptions = new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + { + EndOfLine = endOfLine, + }; var result = await CSharpFormatter.FormatAsync(code, printerOptions); result.Code.Should().Contain(escapedNewLine); } diff --git a/Src/CSharpier.Tests/OptionsProviderTests.cs b/Src/CSharpier.Tests/OptionsProviderTests.cs index 99f4d0cc6..f3f1e1ffe 100644 --- a/Src/CSharpier.Tests/OptionsProviderTests.cs +++ b/Src/CSharpier.Tests/OptionsProviderTests.cs @@ -21,14 +21,19 @@ public async Task Should_Return_Default_CSharp_Options_With_Empty_Json() } [Test] - public async Task Should_Return_Default_Xml_Options_With_Empty_Json() + [Arguments("xml")] + [Arguments("xaml")] + public async Task Should_Return_Default_Xml_Options_With_Empty_Json(string extension) { var context = new TestContext(); context.WhenAFileExists("c:/test/.csharpierrc", "{}"); - var result = await context.CreateProviderAndGetOptionsFor("c:/test", "c:/test/test.xml"); + var result = await context.CreateProviderAndGetOptionsFor( + "c:/test", + "c:/test/test." + extension + ); - ShouldHaveDefaultXmlOptions(result); + ShouldHaveDefaultXmlOptions(result, extension); } [Test] @@ -66,7 +71,7 @@ string extension "c:/test/test." + extension ); - ShouldHaveDefaultXmlOptions(result); + ShouldHaveDefaultXmlOptions(result, extension); } [Test] @@ -102,7 +107,7 @@ public async Task Should_Return_Json_Extension_Options() { "printWidth": 10, "endOfLine": "crlf", - "xmlWhitespaceSensitivity": "xaml" + "xmlWhitespaceSensitivity": "ignore" } """ ); @@ -111,7 +116,7 @@ public async Task Should_Return_Json_Extension_Options() result.Width.Should().Be(10); result.EndOfLine.Should().Be(EndOfLine.CRLF); - result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Xaml); + result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Ignore); } [Test] @@ -125,7 +130,7 @@ public async Task Should_Return_Yaml_Extension_Options(string extension) """ printWidth: 10 endOfLine: crlf -xmlWhitespaceSensitivity: xaml +xmlWhitespaceSensitivity: ignore """ ); @@ -133,7 +138,7 @@ public async Task Should_Return_Yaml_Extension_Options(string extension) result.Width.Should().Be(10); result.EndOfLine.Should().Be(EndOfLine.CRLF); - result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Xaml); + result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Ignore); } [Test] @@ -321,6 +326,7 @@ public async Task Should_Return_Default_CSharp_Options_With_Empty_EditorConfig(s [Test] [Arguments("xml")] + [Arguments("xaml")] [Arguments("csproj")] [Arguments("props")] [Arguments("targets")] @@ -334,7 +340,7 @@ public async Task Should_Return_Default_Xml_Options_With_Empty_EditorConfig(stri "c:/test", "c:/test/test." + extension ); - ShouldHaveDefaultXmlOptions(result); + ShouldHaveDefaultXmlOptions(result, extension); } [Test] @@ -350,7 +356,7 @@ public async Task Should_Support_EditorConfig_Basic() indent_size = 2 max_line_length = 10 end_of_line = crlf - csharpier_xml_whitespace_sensitivity = xaml + csharpier_xml_whitespace_sensitivity = ignore """ ); @@ -360,7 +366,7 @@ public async Task Should_Support_EditorConfig_Basic() result.IndentSize.Should().Be(2); result.Width.Should().Be(10); result.EndOfLine.Should().Be(EndOfLine.CRLF); - result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Xaml); + result.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Ignore); } [Test] @@ -837,6 +843,25 @@ public async Task Should_Prefer_Closer_CSharpierrc() result.IndentSize.Should().Be(1); } + [Test] + [Arguments("xml", XmlWhitespaceSensitivity.Strict)] + [Arguments("xaml", XmlWhitespaceSensitivity.Ignore)] + [Arguments("axaml", XmlWhitespaceSensitivity.Ignore)] + public async Task Should_Default_XmlWhitespaceSensitivity( + string fileExtension, + XmlWhitespaceSensitivity expectedXmlWhitespaceSensitivity + ) + { + var context = new TestContext(); + + var result = await context.CreateProviderAndGetOptionsFor( + "c:/test", + "c:/test/file." + fileExtension + ); + + result.XmlWhitespaceSensitivity.Should().Be(expectedXmlWhitespaceSensitivity); + } + private static void ShouldHaveDefaultCSharpOptions(PrinterOptions printerOptions) { printerOptions.Width.Should().Be(100); @@ -845,13 +870,19 @@ private static void ShouldHaveDefaultCSharpOptions(PrinterOptions printerOptions printerOptions.EndOfLine.Should().Be(EndOfLine.Auto); } - private static void ShouldHaveDefaultXmlOptions(PrinterOptions printerOptions) + private static void ShouldHaveDefaultXmlOptions(PrinterOptions printerOptions, string extension) { printerOptions.Width.Should().Be(100); printerOptions.IndentSize.Should().Be(2); printerOptions.UseTabs.Should().BeFalse(); printerOptions.EndOfLine.Should().Be(EndOfLine.Auto); - printerOptions.XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Strict); + printerOptions + .XmlWhitespaceSensitivity.Should() + .Be( + extension is "xaml" or "axaml" + ? XmlWhitespaceSensitivity.Ignore + : XmlWhitespaceSensitivity.Strict + ); } private sealed class TestContext diff --git a/Src/CSharpier.Tests/PrinterOptionsTests.cs b/Src/CSharpier.Tests/PrinterOptionsTests.cs index 692de9614..0f3db6f4a 100644 --- a/Src/CSharpier.Tests/PrinterOptionsTests.cs +++ b/Src/CSharpier.Tests/PrinterOptionsTests.cs @@ -13,7 +13,10 @@ public void GetLineEndings_Should_Return_Easy_Cases(EndOfLine endOfLine, string var code = "tester\n"; var result = PrinterOptions.GetLineEnding( code, - new PrinterOptions(Formatter.CSharp) { EndOfLine = endOfLine } + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + { + EndOfLine = endOfLine, + } ); result.Should().Be(expected); @@ -26,7 +29,10 @@ public void GetLineEndings_Should_Return_Easy_Cases(EndOfLine endOfLine, string [Arguments("tester", "\n")] public void GetLineEndings_With_Auto_Should_Detect(string code, string expected) { - var result = PrinterOptions.GetLineEnding(code, new PrinterOptions(Formatter.CSharp)); + var result = PrinterOptions.GetLineEnding( + code, + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + ); result.Should().Be(expected); } diff --git a/Src/CSharpier.Tests/RawNodeReaderTests.cs b/Src/CSharpier.Tests/RawNodeReaderTests.cs index ba2661de4..0ad762266 100644 --- a/Src/CSharpier.Tests/RawNodeReaderTests.cs +++ b/Src/CSharpier.Tests/RawNodeReaderTests.cs @@ -1,6 +1,7 @@ #pragma warning disable using AwesomeAssertions; +using CSharpier.Core; using CSharpier.Core.Xml; namespace CSharpier.Tests; @@ -116,8 +117,74 @@ public void Should_Read_Various_Attributes(string xml, string attributeValue) attribute.Value.Should().Be(attributeValue.Replace("\"", """)); } - private static List ReadAllNodes(string xml) + [Test] + public void Should_Set_Top_Level_Whitespace() + { + var nodes = ReadAllNodes( + """ + + """, + XmlWhitespaceSensitivity.Ignore + ); + nodes.First().XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Ignore); + } + + [Test] + public void Should_Override_Whitespace() + { + var nodes = ReadAllNodes( + """ + + """, + XmlWhitespaceSensitivity.Ignore + ); + nodes.First().XmlWhitespaceSensitivity.Should().Be(XmlWhitespaceSensitivity.Strict); + } + + [Test] + public void Should_Override_Whitespace_On_Children() + { + var nodes = ReadAllNodes( + """ + + + + """, + XmlWhitespaceSensitivity.Ignore + ); + nodes + .First() + .Nodes.First() + .XmlWhitespaceSensitivity.Should() + .Be(XmlWhitespaceSensitivity.Strict); + } + + [Test] + public void Should_Override_Whitespace_On_Children2() + { + var nodes = ReadAllNodes( + """ + + + + + + """, + XmlWhitespaceSensitivity.Ignore + ); + nodes + .First() + .Nodes.First() + .Nodes.First() + .XmlWhitespaceSensitivity.Should() + .Be(XmlWhitespaceSensitivity.Ignore); + } + + private static List ReadAllNodes( + string xml, + XmlWhitespaceSensitivity xmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict + ) { - return RawNodeReader.ParseXml(xml, Environment.NewLine).Nodes; + return RawNodeReader.ParseXml(xml, Environment.NewLine, xmlWhitespaceSensitivity).Nodes; } } diff --git a/Src/CSharpier.Tests/Samples/Samples.cs b/Src/CSharpier.Tests/Samples/Samples.cs index 12d95c179..a0c31a4a6 100644 --- a/Src/CSharpier.Tests/Samples/Samples.cs +++ b/Src/CSharpier.Tests/Samples/Samples.cs @@ -27,7 +27,11 @@ public static async Task RunTest(string fileName) var code = await File.ReadAllTextAsync(file); var result = await CSharpFormatter.FormatAsync( code, - new PrinterOptions(Formatter.CSharp) { IncludeDocTree = true, IncludeAST = true } + new PrinterOptions(Formatter.CSharp, XmlWhitespaceSensitivity.Strict) + { + IncludeDocTree = true, + IncludeAST = true, + } ); var syntaxNodeComparer = new SyntaxNodeComparer( diff --git a/Src/CSharpier.VSCode/src/FormattingService.ts b/Src/CSharpier.VSCode/src/FormattingService.ts index a1cd8011b..73091f889 100644 --- a/Src/CSharpier.VSCode/src/FormattingService.ts +++ b/Src/CSharpier.VSCode/src/FormattingService.ts @@ -89,7 +89,7 @@ export class FormattingService { private minimalEdit(document: TextDocument, newText: string) { let existingText = document.getText(); - + let i = 0; while (i < existingText.length && i < newText.length && existingText[i] === newText[i]) { ++i;