Skip to content

Commit 47762e5

Browse files
committed
Fix reporting location of SA1629 after empty elements
Fixes #2680
1 parent 2832906 commit 47762e5

2 files changed

Lines changed: 45 additions & 3 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1629UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.DocumentationRules
55
{
6-
using System;
76
using System.Collections.Generic;
8-
using System.Linq;
97
using System.Threading;
108
using System.Threading.Tasks;
119
using Microsoft.CodeAnalysis;
@@ -297,6 +295,43 @@ public class TestClass
297295
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
298296
}
299297

298+
[Fact]
299+
[WorkItem(2680, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2680")]
300+
public async Task TestReportingAfterEmptyElementAsync()
301+
{
302+
var testCode = @"
303+
/// <summary>
304+
/// Test interface <see cref=""ITest""/>
305+
/// </summary>
306+
public interface ITest
307+
{
308+
/// <summary>
309+
/// Test method <see cref=""Method""/>
310+
/// </summary>
311+
void Method();
312+
}
313+
";
314+
315+
var fixedTestCode = @"
316+
/// <summary>
317+
/// Test interface <see cref=""ITest""/>
318+
/// </summary>
319+
public interface ITest
320+
{
321+
/// <summary>
322+
/// Test method <see cref=""Method""/>.
323+
/// </summary>
324+
void Method();
325+
}
326+
";
327+
328+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(8, 41);
329+
330+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
331+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
332+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
333+
}
334+
300335
protected override Project ApplyCompilationOptions(Project project)
301336
{
302337
var resolver = new TestXmlReferenceResolver();

StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1629DocumentationTextMustEndWithAPeriod.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ protected override void HandleXmlElement(SyntaxNodeAnalysisContext context, bool
7878
foreach (var xmlElement in syntaxList.OfType<XmlElementSyntax>())
7979
{
8080
var elementDone = false;
81+
int? reportingLocation = null;
8182
for (var i = xmlElement.Content.Count - 1; !elementDone && (i >= 0); i--)
8283
{
8384
if (xmlElement.Content[i] is XmlTextSyntax contentNode)
@@ -91,14 +92,20 @@ protected override void HandleXmlElement(SyntaxNodeAnalysisContext context, bool
9192
{
9293
if (!textWithoutTrailingWhitespace.EndsWith(".", StringComparison.Ordinal))
9394
{
94-
var location = Location.Create(xmlElement.SyntaxTree, new TextSpan(textToken.SpanStart + textWithoutTrailingWhitespace.Length, 1));
95+
var location = Location.Create(xmlElement.SyntaxTree, new TextSpan(reportingLocation ?? textToken.SpanStart + textWithoutTrailingWhitespace.Length, 1));
9596
context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
9697
}
9798

9899
elementDone = true;
99100
}
100101
}
101102
}
103+
else if (xmlElement.Content[i] is XmlEmptyElementSyntax emptyElement)
104+
{
105+
// If a diagnostic gets reported for the element, place the diagnostic after the last empty
106+
// element.
107+
reportingLocation = emptyElement.Span.End;
108+
}
102109
}
103110
}
104111
}

0 commit comments

Comments
 (0)