Skip to content

Commit b306648

Browse files
committed
Updated SA1642 and SA1643
1 parent 9de3cb3 commit b306648

4 files changed

Lines changed: 401 additions & 22 deletions

File tree

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
4848

4949
foreach (var diagnostic in context.Diagnostics)
5050
{
51-
var node = root.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true);
51+
if (diagnostic.Properties.ContainsKey(StandardTextDiagnosticBase.NoCodeFixKey))
52+
{
53+
continue;
54+
}
5255

56+
var node = root.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true);
5357
var xmlElementSyntax = node as XmlElementSyntax;
5458

5559
if (xmlElementSyntax != null)

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

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
66
using System.Collections.Generic;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using Microsoft.CodeAnalysis;
910
using Microsoft.CodeAnalysis.CodeFixes;
1011
using Microsoft.CodeAnalysis.Diagnostics;
1112
using StyleCop.Analyzers.DocumentationRules;
13+
using StyleCop.Analyzers.Test.Helpers;
1214
using TestHelper;
1315
using Xunit;
1416
using static StyleCop.Analyzers.DocumentationRules.SA1642ConstructorSummaryDocumentationMustBeginWithStandardText;
@@ -424,6 +426,163 @@ protected CustomizableBlockSubscriberBase()
424426
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
425427
}
426428

