Skip to content

Commit e8f5f09

Browse files
authored
Working on keeping the closing tag of an element clean. (#1789)
closes #1785
1 parent 0325bb4 commit e8f5f09

File tree

5 files changed

+94
-6
lines changed

5 files changed

+94
-6
lines changed

Src/CSharpier.Core/Xml/RawNode.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,29 @@ public RawNode GetLastDescendant()
3131
{
3232
return this.NodeType is XmlNodeType.Element ? this.Nodes.LastOrDefault() ?? this : this;
3333
}
34+
35+
public override string? ToString()
36+
{
37+
if (this.IsTextLike())
38+
{
39+
return this.Value;
40+
}
41+
42+
if (this.NodeType is XmlNodeType.Element)
43+
{
44+
if (this.IsEmpty)
45+
{
46+
return "<" + this.Name + " />";
47+
}
48+
49+
return "<" + this.Name;
50+
}
51+
52+
if (this.NodeType is XmlNodeType.EndElement)
53+
{
54+
return "</" + this.Name + ">";
55+
}
56+
57+
return base.ToString();
58+
}
3459
}

Src/CSharpier.Core/Xml/XNodePrinters/Element.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ Doc PrintLineAfterChildren()
6666
{
6767
return Doc.Null;
6868
}
69+
70+
if (
71+
rawNode.Nodes is [{ NodeType: XmlNodeType.Text }]
72+
&& rawNode.Nodes[0].Value.TrimEnd(' ')[^1] is 'r' or '\n'
73+
)
74+
{
75+
return Doc.Null;
76+
}
77+
6978
return Doc.SoftLine;
7079
}
7180

Src/CSharpier.Core/Xml/XNodePrinters/Tag.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static Doc PrintClosingTagStart(RawNode rawNode, PrintingContext context)
5353
{
5454
var lastChild = rawNode.Nodes.LastOrDefault();
5555

56-
return lastChild is not null && NeedsToBorrowParentClosingTagStartMarker(lastChild)
56+
return lastChild is not null && PrintParentClosingTagStartWithContent(lastChild)
5757
? Doc.Null
5858
: PrintClosingTagStartMarker(rawNode, context);
5959
}
@@ -78,7 +78,7 @@ public static Doc PrintClosingTagEndMarker(RawNode rawNode)
7878

7979
public static Doc PrintClosingTagSuffix(RawNode rawNode, PrintingContext context)
8080
{
81-
return NeedsToBorrowParentClosingTagStartMarker(rawNode)
81+
return PrintParentClosingTagStartWithContent(rawNode)
8282
? PrintClosingTagStartMarker(rawNode.Parent!, context)
8383
: NeedsToBorrowNextOpeningTagStartMarker(rawNode)
8484
? PrintOpeningTagStartMarker(rawNode.NextNode!, context)
@@ -113,7 +113,7 @@ private static bool NeedsToBorrowNextOpeningTagStartMarker(RawNode rawNode)
113113
;
114114
}
115115

116-
private static bool NeedsToBorrowParentClosingTagStartMarker(RawNode rawNode)
116+
private static bool PrintParentClosingTagStartWithContent(RawNode rawNode)
117117
{
118118
/*
119119
* <p>
@@ -126,9 +126,35 @@ private static bool NeedsToBorrowParentClosingTagStartMarker(RawNode rawNode)
126126
* ^^^
127127
* >
128128
*/
129+
// TODO #1790 we really want this last condition only if the indentation of the last line of the text value matches
130+
// the indentation of the start element. Bleh.
131+
/*
132+
may have to handle one of these vs the second
133+
<Root>
134+
<Element Attribute="TheSign">
135+
Life is demanding.
136+
</Element>
137+
</Root>
138+
<Root>
139+
<Element Attribute="TheSign">
140+
Life is demanding.
141+
</Element>
142+
</Root>
143+
there is also this case
144+
<Root>
145+
<Element >
146+
Life is demanding.
147+
</Element>
148+
</Root>
149+
*/
129150
return rawNode.NextNode is null
130151
&& rawNode.IsTextLike()
131-
&& rawNode.GetLastDescendant().NodeType is XmlNodeType.Text;
152+
&& rawNode.GetLastDescendant() is { NodeType: XmlNodeType.Text } textNode
153+
&& (
154+
textNode.Value[^1] is not (' ' or '\r' or '\n')
155+
|| !textNode.Value.Contains('\n')
156+
|| rawNode.Parent!.Nodes.Any(o => !o.IsTextLike())
157+
);
132158
}
133159

134160
public static bool NeedsToBorrowParentOpeningTagEndMarker(RawNode rawNode)

Src/CSharpier.Tests/FormattingTests/TestFiles/xml/Attributes.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@
1111
AND '$(MSBuildProjectName)' != 'System.Net.Http.Formatting.NetCore.Test'
1212
AND '$(MSBuildProjectName)' != 'System.Net.Http.Formatting.NetStandard.Test' "
1313
/>
14+
<Element Attribute="TheSign">
15+
Life is demanding.
16+
</Element>
1417
</Root>

Src/CSharpier.Tests/FormattingTests/TestFiles/xml/StrictWhitespace.test

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,34 @@
33

44
Because whitespace is strict
55
The indentation of the closing element can't change
6-
</Element
7-
>
6+
</Element>
87
<Element>
98
Shorter Text with indentation that can't change
109
</Element>
10+
<returns>
11+
<para
12+
>A <see cref="T:System.Int32" /> containing a value that reflects the sort order of
13+
<paramref name="x" /> as compared to <paramref name="y" />. The following table defines the conditions
14+
under which the returned value is a negative number, zero, or a positive
15+
number.</para
16+
>
17+
</returns>
18+
<para>Some text that ends with a space. </para>
19+
<para
20+
>Some loooooooooooooooooooooooooooooooooong text with this <br /> and a space after this. </para
21+
>
22+
<exception cref="T:System.InvalidOperationException"
23+
>The current instance is read-only and a set operation was attempted. </exception
24+
>
25+
<example>
26+
<code>public void MethodName() {
27+
}
28+
</code>
29+
</example>
30+
<Root>
31+
<Element />
32+
<!--
33+
SomeText
34+
-->
35+
</Root>
1136
</Root>

0 commit comments

Comments
 (0)