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();
+ }
}