429+
/// <summary>
430+
/// Verifies that a constructor with the correct summary text from included documentation will not produce any diagnostics.
431+
/// </summary>
432+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
433+
[Fact]
434+
public async Task TestConstructorWithValidSummaryInIncludedDocsAsync()
435+
{
436+
var testCode = @"
437+
public class TestClass
438+
{
439+
/// <include file='ValidSummary.xml' path='/TestClass/TestClass/*'/>
440+
public TestClass() { }
441+
}
442+
";
443+
444+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
445+
}
446+
447+
/// <summary>
448+
/// Verifies that a constructor with the missing summary tag from included documentation will not produce any diagnostics.
449+
/// </summary>
450+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
451+
[Fact]
452+
public async Task TestConstructorWithMissingSummaryInIncludedDocsAsync()
453+
{
454+
var testCode = @"
455+
public class TestClass
456+
{
457+
/// <include file='MissingSummary.xml' path='/TestClass/TestClass/*'/>
458+
public TestClass() { }
459+
}
460+
";
461+
462+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
463+
}
464+
465+
/// <summary>
466+
/// Verifies that a constructor with an empty summary tag from included documentation will produce a diagnostic and offer no codefix.
467+
/// </summary>
468+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
469+
[Fact]
470+
public async Task TestConstructorWithEmptySummaryInIncludedDocsAsync()
471+
{
472+
var testCode = @"
473+
public class TestClass
474+
{
475+
/// <include file='EmptySummary.xml' path='/TestClass/TestClass/*'/>
476+
public TestClass() { }
477+
}
478+
";
479+
480+
var expected = this.CSharpDiagnostic().WithLocation(4, 9);
481+
482+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
483+
var offeredFixes = await this.GetOfferedCSharpFixesAsync(testCode).ConfigureAwait(false);
484+
Assert.Empty(offeredFixes);
485+
}
486+
487+
/// <summary>
488+
/// Verifies that a constructor with an invalid summary tag from included documentation will produce a diagnostic and offer no codefix.
489+
/// </summary>
490+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
491+
[Fact]
492+
public async Task TestConstructorWithInvalidSummaryInIncludedDocsAsync()
493+
{
494+
var testCode = @"
495+
public class TestClass
496+
{
497+
/// <include file='InvalidSummary.xml' path='/TestClass/TestClass/*'/>
498+
public TestClass() { }
499+
}
500+
";
501+
502+
var expected = this.CSharpDiagnostic().WithLocation(4, 9);
503+
504+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
505+
var offeredFixes = await this.GetOfferedCSharpFixesAsync(testCode).ConfigureAwait(false);
506+
Assert.Empty(offeredFixes);
507+
}
508+
509+
/// <summary>
510+
/// Verifies that a constructor with an invalid class reference in the summary tag from included documentation will produce a diagnostic and offer no codefix.
511+
/// </summary>
512+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
513+
[Fact]
514+
public async Task TestConstructorWithInvalidReferenceInIncludedDocsAsync()
515+
{
516+
var testCode = @"
517+
public class TestClass
518+
{
519+
/// <include file='InvalidReference.xml' path='/TestClass/TestClass/*'/>
520+
public TestClass() { }
521+
}
522+
523+
public class WrongClass { }
524+
";
525+
526+
var expected = this.CSharpDiagnostic().WithLocation(4, 9);
527+
528+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
529+
var offeredFixes = await this.GetOfferedCSharpFixesAsync(testCode).ConfigureAwait(false);
530+
Assert.Empty(offeredFixes);
531+
}
532+
533+
protected override Project ApplyCompilationOptions(Project project)
534+
{
535+
var resolver = new TestXmlReferenceResolver();
536+
537+
string contentValidSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
538+
<TestClass>
539+
<TestClass>
540+
<summary>Initializes a new instance of the <see cref=""TestClass""/> class.</summary>
541+
</TestClass>
542+
</TestClass>
543+
";
544+
resolver.XmlReferences.Add("ValidSummary.xml", contentValidSummary);
545+
546+
string contentMissingSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
547+
<TestClass>
548+
<TestClass>
549+
</TestClass>
550+
</TestClass>
551+
";
552+
resolver.XmlReferences.Add("MissingSummary.xml", contentMissingSummary);
553+
554+
string contentEmptySummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
555+
<TestClass>
556+
<TestClass>
557+
<summary></summary>
558+
</TestClass>
559+
</TestClass>
560+
";
561+
resolver.XmlReferences.Add("EmptySummary.xml", contentEmptySummary);
562+
563+
string contentInvalidSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
564+
<TestClass>
565+
<TestClass>
566+
<summary>Creates the <see cref=""TestClass""/> class.</summary>
567+
</TestClass>
568+
</TestClass>
569+
";
570+
resolver.XmlReferences.Add("InvalidSummary.xml", contentInvalidSummary);
571+
572+
string contentInvalidReference = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
573+
<TestClass>
574+
<TestClass>
575+
<summary>Initializes a new instance of the <see cref=""WrongClass""/> class.</summary>
576+
</TestClass>
577+
</TestClass>
578+
";
579+
resolver.XmlReferences.Add("InvalidReference.xml", contentInvalidReference);
580+
581+
project = base.ApplyCompilationOptions(project);
582+
project = project.WithCompilationOptions(project.CompilationOptions.WithXmlReferenceResolver(resolver));
583+
return project;
584+
}
585+
427586
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
428587
{
429588
yield return new SA1642ConstructorSummaryDocumentationMustBeginWithStandardText();

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

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
66
using System.Collections.Generic;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using Microsoft.CodeAnalysis;
910
using Microsoft.CodeAnalysis.CodeFixes;
1011
using Microsoft.CodeAnalysis.Diagnostics;
1112
using StyleCop.Analyzers.DocumentationRules;
13+
using StyleCop.Analyzers.Test.Helpers;
1214
using TestHelper;
1315
using Xunit;
1416
using static StyleCop.Analyzers.DocumentationRules.SA1643DestructorSummaryDocumentationMustBeginWithStandardText;
@@ -70,6 +72,130 @@ public async Task TestDestructorMissingDocumentationGenericAsync()
7072
await this.TestDestructorMissingDocumentationImplAsync(DestructorStandardText[0], DestructorStandardText[1], true).ConfigureAwait(false);
7173
}
7274

