Skip to content

Commit 93e93cf

Browse files
authored
Merge pull request #2695 from sharwell/sa1642-empty-element
Improve SA1642 code fix handling of empty lines
2 parents 297485d + f8627f7 commit 93e93cf

3 files changed

Lines changed: 106 additions & 24 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/SA1642SA1643CodeFixProvider.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ private static SyntaxList<XmlNodeSyntax> RemoveTrailingEmptyLines(SyntaxList<Xml
306306
{
307307
firstEmptyToken = j;
308308
}
309+
else if (textToken.IsXmlNewLine() && textToken.LeadingTrivia.Any(SyntaxKind.DocumentationCommentExteriorTrivia))
310+
{
311+
// Skip completely blank lines
312+
firstEmptyToken = j;
313+
}
309314
else if (textToken.IsKind(SyntaxKind.XmlTextLiteralToken) && !string.IsNullOrWhiteSpace(textToken.Text))
310315
{
311316
break;
@@ -314,8 +319,10 @@ private static SyntaxList<XmlNodeSyntax> RemoveTrailingEmptyLines(SyntaxList<Xml
314319

315320
if (firstEmptyToken > -1)
316321
{
317-
var newContent = SyntaxFactory.List(content.Take(firstEmptyToken));
318-
newContent.Add(newContent.Last());
322+
var newContent = content.RemoveAt(content.Count - 1);
323+
newContent = newContent
324+
.Add(XmlSyntaxFactory.Text(xmlText.TextTokens.Take(firstEmptyToken).ToArray()))
325+
.Add(XmlSyntaxFactory.Text(xmlText.TextTokens.Last()));
319326
return newContent;
320327
}
321328

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1642UnitTests.cs

Lines changed: 95 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ public TestClass() { }
918918

919919
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
920920
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
921-
await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false);
921+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
922922
}
923923

924924
/// <summary>
@@ -954,7 +954,82 @@ public TestClass() { }
954954

955955
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
956956
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
957-
await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false);
957+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
958+
}
959+
960+
[Theory]
961+
[WorkItem(2686, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2686")]
962+
[InlineData("")]
963+
[InlineData(" ")]
964+
public async Task TestConstructorEmptyDocumentationSingleLineAsync(string emptyContent)
965+
{
966+
var testCode = $@"namespace FooNamespace
967+
{{
968+
public class ClassName
969+
{{
970+
/// <summary>{emptyContent}</summary>
971+
public ClassName()
972+
{{
973+
}}
974+
}}
975+
}}";
976+
977+
var fixedCode = $@"namespace FooNamespace
978+
{{
979+
public class ClassName
980+
{{
981+
/// <summary>
982+
/// Initializes a new instance of the <see cref=""ClassName""/> class.{emptyContent}</summary>
983+
public ClassName()
984+
{{
985+
}}
986+
}}
987+
}}";
988+
989+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(5, 13);
990+
991+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
992+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
993+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
994+
}
995+
996+
[Theory]
997+
[WorkItem(2686, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2686")]
998+
[InlineData("")]
999+
[InlineData(" ")]
1000+
public async Task TestConstructorEmptyDocumentationAsync(string emptyContent)
1001+
{
1002+
var testCode = $@"namespace FooNamespace
1003+
{{
1004+
public class ClassName
1005+
{{
1006+
/// <summary>
1007+
///{emptyContent}
1008+
/// </summary>
1009+
public ClassName()
1010+
{{
1011+
}}
1012+
}}
1013+
}}";
1014+
1015+
var fixedCode = $@"namespace FooNamespace
1016+
{{
1017+
public class ClassName
1018+
{{
1019+
/// <summary>
1020+
/// Initializes a new instance of the <see cref=""ClassName""/> class.
1021+
/// </summary>
1022+
public ClassName()
1023+
{{
1024+
}}
1025+
}}
1026+
}}";
1027+
1028+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(5, 13);
1029+
1030+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
1031+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
1032+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
9581033
}
9591034

9601035
protected override Project ApplyCompilationOptions(Project project)
@@ -1138,44 +1213,44 @@ private async Task TestConstructorCorrectDocumentationCustomizedAsync(string typ
11381213

11391214
private async Task TestConstructorMissingDocumentationAsync(string typeKind, string modifiers, string part1, string part2, bool generic)
11401215
{
1141-
var testCode = @"namespace FooNamespace
1216+
string typeParameters = generic ? "<T1, T2>" : string.Empty;
1217+
string arguments = typeKind == "struct" && modifiers != "static" ? "int argument" : null;
1218+
var testCode = $@"namespace FooNamespace
11421219
{{
1143-
public {0} Foo{1}
1220+
public {typeKind} Foo{typeParameters}
11441221
{{
11451222
/// <summary>
11461223
/// </summary>
1147-
{2}
1148-
Foo({3})
1224+
{modifiers}
1225+
Foo({arguments})
11491226
{{
11501227
11511228
}}
11521229
}}
11531230
}}";
1154-
string arguments = typeKind == "struct" && modifiers != "static" ? "int argument" : null;
1155-
testCode = string.Format(testCode, typeKind, generic ? "<T1, T2>" : string.Empty, modifiers, arguments);
1156-
1157-
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(5, 13);
1158-
1159-
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
11601231

1161-
var fixedCode = @"namespace FooNamespace
1232+
string crefTypeParameters = generic ? "{T1, T2}" : string.Empty;
1233+
string part3 = part2.EndsWith(".") ? string.Empty : ".";
1234+
var fixedCode = $@"namespace FooNamespace
11621235
{{
1163-
public {0} Foo{1}
1236+
public {typeKind} Foo{typeParameters}
11641237
{{
11651238
/// <summary>
1166-
/// {3}<see cref=""Foo{2}""/>{4}{5}
1239+
/// {part1}<see cref=""Foo{crefTypeParameters}""/>{part2}{part3}
11671240
/// </summary>
1168-
{6}
1169-
Foo({7})
1241+
{modifiers}
1242+
Foo({arguments})
11701243
{{
11711244
11721245
}}
11731246
}}
11741247
}}";
11751248

1176-
string part3 = part2.EndsWith(".") ? string.Empty : ".";
1177-
fixedCode = string.Format(fixedCode, typeKind, generic ? "<T1, T2>" : string.Empty, generic ? "{T1, T2}" : string.Empty, part1, part2, part3, modifiers, arguments);
1178-
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
1249+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(5, 13);
1250+
1251+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
1252+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
1253+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
11791254
}
11801255

11811256
private async Task TestConstructorSimpleDocumentationAsync(string typeKind, string modifiers, string part1, string part2, bool generic)

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1643UnitTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public class TestClass
183183

184184
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
185185
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
186-
await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false);
186+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
187187
}
188188

189189
/// <summary>
@@ -217,7 +217,7 @@ public class TestClass
217217

218218
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
219219
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
220-
await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false);
220+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
221221
}
222222

223223
protected override Project ApplyCompilationOptions(Project project)

0 commit comments

Comments
 (0)