Skip to content

Commit 34dce82

Browse files
committed
Updated SA1620
1 parent 867e192 commit 34dce82

2 files changed

Lines changed: 418 additions & 57 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1620UnitTests.cs

Lines changed: 322 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
77
using System.Threading;
88
using System.Threading.Tasks;
99
using Analyzers.DocumentationRules;
10+
using Helpers;
11+
using Microsoft.CodeAnalysis;
1012
using Microsoft.CodeAnalysis.Diagnostics;
1113
using TestHelper;
1214
using Xunit;
@@ -16,6 +18,9 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
1618
/// </summary>
1719
public class SA1620UnitTests : DiagnosticVerifier
1820
{
21+
private const string OrderFormatString = "The type parameter documentation for '{0}' should be at position {1}.";
22+
private const string ParameterDoesNotExistFormatString = "The type parameter '{0}' does not exist.";
23+
1924
public static IEnumerable<object[]> Members
2025
{
2126
get
@@ -156,7 +161,7 @@ public class ClassName
156161
}";
157162

158163
var diagnostic = this.CSharpDiagnostic()
159-
.WithMessageFormat("The type parameter documentation for '{0}' should be at position {1}.");
164+
.WithMessageFormat(OrderFormatString);
160165

161166
var expected = new[]
162167
{
@@ -180,7 +185,7 @@ public async Task TestTypesWithAllDocumentationWrongOrderAsync(string p)
180185
public ##";
181186

182187
var diagnostic = this.CSharpDiagnostic()
183-
.WithMessageFormat("The type parameter documentation for '{0}' should be at position {1}.");
188+
.WithMessageFormat(OrderFormatString);
184189

185190
var expected = new[]
186191
{
@@ -293,7 +298,7 @@ public class ClassName
293298
}";
294299

295300
var diagnostic = this.CSharpDiagnostic()
296-
.WithMessageFormat("The type parameter '{0}' does not exist.");
301+
.WithMessageFormat(ParameterDoesNotExistFormatString);
297302

298303
var expected = diagnostic.WithLocation(12, 26).WithArguments("Tc");
299304

@@ -314,7 +319,7 @@ public async Task TestTypesWithInvalidDocumentationAsync(string p)
314319
public ##";
315320

316321
var diagnostic = this.CSharpDiagnostic()
317-
.WithMessageFormat("The type parameter '{0}' does not exist.");
322+
.WithMessageFormat(ParameterDoesNotExistFormatString);
318323

319324
var expected = diagnostic.WithLocation(7, 22).WithArguments("Tc");
320325

@@ -341,7 +346,7 @@ public class ClassName
341346
}";
342347

343348
var diagnostic = this.CSharpDiagnostic()
344-
.WithMessageFormat("The type parameter documentation for '{0}' should be at position {1}.");
349+
.WithMessageFormat(OrderFormatString);
345350

346351
var expected = diagnostic.WithLocation(12, 26).WithArguments("Tb", 2);
347352

@@ -362,13 +367,324 @@ public async Task TestTypesWithTooManyDocumentationAsync(string p)
362367
public ##";
363368

364369
var diagnostic = this.CSharpDiagnostic()
365-
.WithMessageFormat("The type parameter documentation for '{0}' should be at position {1}.");
370+
.WithMessageFormat(OrderFormatString);
366371

367372
var expected = diagnostic.WithLocation(7, 22).WithArguments("Tb", 2);
368373

369374
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
370375
}
371376

