diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1642UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1642UnitTests.cs index 4433b5044..d6d81d7db 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1642UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1642UnitTests.cs @@ -1061,6 +1061,36 @@ public ClassName() await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); } + [Fact] + [WorkItem(3575, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3575")] + public async Task TestConstructorSummaryWithParaTagsAsync() + { + var testCode = @" +using System; +/// +/// Does a thing. +/// +public class B +{ + /// + /// + /// Initializes a new instance of the class. + /// + /// + /// Some more info about B. + /// + /// + public B() + { + } +} +"; + + var expectedDiagnostics = DiagnosticResult.EmptyDiagnosticResults; + + await VerifyCSharpFixAsync(testCode, expectedDiagnostics, testCode, CancellationToken.None).ConfigureAwait(false); + } + private static async Task TestEmptyConstructorAsync(string typeKind, string modifiers) { var testCode = @"namespace FooNamespace diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/StandardTextDiagnosticBase.cs b/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/StandardTextDiagnosticBase.cs index 2b6c7263e..2af1351f2 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/StandardTextDiagnosticBase.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/StandardTextDiagnosticBase.cs @@ -122,6 +122,26 @@ protected static MatchResult HandleDeclaration(SyntaxNodeAnalysisContext context diagnosticLocation = summaryElement.GetLocation(); diagnosticProperties = ImmutableDictionary.Create(); + // Handle empty or whitespace-only summary content + var firstElementWithContent = XmlCommentHelper.TryGetFirstTextElementWithContent(summaryElement); + if (firstElementWithContent == null) + { + // Report the diagnostic for empty or whitespace-only summaries + if (diagnosticDescriptor != null) + { + context.ReportDiagnostic(Diagnostic.Create(diagnosticDescriptor, diagnosticLocation, diagnosticProperties)); + } + + return MatchResult.None; + } + + // Check if the summary content starts with a tag + if (firstElementWithContent != null && firstElementWithContent.Parent is XmlElementSyntax firstElement && firstElement.StartTag.Name.ToString() == "para") + { + // We found a correct standard text + return MatchResult.FoundMatch; + } + // Check if the summary content could be a correct standard text if (summaryElement.Content.Count >= 3) { diff --git a/documentation/SA1642.md b/documentation/SA1642.md index f64ea96b4..f12da3238 100644 --- a/documentation/SA1642.md +++ b/documentation/SA1642.md @@ -96,6 +96,23 @@ private Customer() } ``` +The `` tag can be used within the `` tag to structure the text. +For example: + +```csharp +/// +/// +/// Initializes a new instance of the class. +/// +/// +/// Additional information can be included in subsequent paragraphs. +/// +/// +public Customer() +{ +} +``` + ## How to fix violations To fix a violation of this rule, edit the summary text for the constructor as described above.