Skip to content

Commit 48d6e70

Browse files
committed
Update SA1619 to suppress messages when documentation for an element is optional
Fixes #2453
1 parent 14644aa commit 48d6e70

2 files changed

Lines changed: 71 additions & 3 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1619UnitTests.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
66
using System.Collections.Generic;
77
using System.Threading;
88
using System.Threading.Tasks;
9-
using Analyzers.DocumentationRules;
109
using Microsoft.CodeAnalysis;
1110
using Microsoft.CodeAnalysis.Diagnostics;
11+
using StyleCop.Analyzers.DocumentationRules;
1212
using StyleCop.Analyzers.Test.Helpers;
1313
using TestHelper;
1414
using Xunit;
@@ -18,6 +18,8 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
1818
/// </summary>
1919
public class SA1619UnitTests : DiagnosticVerifier
2020
{
21+
private string currentTestSettings;
22+
2123
public static IEnumerable<object[]> Types
2224
{
2325
get
@@ -122,6 +124,32 @@ public async Task TestPartialTypesWithMissingDocumentationAsync(string p)
122124
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), expected, CancellationToken.None).ConfigureAwait(false);
123125
}
124126

127+
[Theory]
128+
[MemberData(nameof(Types))]
129+
[WorkItem(2453, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2453")]
130+
public async Task TestPartialTypesWithMissingButNotRequiredDocumentationAsync(string p)
131+
{
132+
var testCode = @"
133+
/// <summary>
134+
/// Foo
135+
/// </summary>
136+
public partial ##";
137+
138+
// This situation is allowed if 'documentExposedElements' and 'documentInterfaces' is false
139+
string interfaceSettingName = p.StartsWith("interface ") ? "documentInterfaces" : "ignoredProperty";
140+
this.currentTestSettings = $@"
141+
{{
142+
""settings"": {{
143+
""documentationRules"": {{
144+
""documentExposedElements"": false,
145+
""{interfaceSettingName}"": false
146+
}}
147+
}}
148+
}}
149+
";
150+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("##", p), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
151+
}
152+
125153
[Theory]
126154
[MemberData(nameof(Types))]
127155
public async Task TestNonPartialTypesWithMissingDocumentationAsync(string p)
@@ -200,6 +228,31 @@ public partial class TestClass<T>
200228
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
201229
}
202230

231+
[Fact]
232+
[WorkItem(2453, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2453")]
233+
public async Task TestGenericPartialTypeWithoutTypeparamInIncludedButNotRequiredDocumentationAsync()
234+
{
235+
var testCode = @"
236+
/// <include file='ClassWithoutTypeparamDoc.xml' path='/TestClass/*'/>
237+
public partial class TestClass<T>
238+
{
239+
}
240+
";
241+
242+
// The situation is allowed if 'documentExposedElements' false
243+
this.currentTestSettings = @"
244+
{
245+
""settings"": {
246+
""documentationRules"": {
247+
""documentExposedElements"": false
248+
}
249+
}
250+
}
251+
";
252+
253+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
254+
}
255+
203256
/// <summary>
204257
/// Verifies that a generic partial type with &lt;inheritdoc&gt; in included documentation will work.
205258
/// </summary>
@@ -254,6 +307,11 @@ protected override Project ApplyCompilationOptions(Project project)
254307
return project;
255308
}
256309

310+
protected override string GetSettings()
311+
{
312+
return this.currentTestSettings ?? base.GetSettings();
313+
}
314+
257315
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
258316
{
259317
yield return new SA1619GenericTypeParametersMustBeDocumentedPartialClass();

StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1619GenericTypeParametersMustBeDocumentedPartialClass.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace StyleCop.Analyzers.DocumentationRules
1212
using Microsoft.CodeAnalysis.CSharp.Syntax;
1313
using Microsoft.CodeAnalysis.Diagnostics;
1414
using StyleCop.Analyzers.Helpers;
15+
using StyleCop.Analyzers.Settings.ObjectModel;
1516

1617
/// <summary>
1718
/// A generic, partial C# element is missing documentation for one or more of its generic type parameters, and the
@@ -91,7 +92,7 @@ internal class SA1619GenericTypeParametersMustBeDocumentedPartialClass : Diagnos
9192
private static readonly DiagnosticDescriptor Descriptor =
9293
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.DocumentationRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
9394

94-
private static readonly Action<SyntaxNodeAnalysisContext> TypeDeclarationAction = HandleTypeDeclaration;
95+
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> TypeDeclarationAction = HandleTypeDeclaration;
9596

9697
/// <inheritdoc/>
9798
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -106,7 +107,7 @@ public override void Initialize(AnalysisContext context)
106107
context.RegisterSyntaxNodeAction(TypeDeclarationAction, SyntaxKinds.TypeDeclaration);
107108
}
108109

109-
private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context)
110+
private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
110111
{
111112
TypeDeclarationSyntax typeDeclaration = (TypeDeclarationSyntax)context.Node;
112113

@@ -129,6 +130,15 @@ private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context)
129130
return;
130131
}
131132

133+
Accessibility declaredAccessibility = typeDeclaration.GetDeclaredAccessibility(context.SemanticModel, context.CancellationToken);
134+
Accessibility effectiveAccessibility = typeDeclaration.GetEffectiveAccessibility(context.SemanticModel, context.CancellationToken);
135+
bool needsComment = SA1600ElementsMustBeDocumented.NeedsComment(settings.DocumentationRules, typeDeclaration.Kind(), typeDeclaration.Parent.Kind(), declaredAccessibility, effectiveAccessibility);
136+
if (!needsComment)
137+
{
138+
// Omitting documentation is allowed for this element.
139+
return;
140+
}
141+
132142
var includeElement = documentation.Content.GetFirstXmlElement(XmlCommentHelper.IncludeXmlTag);
133143
if (includeElement != null)
134144
{

0 commit comments

Comments
 (0)