From d0cc84bc89a7ce71b667573d0f1e13dd3d7aa91b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:26:53 +0000 Subject: [PATCH 1/6] Initial plan From 22778ffd0ac8bcdc34a308394755fafad8fa28ac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:34:06 +0000 Subject: [PATCH 2/6] feat: add multiline xml comment analyzer Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com> --- README.md | 1 + docs/README.md | 1 + docs/Rules/MA0211.md | 51 +++++++++ .../UseMultiLineXmlCommentSyntaxFixer.cs | 93 ++++++++++++++++ .../configuration/all-errors.editorconfig | 3 + .../all-suggestions.editorconfig | 3 + .../configuration/all-warnings.editorconfig | 3 + .../configuration/default.editorconfig | 3 + .../configuration/none.editorconfig | 3 + src/Meziantou.Analyzer/RuleIdentifiers.cs | 1 + .../UseMultiLineXmlCommentSyntaxAnalyzer.cs | 95 ++++++++++++++++ ...lCommentSyntaxWhenPossibleAnalyzerTests.cs | 102 ++++++++++++++++++ 12 files changed, 359 insertions(+) create mode 100644 docs/Rules/MA0211.md create mode 100644 src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs create mode 100644 src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs diff --git a/README.md b/README.md index 561a1c6a0..9d1812b30 100755 --- a/README.md +++ b/README.md @@ -229,6 +229,7 @@ If you are already using other analyzers, you can check [which rules are duplica |[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| |[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| |[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line XML comment syntax|ℹ️|❌|✔️| diff --git a/docs/README.md b/docs/README.md index 19b0c1dc2..4285b3bbe 100755 --- a/docs/README.md +++ b/docs/README.md @@ -209,6 +209,7 @@ |[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| |[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| |[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line XML comment syntax|ℹ️|❌|✔️| |Id|Suppressed rule|Justification| |--|---------------|-------------| diff --git a/docs/Rules/MA0211.md b/docs/Rules/MA0211.md new file mode 100644 index 000000000..f1fa88611 --- /dev/null +++ b/docs/Rules/MA0211.md @@ -0,0 +1,51 @@ +# MA0211 - Use multi-line XML comment syntax + +Sources: [UseMultiLineXmlCommentSyntaxAnalyzer.cs](https://github.com/meziantou/Meziantou.Analyzer/blob/main/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs), [UseMultiLineXmlCommentSyntaxFixer.cs](https://github.com/meziantou/Meziantou.Analyzer/blob/main/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs) + + +This rule reports XML documentation comments written on a single line when they can be expanded to the standard multi-line XML comment form. + +````csharp +/// Description +public class Sample { } + +// Should be +/// +/// Description +/// +public class Sample { } +```` + +## When to use multi-line format + +Use this rule when you want XML documentation comments to consistently use the multi-line form, even when the content fits on a single line. + +## When NOT to use multi-line format + +The analyzer will NOT suggest converting when: + +- The XML element already spans multiple lines +- The element contains multiple lines of source content +- The element contains CDATA sections +- The element contains nested XML elements (like ``, ``, etc.) + +## Examples + +````csharp +// Non-compliant: Single-line summary +/// Returns the sum of two numbers +public int Add(int a, int b) => a + b; + +// Compliant: Multi-line summary +/// +/// Returns the sum of two numbers +/// +public int Add(int a, int b) => a + b; + +// Compliant: Multiple lines of source content +/// +/// Returns the sum of two numbers. +/// This method handles integer overflow. +/// +public int Add(int a, int b) => a + b; +```` diff --git a/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs new file mode 100644 index 000000000..254b86856 --- /dev/null +++ b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs @@ -0,0 +1,93 @@ +using System.Collections.Immutable; +using System.Composition; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace Meziantou.Analyzer.Rules; + +[ExportCodeFixProvider(LanguageNames.CSharp), Shared] +public sealed class UseMultiLineXmlCommentSyntaxFixer : CodeFixProvider +{ + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(RuleIdentifiers.UseMultiLineXmlCommentSyntax); + + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + var nodeToFix = root?.FindNode(context.Span, getInnermostNodeForTie: true, findInsideTrivia: true); + if (nodeToFix is not XmlElementSyntax elementSyntax) + return; + + var sourceText = await context.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); + if (!TryCreateReplacementText(sourceText, elementSyntax, out var replacementText)) + return; + + var title = "Use multi-line XML comment syntax"; + var codeAction = CodeAction.Create( + title, + cancellationToken => FixAsync(context.Document, elementSyntax.Span, replacementText, cancellationToken), + equivalenceKey: title); + + context.RegisterCodeFix(codeAction, context.Diagnostics); + } + + private static bool TryCreateReplacementText(SourceText sourceText, XmlElementSyntax elementSyntax, out string replacementText) + { + replacementText = string.Empty; + + var lineSpan = elementSyntax.GetLocation().GetLineSpan(); + if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line) + return false; + + var line = sourceText.Lines.GetLineFromPosition(elementSyntax.SpanStart); + var commentPrefix = sourceText.ToString(TextSpan.FromBounds(line.Start, elementSyntax.SpanStart)); + var lineBreak = sourceText.ToString(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)); + if (lineBreak.Length == 0) + { + lineBreak = "\n"; + } + + var contentText = new StringBuilder(); + foreach (var content in elementSyntax.Content) + { + if (content is not XmlTextSyntax textSyntax) + continue; + + foreach (var token in textSyntax.TextTokens) + { + if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken)) + continue; + + var text = token.Text.Trim(); + if (string.IsNullOrWhiteSpace(text)) + continue; + + if (contentText.Length > 0) + { + contentText.Append(' '); + } + + contentText.Append(text); + } + } + + var startTagText = elementSyntax.StartTag.ToString(); + var endTagText = elementSyntax.EndTag.ToString(); + replacementText = contentText.Length == 0 + ? startTagText + lineBreak + commentPrefix + endTagText + : startTagText + lineBreak + commentPrefix + contentText + lineBreak + commentPrefix + endTagText; + return true; + } + + private static async Task FixAsync(Document document, TextSpan span, string replacementText, CancellationToken cancellationToken) + { + var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + return document.WithText(sourceText.Replace(span, replacementText)); + } +} diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig index 7da19b8a6..5e7d17634 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig @@ -625,3 +625,6 @@ dotnet_diagnostic.MA0209.severity = error # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = error + +# MA0211: Use multi-line XML comment syntax +dotnet_diagnostic.MA0211.severity = error diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig index b181487d6..041107d15 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig @@ -625,3 +625,6 @@ dotnet_diagnostic.MA0209.severity = suggestion # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = suggestion + +# MA0211: Use multi-line XML comment syntax +dotnet_diagnostic.MA0211.severity = suggestion diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig index 2bab61064..d35e551ca 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig @@ -625,3 +625,6 @@ dotnet_diagnostic.MA0209.severity = warning # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = warning + +# MA0211: Use multi-line XML comment syntax +dotnet_diagnostic.MA0211.severity = warning diff --git a/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig index 271660244..988b09450 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig @@ -625,3 +625,6 @@ dotnet_diagnostic.MA0209.severity = none # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = none + +# MA0211: Use multi-line XML comment syntax +dotnet_diagnostic.MA0211.severity = none diff --git a/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig index 73e54dea9..8bf3a31c3 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig @@ -625,3 +625,6 @@ dotnet_diagnostic.MA0209.severity = none # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = none + +# MA0211: Use multi-line XML comment syntax +dotnet_diagnostic.MA0211.severity = none diff --git a/src/Meziantou.Analyzer/RuleIdentifiers.cs b/src/Meziantou.Analyzer/RuleIdentifiers.cs index 2f40da136..4aa3989a8 100755 --- a/src/Meziantou.Analyzer/RuleIdentifiers.cs +++ b/src/Meziantou.Analyzer/RuleIdentifiers.cs @@ -210,6 +210,7 @@ internal static class RuleIdentifiers public const string FixedAddressValueTypeAttribute_FieldTypeMustBeValueType = "MA0208"; public const string UseInKeywordForInParameter = "MA0209"; public const string UseInKeywordToSelectInOverload = "MA0210"; + public const string UseMultiLineXmlCommentSyntax = "MA0211"; public static string GetHelpUri(string identifier) { diff --git a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs new file mode 100644 index 000000000..f130d1bd1 --- /dev/null +++ b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs @@ -0,0 +1,95 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Meziantou.Analyzer.Rules; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class UseMultiLineXmlCommentSyntaxAnalyzer : DiagnosticAnalyzer +{ + private static readonly DiagnosticDescriptor Rule = new( + RuleIdentifiers.UseMultiLineXmlCommentSyntax, + title: "Use multi-line XML comment syntax", + messageFormat: "Use multi-line XML comment syntax", + RuleCategories.Style, + DiagnosticSeverity.Info, + isEnabledByDefault: false, + description: "", + helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseMultiLineXmlCommentSyntax)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType, SymbolKind.Method, SymbolKind.Field, SymbolKind.Event, SymbolKind.Property); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context) + { + var symbol = context.Symbol; + if (symbol.IsImplicitlyDeclared) + return; + + if (symbol is INamedTypeSymbol namedTypeSymbol && (namedTypeSymbol.IsImplicitClass || symbol.Name.Contains('$', StringComparison.Ordinal))) + return; + + foreach (var syntaxReference in symbol.DeclaringSyntaxReferences) + { + var syntax = syntaxReference.GetSyntax(context.CancellationToken); + if (!syntax.HasStructuredTrivia) + continue; + + foreach (var trivia in syntax.GetLeadingTrivia()) + { + var structure = trivia.GetStructure(); + if (structure is not DocumentationCommentTriviaSyntax documentation) + continue; + + foreach (var childNode in documentation.ChildNodes()) + { + if (childNode is not XmlElementSyntax elementSyntax) + continue; + + var startLine = elementSyntax.StartTag.GetLocation().GetLineSpan().StartLinePosition.Line; + var endLine = elementSyntax.EndTag.GetLocation().GetLineSpan().EndLinePosition.Line; + if (endLine != startLine) + continue; + + var hasCDataOrOtherElements = false; + var meaningfulTextTokenCount = 0; + foreach (var content in elementSyntax.Content) + { + if (content is XmlTextSyntax textSyntax) + { + foreach (var token in textSyntax.TextTokens) + { + if (token.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.XmlTextLiteralNewLineToken)) + continue; + + var text = token.Text.Trim(); + if (!string.IsNullOrWhiteSpace(text)) + { + meaningfulTextTokenCount++; + } + } + } + else if (content is XmlCDataSectionSyntax || content is XmlElementSyntax) + { + hasCDataOrOtherElements = true; + break; + } + } + + if (!hasCDataOrOtherElements && meaningfulTextTokenCount <= 1) + { + context.ReportDiagnostic(Diagnostic.Create(Rule, elementSyntax.GetLocation())); + } + } + } + } + } +} diff --git a/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs index 18ae4a3df..a5cc1f862 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs @@ -313,3 +313,105 @@ class Sample { } .ValidateAsync(); } } + +public sealed class UseMultiLineXmlCommentSyntaxAnalyzerTests +{ + private static ProjectBuilder CreateProjectBuilder() + { + return new ProjectBuilder() + .WithAnalyzer() + .WithCodeFixProvider() + .WithTargetFramework(TargetFramework.NetLatest); + } + + [Fact] + public async Task SummarySingleLine_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// {|MA0211:description|} + class Sample { } + """) + .ShouldFixCodeWith(""" + /// + /// description + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task ParamSingleLine_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + class Sample + { + /// {|MA0211:The value|} + public void Method(int value) { } + } + """) + .ShouldFixCodeWith(""" + class Sample + { + /// + /// The value + /// + public void Method(int value) { } + } + """) + .ValidateAsync(); + } + + [Fact] + public async Task EmptyContent_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// {|MA0211:|} + class Sample { } + """) + .ShouldFixCodeWith(""" + /// + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task MultiLineDescription_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + /// description + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task InnerXmlElements_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// This has code inside + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task CDataSection_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + class Sample { } + """) + .ValidateAsync(); + } +} From b536d3c33e666fd516858b4aa5571f879a04926b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:39:22 +0000 Subject: [PATCH 3/6] chore: polish multiline xml comment analyzer Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com> --- .../Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs index f130d1bd1..c968d26d2 100644 --- a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs @@ -15,7 +15,7 @@ public sealed class UseMultiLineXmlCommentSyntaxAnalyzer : DiagnosticAnalyzer RuleCategories.Style, DiagnosticSeverity.Info, isEnabledByDefault: false, - description: "", + description: "Enforce multi-line XML documentation comment syntax for consistency.", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseMultiLineXmlCommentSyntax)); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); @@ -34,7 +34,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) if (symbol.IsImplicitlyDeclared) return; - if (symbol is INamedTypeSymbol namedTypeSymbol && (namedTypeSymbol.IsImplicitClass || symbol.Name.Contains('$', StringComparison.Ordinal))) + if (IsCompilerGeneratedType(symbol)) return; foreach (var syntaxReference in symbol.DeclaringSyntaxReferences) @@ -92,4 +92,9 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) } } } + + private static bool IsCompilerGeneratedType(ISymbol symbol) + { + return symbol is INamedTypeSymbol namedTypeSymbol && (namedTypeSymbol.IsImplicitClass || symbol.Name.Contains('$', StringComparison.Ordinal)); + } } From d70bbeb694b15811b9e0e6ecbea7c90b1dcb6ce9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:46:17 +0000 Subject: [PATCH 4/6] test: separate multiline xml comment analyzer tests Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com> --- .../UseMultiLineXmlCommentSyntaxFixer.cs | 3 - .../UseMultiLineXmlCommentSyntaxAnalyzer.cs | 3 +- ...lCommentSyntaxWhenPossibleAnalyzerTests.cs | 102 ----------------- ...eMultiLineXmlCommentSyntaxAnalyzerTests.cs | 107 ++++++++++++++++++ 4 files changed, 109 insertions(+), 106 deletions(-) create mode 100644 tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs diff --git a/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs index 254b86856..497102345 100644 --- a/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs +++ b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs @@ -61,9 +61,6 @@ private static bool TryCreateReplacementText(SourceText sourceText, XmlElementSy foreach (var token in textSyntax.TextTokens) { - if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken)) - continue; - var text = token.Text.Trim(); if (string.IsNullOrWhiteSpace(text)) continue; diff --git a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs index c968d26d2..a4bc2410e 100644 --- a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -67,7 +68,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) { foreach (var token in textSyntax.TextTokens) { - if (token.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.XmlTextLiteralNewLineToken)) + if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken)) continue; var text = token.Text.Trim(); diff --git a/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs index a5cc1f862..18ae4a3df 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzerTests.cs @@ -313,105 +313,3 @@ class Sample { } .ValidateAsync(); } } - -public sealed class UseMultiLineXmlCommentSyntaxAnalyzerTests -{ - private static ProjectBuilder CreateProjectBuilder() - { - return new ProjectBuilder() - .WithAnalyzer() - .WithCodeFixProvider() - .WithTargetFramework(TargetFramework.NetLatest); - } - - [Fact] - public async Task SummarySingleLine_ShouldReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - /// {|MA0211:description|} - class Sample { } - """) - .ShouldFixCodeWith(""" - /// - /// description - /// - class Sample { } - """) - .ValidateAsync(); - } - - [Fact] - public async Task ParamSingleLine_ShouldReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - class Sample - { - /// {|MA0211:The value|} - public void Method(int value) { } - } - """) - .ShouldFixCodeWith(""" - class Sample - { - /// - /// The value - /// - public void Method(int value) { } - } - """) - .ValidateAsync(); - } - - [Fact] - public async Task EmptyContent_ShouldReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - /// {|MA0211:|} - class Sample { } - """) - .ShouldFixCodeWith(""" - /// - /// - class Sample { } - """) - .ValidateAsync(); - } - - [Fact] - public async Task MultiLineDescription_ShouldNotReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - /// - /// description - /// - class Sample { } - """) - .ValidateAsync(); - } - - [Fact] - public async Task InnerXmlElements_ShouldNotReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - /// This has code inside - class Sample { } - """) - .ValidateAsync(); - } - - [Fact] - public async Task CDataSection_ShouldNotReportDiagnostic() - { - await CreateProjectBuilder() - .WithSourceCode(""" - /// - class Sample { } - """) - .ValidateAsync(); - } -} diff --git a/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs new file mode 100644 index 000000000..1dfdcf41a --- /dev/null +++ b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs @@ -0,0 +1,107 @@ +using Meziantou.Analyzer.Rules; +using Meziantou.Analyzer.Test.Helpers; +using TestHelper; + +namespace Meziantou.Analyzer.Test.Rules; + +public sealed class UseMultiLineXmlCommentSyntaxAnalyzerTests +{ + private static ProjectBuilder CreateProjectBuilder() + { + return new ProjectBuilder() + .WithAnalyzer() + .WithCodeFixProvider() + .WithTargetFramework(TargetFramework.NetLatest); + } + + [Fact] + public async Task SummarySingleLine_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// {|MA0211:description|} + class Sample { } + """) + .ShouldFixCodeWith(""" + /// + /// description + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task ParamSingleLine_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + class Sample + { + /// {|MA0211:The value|} + public void Method(int value) { } + } + """) + .ShouldFixCodeWith(""" + class Sample + { + /// + /// The value + /// + public void Method(int value) { } + } + """) + .ValidateAsync(); + } + + [Fact] + public async Task EmptyContent_ShouldReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// {|MA0211:|} + class Sample { } + """) + .ShouldFixCodeWith(""" + /// + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task MultiLineDescription_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + /// description + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task InnerXmlElements_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// This has code inside + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task CDataSection_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + class Sample { } + """) + .ValidateAsync(); + } +} From ef91285fc524d1e3332446b7e23b7cce6ff24e0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Jul 2026 00:19:01 +0000 Subject: [PATCH 5/6] fix: narrow MA0211 to summary comments Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com> --- README.md | 2 +- docs/README.md | 2 +- docs/Rules/MA0211.md | 24 +++---- .../UseMultiLineXmlCommentSyntaxFixer.cs | 34 +++------- .../configuration/all-errors.editorconfig | 2 +- .../all-suggestions.editorconfig | 2 +- .../configuration/all-warnings.editorconfig | 2 +- .../configuration/default.editorconfig | 2 +- .../configuration/none.editorconfig | 2 +- .../UseMultiLineXmlCommentSyntaxAnalyzer.cs | 39 ++--------- ...eMultiLineXmlCommentSyntaxAnalyzerTests.cs | 68 ++++++++++++------- 11 files changed, 79 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index 9d1812b30..6bba5ab63 100755 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ If you are already using other analyzers, you can check [which rules are duplica |[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| |[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| |[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| -|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line XML comment syntax|ℹ️|❌|✔️| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️| diff --git a/docs/README.md b/docs/README.md index 4285b3bbe..d56e1e526 100755 --- a/docs/README.md +++ b/docs/README.md @@ -209,7 +209,7 @@ |[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| |[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| |[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| -|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line XML comment syntax|ℹ️|❌|✔️| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️| |Id|Suppressed rule|Justification| |--|---------------|-------------| diff --git a/docs/Rules/MA0211.md b/docs/Rules/MA0211.md index f1fa88611..3c42a8f9b 100644 --- a/docs/Rules/MA0211.md +++ b/docs/Rules/MA0211.md @@ -1,9 +1,9 @@ -# MA0211 - Use multi-line XML comment syntax +# MA0211 - Use multi-line syntax for XML summary comments Sources: [UseMultiLineXmlCommentSyntaxAnalyzer.cs](https://github.com/meziantou/Meziantou.Analyzer/blob/main/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs), [UseMultiLineXmlCommentSyntaxFixer.cs](https://github.com/meziantou/Meziantou.Analyzer/blob/main/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs) -This rule reports XML documentation comments written on a single line when they can be expanded to the standard multi-line XML comment form. +This rule reports single-line `` XML documentation comments when they contain non-empty content and can be expanded to the standard multi-line XML comment form. ````csharp /// Description @@ -18,16 +18,15 @@ public class Sample { } ## When to use multi-line format -Use this rule when you want XML documentation comments to consistently use the multi-line form, even when the content fits on a single line. +Use this rule when you want `` XML documentation comments to consistently use the multi-line form, even when the content fits on a single line. ## When NOT to use multi-line format The analyzer will NOT suggest converting when: -- The XML element already spans multiple lines -- The element contains multiple lines of source content -- The element contains CDATA sections -- The element contains nested XML elements (like ``, ``, etc.) +- The `` element already spans multiple lines +- The `` element is empty or contains only whitespace +- The XML documentation element is not a `` element ## Examples @@ -42,10 +41,11 @@ public int Add(int a, int b) => a + b; /// public int Add(int a, int b) => a + b; -// Compliant: Multiple lines of source content -/// -/// Returns the sum of two numbers. -/// This method handles integer overflow. -/// +// Compliant: Empty summary +/// public int Add(int a, int b) => a + b; + +// Compliant: Other XML documentation elements are ignored +/// The value +public void SetValue(int value) { } ```` diff --git a/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs index 497102345..f996a7bf8 100644 --- a/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs +++ b/src/Meziantou.Analyzer.CodeFixers/Rules/UseMultiLineXmlCommentSyntaxFixer.cs @@ -1,10 +1,8 @@ using System.Collections.Immutable; using System.Composition; -using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -24,11 +22,14 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) if (nodeToFix is not XmlElementSyntax elementSyntax) return; + if (!string.Equals(elementSyntax.StartTag.Name.LocalName.ValueText, "summary", StringComparison.Ordinal)) + return; + var sourceText = await context.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); if (!TryCreateReplacementText(sourceText, elementSyntax, out var replacementText)) return; - var title = "Use multi-line XML comment syntax"; + var title = "Use multi-line syntax for XML summary comments"; var codeAction = CodeAction.Create( title, cancellationToken => FixAsync(context.Document, elementSyntax.Span, replacementText, cancellationToken), @@ -53,32 +54,13 @@ private static bool TryCreateReplacementText(SourceText sourceText, XmlElementSy lineBreak = "\n"; } - var contentText = new StringBuilder(); - foreach (var content in elementSyntax.Content) - { - if (content is not XmlTextSyntax textSyntax) - continue; - - foreach (var token in textSyntax.TextTokens) - { - var text = token.Text.Trim(); - if (string.IsNullOrWhiteSpace(text)) - continue; - - if (contentText.Length > 0) - { - contentText.Append(' '); - } - - contentText.Append(text); - } - } + var contentText = string.Concat(elementSyntax.Content.Select(static content => content.ToFullString())).Trim(); + if (contentText.Length == 0) + return false; var startTagText = elementSyntax.StartTag.ToString(); var endTagText = elementSyntax.EndTag.ToString(); - replacementText = contentText.Length == 0 - ? startTagText + lineBreak + commentPrefix + endTagText - : startTagText + lineBreak + commentPrefix + contentText + lineBreak + commentPrefix + endTagText; + replacementText = startTagText + lineBreak + commentPrefix + contentText + lineBreak + commentPrefix + endTagText; return true; } diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig index 5e7d17634..586ac82c9 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-errors.editorconfig @@ -626,5 +626,5 @@ dotnet_diagnostic.MA0209.severity = error # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = error -# MA0211: Use multi-line XML comment syntax +# MA0211: Use multi-line syntax for XML summary comments dotnet_diagnostic.MA0211.severity = error diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig index 041107d15..e79c43817 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-suggestions.editorconfig @@ -626,5 +626,5 @@ dotnet_diagnostic.MA0209.severity = suggestion # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = suggestion -# MA0211: Use multi-line XML comment syntax +# MA0211: Use multi-line syntax for XML summary comments dotnet_diagnostic.MA0211.severity = suggestion diff --git a/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig index d35e551ca..4b1f0d82e 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/all-warnings.editorconfig @@ -626,5 +626,5 @@ dotnet_diagnostic.MA0209.severity = warning # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = warning -# MA0211: Use multi-line XML comment syntax +# MA0211: Use multi-line syntax for XML summary comments dotnet_diagnostic.MA0211.severity = warning diff --git a/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig index 988b09450..deda0322e 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/default.editorconfig @@ -626,5 +626,5 @@ dotnet_diagnostic.MA0209.severity = none # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = none -# MA0211: Use multi-line XML comment syntax +# MA0211: Use multi-line syntax for XML summary comments dotnet_diagnostic.MA0211.severity = none diff --git a/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig b/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig index 8bf3a31c3..b711d0e13 100644 --- a/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig +++ b/src/Meziantou.Analyzer.Pack/configuration/none.editorconfig @@ -626,5 +626,5 @@ dotnet_diagnostic.MA0209.severity = none # MA0210: Use in keyword to call the in overload dotnet_diagnostic.MA0210.severity = none -# MA0211: Use multi-line XML comment syntax +# MA0211: Use multi-line syntax for XML summary comments dotnet_diagnostic.MA0211.severity = none diff --git a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs index a4bc2410e..706eedc45 100644 --- a/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseMultiLineXmlCommentSyntaxAnalyzer.cs @@ -1,6 +1,5 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -11,12 +10,12 @@ public sealed class UseMultiLineXmlCommentSyntaxAnalyzer : DiagnosticAnalyzer { private static readonly DiagnosticDescriptor Rule = new( RuleIdentifiers.UseMultiLineXmlCommentSyntax, - title: "Use multi-line XML comment syntax", - messageFormat: "Use multi-line XML comment syntax", + title: "Use multi-line syntax for XML summary comments", + messageFormat: "Use multi-line syntax for XML summary comments", RuleCategories.Style, DiagnosticSeverity.Info, isEnabledByDefault: false, - description: "Enforce multi-line XML documentation comment syntax for consistency.", + description: "Enforce multi-line XML documentation comment syntax for elements.", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseMultiLineXmlCommentSyntax)); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); @@ -55,40 +54,16 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) if (childNode is not XmlElementSyntax elementSyntax) continue; + if (!string.Equals(elementSyntax.StartTag.Name.LocalName.ValueText, "summary", StringComparison.Ordinal)) + continue; + var startLine = elementSyntax.StartTag.GetLocation().GetLineSpan().StartLinePosition.Line; var endLine = elementSyntax.EndTag.GetLocation().GetLineSpan().EndLinePosition.Line; if (endLine != startLine) continue; - var hasCDataOrOtherElements = false; - var meaningfulTextTokenCount = 0; - foreach (var content in elementSyntax.Content) - { - if (content is XmlTextSyntax textSyntax) - { - foreach (var token in textSyntax.TextTokens) - { - if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken)) - continue; - - var text = token.Text.Trim(); - if (!string.IsNullOrWhiteSpace(text)) - { - meaningfulTextTokenCount++; - } - } - } - else if (content is XmlCDataSectionSyntax || content is XmlElementSyntax) - { - hasCDataOrOtherElements = true; - break; - } - } - - if (!hasCDataOrOtherElements && meaningfulTextTokenCount <= 1) - { + if (!string.IsNullOrWhiteSpace(string.Concat(elementSyntax.Content.Select(static content => content.ToFullString())))) context.ReportDiagnostic(Diagnostic.Create(Rule, elementSyntax.GetLocation())); - } } } } diff --git a/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs index 1dfdcf41a..dd299a2e8 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs @@ -32,38 +32,33 @@ class Sample { } } [Fact] - public async Task ParamSingleLine_ShouldReportDiagnostic() + public async Task SingleLineSummaryWithNestedElement_ShouldReportDiagnostic() { await CreateProjectBuilder() .WithSourceCode(""" - class Sample - { - /// {|MA0211:The value|} - public void Method(int value) { } - } + /// {|MA0211:This has code inside|} + class Sample { } """) .ShouldFixCodeWith(""" - class Sample - { - /// - /// The value - /// - public void Method(int value) { } - } + /// + /// This has code inside + /// + class Sample { } """) .ValidateAsync(); } [Fact] - public async Task EmptyContent_ShouldReportDiagnostic() + public async Task SingleLineSummaryWithCData_ShouldReportDiagnostic() { await CreateProjectBuilder() .WithSourceCode(""" - /// {|MA0211:|} + /// {|MA0211:|} class Sample { } """) .ShouldFixCodeWith(""" /// + /// /// class Sample { } """) @@ -71,35 +66,62 @@ class Sample { } } [Fact] - public async Task MultiLineDescription_ShouldNotReportDiagnostic() + public async Task EmptyContent_ShouldNotReportDiagnostic() { await CreateProjectBuilder() .WithSourceCode(""" - /// - /// description - /// + /// class Sample { } """) .ValidateAsync(); } [Fact] - public async Task InnerXmlElements_ShouldNotReportDiagnostic() + public async Task ParamSingleLine_ShouldNotReportDiagnostic() { await CreateProjectBuilder() .WithSourceCode(""" - /// This has code inside + class Sample + { + /// The value + public void Method(int value) { } + } + """) + .ValidateAsync(); + } + + [Fact] + public async Task SummaryContainingOnlyWhitespace_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// class Sample { } """) .ValidateAsync(); } [Fact] - public async Task CDataSection_ShouldNotReportDiagnostic() + public async Task MultiLineDescription_ShouldNotReportDiagnostic() { await CreateProjectBuilder() .WithSourceCode(""" - /// + /// + /// description + /// + class Sample { } + """) + .ValidateAsync(); + } + + [Fact] + public async Task MultiLineSummaryWithNestedElement_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + /// This has code inside + /// class Sample { } """) .ValidateAsync(); From feaad1a6d6a2ba28c4a2de53af2e82d8174d4aeb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Jul 2026 00:22:18 +0000 Subject: [PATCH 6/6] test: cover multiline cdata summary Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com> --- .../UseMultiLineXmlCommentSyntaxAnalyzerTests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs index dd299a2e8..d5ca108bf 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/UseMultiLineXmlCommentSyntaxAnalyzerTests.cs @@ -126,4 +126,17 @@ class Sample { } """) .ValidateAsync(); } + + [Fact] + public async Task MultiLineSummaryWithCData_ShouldNotReportDiagnostic() + { + await CreateProjectBuilder() + .WithSourceCode(""" + /// + /// + /// + class Sample { } + """) + .ValidateAsync(); + } }