75+
/// <summary>
76+
/// Verifies that a destructor with the correct summary text from included documentation will not produce any diagnostics.
77+
/// </summary>
78+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
79+
[Fact]
80+
public async Task TestDestructorWithValidSummaryInIncludedDocsAsync()
81+
{
82+
var testCode = @"
83+
public class TestClass
84+
{
85+
/// <include file='ValidSummary.xml' path='/TestClass/Destructor/*'/>
86+
~TestClass() { }
87+
}
88+
";
89+
90+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
91+
}
92+
93+
/// <summary>
94+
/// Verifies that a destructor with the missing summary tag from included documentation will not produce any diagnostics.
95+
/// </summary>
96+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
97+
[Fact]
98+
public async Task TestDestructorWithMissingSummaryInIncludedDocsAsync()
99+
{
100+
var testCode = @"
101+
public class TestClass
102+
{
103+
/// <include file='MissingSummary.xml' path='/TestClass/Destructor/*'/>
104+
~TestClass() { }
105+
}
106+
";
107+
108+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
109+
}
110+
111+
/// <summary>
112+
/// Verifies that a destructor with an empty summary tag from included documentation will produce a diagnostic and offer no codefix.
113+
/// </summary>
114+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
115+
[Fact]
116+
public async Task TestDestructorWithEmptySummaryInIncludedDocsAsync()
117+
{
118+
var testCode = @"
119+
public class TestClass
120+
{
121+
/// <include file='EmptySummary.xml' path='/TestClass/Destructor/*'/>
122+
~TestClass() { }
123+
}
124+
";
125+
126+
var expected = this.CSharpDiagnostic().WithLocation(4, 9);
127+
128+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
129+
var offeredFixes = await this.GetOfferedCSharpFixesAsync(testCode).ConfigureAwait(false);
130+
Assert.Empty(offeredFixes);
131+
}
132+
133+
/// <summary>
134+
/// Verifies that a destructor with an invalid summary tag from included documentation will produce a diagnostic and offer no codefix.
135+
/// </summary>
136+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
137+
[Fact]
138+
public async Task TestDestructorWithInvalidSummaryInIncludedDocsAsync()
139+
{
140+
var testCode = @"
141+
public class TestClass
142+
{
143+
/// <include file='InvalidSummary.xml' path='/TestClass/Destructor/*'/>
144+
~TestClass() { }
145+
}
146+
";
147+
148+
var expected = this.CSharpDiagnostic().WithLocation(4, 9);
149+
150+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
151+
var offeredFixes = await this.GetOfferedCSharpFixesAsync(testCode).ConfigureAwait(false);
152+
Assert.Empty(offeredFixes);
153+
}
154+
155+
protected override Project ApplyCompilationOptions(Project project)
156+
{
157+
var resolver = new TestXmlReferenceResolver();
158+
159+
string contentValidSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
160+
<TestClass>
161+
<Destructor>
162+
<summary>Finalizes an instance of the <see cref=""TestClass""/> class.</summary>
163+
</Destructor>
164+
</TestClass>
165+
";
166+
resolver.XmlReferences.Add("ValidSummary.xml", contentValidSummary);
167+
168+
string contentMissingSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
169+
<TestClass>
170+
<Destructor>
171+
</Destructor>
172+
</TestClass>
173+
";
174+
resolver.XmlReferences.Add("MissingSummary.xml", contentMissingSummary);
175+
176+
string contentEmptySummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
177+
<TestClass>
178+
<Destructor>
179+
<summary></summary>
180+
</Destructor>
181+
</TestClass>
182+
";
183+
resolver.XmlReferences.Add("EmptySummary.xml", contentEmptySummary);
184+
185+
string contentInvalidSummary = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
186+
<TestClass>
187+
<Destructor>
188+
<summary>Creates the <see cref=""TestClass""/> class.</summary>
189+
</Destructor>
190+
</TestClass>
191+
";
192+
resolver.XmlReferences.Add("InvalidSummary.xml", contentInvalidSummary);
193+
194+
project = base.ApplyCompilationOptions(project);
195+
project = project.WithCompilationOptions(project.CompilationOptions.WithXmlReferenceResolver(resolver));
196+
return project;
197+
}
198+
73199
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
74200
{
75201
yield return new SA1643DestructorSummaryDocumentationMustBeginWithStandardText();

0 commit comments

Comments
 (0)