377+
/// <summary>
378+
/// Verifies that a type with included documentation will produce no diagnostics.
379+
/// </summary>
380+
/// <param name="p">The type declaration text that will be used.</param>
381+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
382+
[Theory]
383+
[MemberData(nameof(Types))]
384+
public async Task TestTypeWithIncludedDocumentationAsync(string p)
385+
{
386+
var testCode = @"
387+
/// <include file='TypeWithTypeparamsDoc.xml' path='/Foo/*'/>
388+
public ##
389+
";
390+
391+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
392+
}
393+
394+
/// <summary>
395+
/// Verifies that a type without typeparam documentation in the included documentation will produce no diagnostics.
396+
/// </summary>
397+
/// <param name="p">The type declaration text that will be used.</param>
398+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
399+
[Theory]
400+
[MemberData(nameof(Types))]
401+
public async Task TestTypeWithoutTypeparamInIncludedDocumentationAsync(string p)
402+
{
403+
var testCode = @"
404+
/// <include file='TypeWithoutTypeparamsDoc.xml' path='/Foo/*'/>
405+
public ##
406+
";
407+
408+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
409+
}
410+
411+
/// <summary>
412+
/// Verifies that a type with inheritdoc in the included documentation will produce no diagnostics.
413+
/// </summary>
414+
/// <param name="p">The type declaration text that will be used.</param>
415+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
416+
[Theory]
417+
[MemberData(nameof(Types))]
418+
public async Task TestTypeWithInheritDocInIncludedDocumentationAsync(string p)
419+
{
420+
var testCode = @"
421+
/// <include file='TypeWithInheritdoc.xml' path='/Foo/*'/>
422+
public ##
423+
";
424+
425+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
426+
}
427+
428+
/// <summary>
429+
/// Verifies that a type with wrongly ordered typeparam documentation in the included documentation will produce the expected diagnostics.
430+
/// </summary>
431+
/// <param name="p">The type declaration text that will be used.</param>
432+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
433+
[Theory]
434+
[MemberData(nameof(Types))]
435+
public async Task TestTypeWithWronglyOrderedTypeParamInIncludedDocumentationAsync(string p)
436+
{
437+
var testCode = @"
438+
/// <include file='TypeWithWronglyOrderedTypeparamsDoc.xml' path='/Foo/*'/>
439+
public ##
440+
";
441+
DiagnosticResult[] expected =
442+
{
443+
this.CSharpDiagnostic().WithLocation(2, 5).WithMessageFormat(OrderFormatString).WithArguments("Tb", 2),
444+
this.CSharpDiagnostic().WithLocation(2, 5).WithMessageFormat(OrderFormatString).WithArguments("Ta", 1),
445+
};
446+
447+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
448+
}
449+
450+
/// <summary>
451+
/// Verifies that a type with a missing typeparam in the included documentation will produce the expected diagnostics.
452+
/// </summary>
453+
/// <param name="p">The type declaration text that will be used.</param>
454+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
455+
[Theory]
456+
[MemberData(nameof(Types))]
457+
public async Task TestTypeWithMissingTypeParamInIncludedDocumentationAsync(string p)
458+
{
459+
var testCode = @"
460+
/// <include file='TypeWithMissingTypeparamDoc.xml' path='/Foo/*'/>
461+
public ##
462+
";
463+
DiagnosticResult[] expected =
464+
{
465+
this.CSharpDiagnostic().WithLocation(2, 5).WithMessageFormat(OrderFormatString).WithArguments("Tb", 2),
466+
this.CSharpDiagnostic().WithLocation(2, 5).WithMessageFormat(ParameterDoesNotExistFormatString).WithArguments("Tc"),
467+
};
468+
469+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
470+
}
471+
472+
/// <summary>
473+
/// Verifies that a method with included documentation will produce no diagnostics.
474+
/// </summary>
475+
/// <param name="p">The method declaration text that will be used.</param>
476+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
477+
[Theory]
478+
[MemberData(nameof(Members))]
479+
public async Task TestMethodWithIncludedDocumentationAsync(string p)
480+
{
481+
var testCode = @"
482+
/// <summary>Test class</summary>
483+
public class TestClass
484+
{
485+
/// <include file='MethodWithTypeparamsDoc.xml' path='/TestClass/Foo/*'/>
486+
public ##
487+
}
488+
";
489+
490+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
491+
}
492+
493+
/// <summary>
494+
/// Verifies that a method without typeparam documentation in the included documentation will produce no diagnostics.
495+
/// </summary>
496+
/// <param name="p">The method declaration text that will be used.</param>
497+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
498+
[Theory]
499+
[MemberData(nameof(Members))]
500+
public async Task TestMethodWithoutTypeparamInIncludedDocumentationAsync(string p)
501+
{
502+
var testCode = @"
503+
/// <summary>Test class</summary>
504+
public class TestClass
505+
{
506+
/// <include file='MethodWithoutTypeparamsDoc.xml' path='/TestClass/Foo/*'/>
507+
public ##
508+
}
509+
";
510+
511+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
512+
}
513+
514+
/// <summary>
515+
/// Verifies that a method with inheritdoc in the included documentation will produce no diagnostics.
516+
/// </summary>
517+
/// <param name="p">The method declaration text that will be used.</param>
518+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
519+
[Theory]
520+
[MemberData(nameof(Members))]
521+
public async Task TestMethodWithInheritDocInIncludedDocumentationAsync(string p)
522+
{
523+
var testCode = @"
524+
/// <summary>Test class</summary>
525+
public class TestClass
526+
{
527+
/// <include file='MethodWithoutTypeparamsDoc.xml' path='/TestClass/Foo/*'/>
528+
public ##
529+
}
530+
";
531+
532+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
533+
}
534+
535+
/// <summary>
536+
/// Verifies that a method with wrongly ordered typeparam documentation in the included documentation will produce the expected diagnostics.
537+
/// </summary>
538+
/// <param name="p">The method declaration text that will be used.</param>
539+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
540+
[Theory]
541+
[MemberData(nameof(Members))]
542+
public async Task TestMethodWithWronglyOrderedTypeParamInIncludedDocumentationAsync(string p)
543+
{
544+
var testCode = @"
545+
/// <summary>Test class</summary>
546+
public class TestClass
547+
{
548+
/// <include file='MethodWithWronglyOrderedTypeparamsDoc.xml' path='/TestClass/Foo/*'/>
549+
public ##
550+
}
551+
";
552+
DiagnosticResult[] expected =
553+
{
554+
this.CSharpDiagnostic().WithLocation(5, 9).WithMessageFormat(OrderFormatString).WithArguments("Tb", 2),
555+
this.CSharpDiagnostic().WithLocation(5, 9).WithMessageFormat(OrderFormatString).WithArguments("Ta", 1),
556+
};
557+
558+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
559+
}
560+
561+
/// <summary>
562+
/// Verifies that a method with a missing typeparam in the included documentation will produce the expected diagnostics.
563+
/// </summary>
564+
/// <param name="p">The method declaration text that will be used.</param>
565+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
566+
[Theory]
567+
[MemberData(nameof(Members))]
568+
public async Task TestMethodWithMissingTypeParamInIncludedDocumentationAsync(string p)
569+
{
570+
var testCode = @"
571+
/// <summary>Test class</summary>
572+
public class TestClass
573+
{
574+
/// <include file='MethodWithMissingTypeparamDoc.xml' path='/TestClass/Foo/*'/>
575+
public ##
576+
}
577+
";
578+
DiagnosticResult[] expected =
579+
{
580+
this.CSharpDiagnostic().WithLocation(5, 9).WithMessageFormat(OrderFormatString).WithArguments("Tb", 2),
581+
this.CSharpDiagnostic().WithLocation(5, 9).WithMessageFormat(ParameterDoesNotExistFormatString).WithArguments("Tc"),
582+
};
583+
584+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
585+
}
586+
587+
protected override Project ApplyCompilationOptions(Project project)
588+
{
589+
var resolver = new TestXmlReferenceResolver();
590+
591+
string contentTypeWithTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
592+
<Foo>
593+
<summary>Test class</summary>
594+
<typeparam name=""Ta"">Param 1</typeparam>
595+
<typeparam name=""Tb"">Param 2</typeparam>
596+
</Foo>
597+
";
598+
resolver.XmlReferences.Add("TypeWithTypeparamsDoc.xml", contentTypeWithTypeparamDoc);
599+
600+
string contentTypeWithoutTypeparamsDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
601+
<Foo>
602+
<summary>Test class</summary>
603+
</Foo>
604+
";
605+
resolver.XmlReferences.Add("TypeWithoutTypeparamsDoc.xml", contentTypeWithoutTypeparamsDoc);
606+
607+
string contentTypeInheritdoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
608+
<Foo>
609+
<inheritdoc/>
610+
</Foo>
611+
";
612+
resolver.XmlReferences.Add("TypeWithInheritdoc.xml", contentTypeInheritdoc);
613+
614+
string contentTypeWithWronglyOrderedTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
615+
<Foo>
616+
<summary>Test class</summary>
617+
<typeparam name=""Tb"">Param 2</typeparam>
618+
<typeparam name=""Ta"">Param 1</typeparam>
619+
</Foo>
620+
";
621+
resolver.XmlReferences.Add("TypeWithWronglyOrderedTypeparamsDoc.xml", contentTypeWithWronglyOrderedTypeparamDoc);
622+
623+
string contentTypeWithMissingTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
624+
<Foo>
625+
<summary>Test class</summary>
626+
<typeparam name=""Tb"">Param 2</typeparam>
627+
<typeparam name=""Tc"">Param 3</typeparam>
628+
</Foo>
629+
";
630+
resolver.XmlReferences.Add("TypeWithMissingTypeparamDoc.xml", contentTypeWithMissingTypeparamDoc);
631+
632+
string contentMethodWithTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
633+
<TestClass>
634+
<Foo>
635+
<summary>Test class</summary>
636+
<typeparam name=""Ta"">Param 1</typeparam>
637+
<typeparam name=""Tb"">Param 2</typeparam>
638+
</Foo>
639+
</TestClass>
640+
";
641+
resolver.XmlReferences.Add("MethodWithTypeparamsDoc.xml", contentMethodWithTypeparamDoc);
642+
643+
string contentMethodWithoutTypeparamsDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
644+
<TestClass>
645+
<Foo>
646+
<summary>Test class</summary>
647+
</Foo>
648+
</TestClass>
649+
";
650+
resolver.XmlReferences.Add("MethodWithoutTypeparamsDoc.xml", contentMethodWithoutTypeparamsDoc);
651+
652+
string contentMethodInheritdoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
653+
<TestClass>
654+
<Foo>
655+
<inheritdoc/>
656+
</Foo>
657+
</TestClass>
658+
";
659+
resolver.XmlReferences.Add("MethodWithInheritdoc.xml", contentMethodInheritdoc);
660+
661+
string contentMethodWithWronglyOrderedTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
662+
<TestClass>
663+
<Foo>
664+
<summary>Test class</summary>
665+
<typeparam name=""Tb"">Param 2</typeparam>
666+
<typeparam name=""Ta"">Param 1</typeparam>
667+
</Foo>
668+
</TestClass>
669+
";
670+
resolver.XmlReferences.Add("MethodWithWronglyOrderedTypeparamsDoc.xml", contentMethodWithWronglyOrderedTypeparamDoc);
671+
672+
string contentMethodWithMissingTypeparamDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
673+
<TestClass>
674+
<Foo>
675+
<summary>Test class</summary>
676+
<typeparam name=""Tb"">Param 2</typeparam>
677+
<typeparam name=""Tc"">Param 3</typeparam>
678+
</Foo>
679+
</TestClass>
680+
";
681+
resolver.XmlReferences.Add("MethodWithMissingTypeparamDoc.xml", contentMethodWithMissingTypeparamDoc);
682+
683+
project = base.ApplyCompilationOptions(project);
684+
project = project.WithCompilationOptions(project.CompilationOptions.WithXmlReferenceResolver(resolver));
685+
return project;
686+
}
687+
372688
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
373689
{
374690
yield return new SA1620GenericTypeParameterDocumentationMustMatchTypeParameters();

0 commit comments

Comments
 (0)