From 2b7b012f695adb117cfa3d61363ac2f387638945 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:15:04 +0000 Subject: [PATCH 1/6] Initial plan From f7d215f8b7871914a382068b4fb0548fda2e1e0a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:59:37 +0000 Subject: [PATCH 2/6] Add CS1591 warning suppression to ComInterfaceGenerator and add test Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../ComInterfaceGenerator.cs | 2 +- .../Compiles.cs | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs index 26eae7fd73c406..e10a2ddd2f67dc 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs @@ -204,7 +204,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) using StringWriter source = new(); source.WriteLine("// "); - source.WriteLine("#pragma warning disable CS0612, CS0618, CS0649"); // Suppress warnings about [Obsolete] and "lack of assignment" in generated code. + source.WriteLine("#pragma warning disable CS0612, CS0618, CS0649, CS1591"); // Suppress warnings about [Obsolete], "lack of assignment", and missing XML documentation in generated code. // If the user has specified 'ManagedObjectWrapper', it means that the COM interface will never be used to marshal a native // object as an RCW (eg. the IDIC vtable will also not be generated, nor any additional supporting code). To reduce binary diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index 3f5a90d3c1a2c0..ee8b72ae648eb1 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -4,8 +4,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -369,5 +373,72 @@ public async Task ValidateComInterfaceSnippets(string id, string source) await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source); } + + [Fact] + public async Task ComInterfaceWithDocumentationDoesNotProduceCS1591() + { + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + namespace Test + { + /// + /// This is my interface. + /// + [GeneratedComInterface, Guid("27dd3a3d-4c16-485a-a123-7cd8f39c6ef2")] + public partial interface IMyInterface + { + /// + /// This does something. + /// + void DoSomething(); + } + + /// + /// This is my other interface. + /// + [GeneratedComInterface, Guid("1b681178-368a-4d13-8893-66b4673d2ff9")] + public partial interface MyOtherInterface : IMyInterface + { + /// + /// This does something else. + /// + void DoSomethingElse(); + } + } + """; + + var test = new VerifyCompilationTest(false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck | TestBehaviors.SkipGeneratedCodeCheck, + CompilationVerifier = compilation => + { + // Verify that no CS1591 warnings are produced in the generated code + var diagnostics = compilation.GetDiagnostics(); + var cs1591Diagnostics = diagnostics.Where(d => d.Id == "CS1591").ToList(); + + Assert.Empty(cs1591Diagnostics); + } + }; + + // Enable XML documentation warnings to ensure CS1591 would be raised if not suppressed + test.CompilerDiagnostics = CompilerDiagnostics.Warnings; + test.SolutionTransforms.Add((solution, projectId) => + { + var project = solution.GetProject(projectId); + if (project is null) return solution; + + var compilationOptions = project.CompilationOptions! + .WithSpecificDiagnosticOptions(new Dictionary + { + ["CS1591"] = ReportDiagnostic.Warn + }); + return solution.WithProjectCompilationOptions(projectId, compilationOptions); + }); + + await test.RunAsync(); + } } } From 219250c18304ac91b52dd0a31f8a204a3bd29a40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 19:57:46 +0000 Subject: [PATCH 3/6] Refactor CS1591 test to use CodeSnippets pattern as requested Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../CodeSnippets.cs | 32 +++++++++ .../Compiles.cs | 70 +------------------ 2 files changed, 33 insertions(+), 69 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 8b3f5652bbab6b..70b7219d98a291 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -636,6 +636,38 @@ partial interface IComInterface2 } """; + public string DocumentedComInterface => $$""" + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + namespace Test + { + /// + /// This is my interface. + /// + {{GeneratedComInterface()}} + public partial interface IMyInterface + { + /// + /// This does something. + /// + void DoSomething(); + } + + /// + /// This is my other interface. + /// + {{GeneratedComInterface()}} + public partial interface MyOtherInterface : IMyInterface + { + /// + /// This does something else. + /// + void DoSomethingElse(); + } + } + """; + public string InterfaceWithPropertiesAndEvents => $$""" using System; using System.Runtime.CompilerServices; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index ee8b72ae648eb1..3934adfd354c3e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -4,12 +4,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -345,6 +341,7 @@ public static IEnumerable ComInterfaceSnippetsToCompile() yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeTwoLevelShadows}; yield return new object[] { ID(), codeSnippets.DerivedWithParametersDeclaredInOtherNamespace }; yield return new object[] { ID(), codeSnippets.ComInterfaceParameters }; + yield return new object[] { ID(), codeSnippets.DocumentedComInterface }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref") }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref readonly") }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("in") }; @@ -374,71 +371,6 @@ public async Task ValidateComInterfaceSnippets(string id, string source) await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source); } - [Fact] - public async Task ComInterfaceWithDocumentationDoesNotProduceCS1591() - { - string source = """ - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.Marshalling; - - namespace Test - { - /// - /// This is my interface. - /// - [GeneratedComInterface, Guid("27dd3a3d-4c16-485a-a123-7cd8f39c6ef2")] - public partial interface IMyInterface - { - /// - /// This does something. - /// - void DoSomething(); - } - - /// - /// This is my other interface. - /// - [GeneratedComInterface, Guid("1b681178-368a-4d13-8893-66b4673d2ff9")] - public partial interface MyOtherInterface : IMyInterface - { - /// - /// This does something else. - /// - void DoSomethingElse(); - } - } - """; - - var test = new VerifyCompilationTest(false) - { - TestCode = source, - TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck | TestBehaviors.SkipGeneratedCodeCheck, - CompilationVerifier = compilation => - { - // Verify that no CS1591 warnings are produced in the generated code - var diagnostics = compilation.GetDiagnostics(); - var cs1591Diagnostics = diagnostics.Where(d => d.Id == "CS1591").ToList(); - - Assert.Empty(cs1591Diagnostics); - } - }; - - // Enable XML documentation warnings to ensure CS1591 would be raised if not suppressed - test.CompilerDiagnostics = CompilerDiagnostics.Warnings; - test.SolutionTransforms.Add((solution, projectId) => - { - var project = solution.GetProject(projectId); - if (project is null) return solution; - - var compilationOptions = project.CompilationOptions! - .WithSpecificDiagnosticOptions(new Dictionary - { - ["CS1591"] = ReportDiagnostic.Warn - }); - return solution.WithProjectCompilationOptions(projectId, compilationOptions); - }); - await test.RunAsync(); - } } } From 0d276b68918415075363c531ba964a56e82e4f0e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 25 Sep 2025 13:04:58 -0700 Subject: [PATCH 4/6] Update Compiles.cs --- .../tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index 3934adfd354c3e..05a2dcce2cd16d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -370,7 +370,5 @@ public async Task ValidateComInterfaceSnippets(string id, string source) await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source); } - - } } From 02a5dbefb82c08cd95f3b3d63ce8c209e82e258c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 00:16:44 +0000 Subject: [PATCH 5/6] Add proper test that validates CS1591 warning suppression Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- .../Compiles.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index 05a2dcce2cd16d..d88ad69371e888 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -4,8 +4,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -370,5 +373,71 @@ public async Task ValidateComInterfaceSnippets(string id, string source) await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source); } + + [Fact] + public async Task DocumentedComInterfaceDoesNotProduceCS1591Warnings() + { + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + namespace Test + { + /// + /// This is my interface. + /// + [GeneratedComInterface, Guid("27dd3a3d-4c16-485a-a123-7cd8f39c6ef2")] + public partial interface IMyInterface + { + /// + /// This does something. + /// + void DoSomething(); + } + + /// + /// This is my other interface. + /// + [GeneratedComInterface, Guid("1b681178-368a-4d13-8893-66b4673d2ff9")] + public partial interface MyOtherInterface : IMyInterface + { + /// + /// This does something else. + /// + void DoSomethingElse(); + } + } + """; + + var test = new VerifyCompilationTest(false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck | TestBehaviors.SkipGeneratedCodeCheck, + CompilationVerifier = compilation => + { + // Verify that no CS1591 warnings are produced in the generated code + var diagnostics = compilation.GetDiagnostics(); + var cs1591Diagnostics = diagnostics.Where(d => d.Id == "CS1591").ToList(); + + Assert.Empty(cs1591Diagnostics); + } + }; + + // Enable XML documentation warnings to ensure CS1591 would be raised if not suppressed + test.SolutionTransforms.Add((solution, projectId) => + { + var project = solution.GetProject(projectId); + if (project is null) return solution; + + var compilationOptions = project.CompilationOptions! + .WithSpecificDiagnosticOptions(new Dictionary + { + ["CS1591"] = ReportDiagnostic.Warn + }); + return solution.WithProjectCompilationOptions(projectId, compilationOptions); + }); + + await test.RunAsync(); + } } } From d8db2d5b29c8a6698d87475fa8f140f8de17f067 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Oct 2025 21:55:14 +0000 Subject: [PATCH 6/6] Add DocumentationMode.Diagnose and remove unused DocumentedComInterface snippet Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../CodeSnippets.cs | 32 ------------------- .../Compiles.cs | 11 ++++++- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 70b7219d98a291..8b3f5652bbab6b 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -636,38 +636,6 @@ partial interface IComInterface2 } """; - public string DocumentedComInterface => $$""" - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.Marshalling; - - namespace Test - { - /// - /// This is my interface. - /// - {{GeneratedComInterface()}} - public partial interface IMyInterface - { - /// - /// This does something. - /// - void DoSomething(); - } - - /// - /// This is my other interface. - /// - {{GeneratedComInterface()}} - public partial interface MyOtherInterface : IMyInterface - { - /// - /// This does something else. - /// - void DoSomethingElse(); - } - } - """; - public string InterfaceWithPropertiesAndEvents => $$""" using System; using System.Runtime.CompilerServices; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index d88ad69371e888..247bd7a84f56e0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop.UnitTests; using Xunit; @@ -344,7 +345,6 @@ public static IEnumerable ComInterfaceSnippetsToCompile() yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeTwoLevelShadows}; yield return new object[] { ID(), codeSnippets.DerivedWithParametersDeclaredInOtherNamespace }; yield return new object[] { ID(), codeSnippets.ComInterfaceParameters }; - yield return new object[] { ID(), codeSnippets.DocumentedComInterface }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref") }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref readonly") }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("in") }; @@ -429,6 +429,15 @@ public partial interface MyOtherInterface : IMyInterface var project = solution.GetProject(projectId); if (project is null) return solution; + // Set parse options to enable documentation mode which is required for CS1591 validation + var parseOptions = (CSharpParseOptions?)project.ParseOptions; + if (parseOptions is not null) + { + parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Diagnose); + solution = solution.WithProjectParseOptions(projectId, parseOptions); + project = solution.GetProject(projectId)!; + } + var compilationOptions = project.CompilationOptions! .WithSpecificDiagnosticOptions(new Dictionary {