From dc2162337fd7d2c6d54c828859bd599615acfcb7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 5 Aug 2025 20:50:55 +0000
Subject: [PATCH 01/15] Initial plan
From f5b0c53e68212dcbff138eca2e102887f8a98818 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 5 Aug 2025 21:03:08 +0000
Subject: [PATCH 02/15] Implement csharp_style_namespace_declarations
EditorConfig support
- Add CSharpCodeGenerationConfiguration class with namespace declaration style setting
- Modify DefineStepsCommand to read EditorConfig and generate file-scoped namespaces when configured
- Add csharp_style_namespace_declarations setting to .editorconfig
- Create unit tests for the new configuration class
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.editorconfig | 1 +
.../CSharpCodeGenerationConfiguration.cs | 18 ++++
.../Editor/Commands/DefineStepsCommand.cs | 36 +++++++-
.../CSharpCodeGenerationConfigurationTests.cs | 82 +++++++++++++++++++
4 files changed, 133 insertions(+), 4 deletions(-)
create mode 100644 Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
create mode 100644 Tests/Reqnroll.VisualStudio.Tests/Configuration/CSharpCodeGenerationConfigurationTests.cs
diff --git a/.editorconfig b/.editorconfig
index c785b717..64d0c0c2 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -20,6 +20,7 @@ tab_width=2
csharp_new_line_before_members_in_object_initializers=false
csharp_preferred_modifier_order=public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
csharp_space_after_cast=false
+csharp_style_namespace_declarations=file_scoped:warning
csharp_style_var_elsewhere=true:hint
csharp_style_var_for_built_in_types=true:hint
csharp_style_var_when_type_is_apparent=true:hint
diff --git a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
new file mode 100644
index 00000000..ef6f7e3c
--- /dev/null
+++ b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
@@ -0,0 +1,18 @@
+namespace Reqnroll.VisualStudio.Configuration;
+
+public class CSharpCodeGenerationConfiguration
+{
+ ///
+ /// Specifies the namespace declaration style for generated C# code.
+ /// Uses file-scoped namespaces when set to "file_scoped", otherwise uses block-scoped namespaces.
+ ///
+ [EditorConfigSetting("csharp_style_namespace_declarations")]
+ public string NamespaceDeclarationStyle { get; set; } = "block_scoped";
+
+ ///
+ /// Determines if file-scoped namespaces should be used based on the EditorConfig setting.
+ ///
+ public bool UseFileScopedNamespaces =>
+ NamespaceDeclarationStyle != null &&
+ NamespaceDeclarationStyle.StartsWith("file_scoped", StringComparison.OrdinalIgnoreCase);
+}
\ No newline at end of file
diff --git a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
index 507d804f..b8c7bc0f 100644
--- a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
+++ b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
@@ -4,13 +4,17 @@ namespace Reqnroll.VisualStudio.Editor.Commands;
[Export(typeof(IDeveroomFeatureEditorCommand))]
public class DefineStepsCommand : DeveroomEditorCommandBase, IDeveroomFeatureEditorCommand
{
+ private readonly IEditorConfigOptionsProvider _editorConfigOptionsProvider;
+
[ImportingConstructor]
public DefineStepsCommand(
IIdeScope ideScope,
IBufferTagAggregatorFactoryService aggregatorFactory,
- IDeveroomTaggerProvider taggerProvider)
+ IDeveroomTaggerProvider taggerProvider,
+ IEditorConfigOptionsProvider editorConfigOptionsProvider)
: base(ideScope, aggregatorFactory, taggerProvider)
{
+ _editorConfigOptionsProvider = editorConfigOptionsProvider;
}
public override DeveroomEditorCommandTargetKey[] Targets => new[]
@@ -101,7 +105,7 @@ public override bool PreExec(IWpfTextView textView, DeveroomEditorCommandTargetK
switch (viewModel.Result)
{
case CreateStepDefinitionsDialogResult.Create:
- SaveAsStepDefinitionClass(projectScope, combinedSnippet, viewModel.ClassName, indent, newLine);
+ SaveAsStepDefinitionClass(projectScope, combinedSnippet, viewModel.ClassName, indent, newLine, textView);
break;
case CreateStepDefinitionsDialogResult.CopyToClipboard:
Logger.LogVerbose($"Copy to clipboard: {combinedSnippet}");
@@ -114,7 +118,7 @@ public override bool PreExec(IWpfTextView textView, DeveroomEditorCommandTargetK
}
private void SaveAsStepDefinitionClass(IProjectScope projectScope, string combinedSnippet, string className,
- string indent, string newLine)
+ string indent, string newLine, IWpfTextView textView)
{
string targetFolder = projectScope.ProjectFolder;
var projectSettings = projectScope.GetProjectSettings();
@@ -130,7 +134,30 @@ private void SaveAsStepDefinitionClass(IProjectScope projectScope, string combin
var isSpecFlow = projectTraits.HasFlag(ReqnrollProjectTraits.LegacySpecFlow) || projectTraits.HasFlag(ReqnrollProjectTraits.SpecFlowCompatibility);
var libraryNameSpace = isSpecFlow ? "SpecFlow" : "Reqnroll";
- var template = "using System;" + newLine +
+ // Get C# code generation configuration from EditorConfig
+ var csharpConfig = new CSharpCodeGenerationConfiguration();
+ var editorConfigOptions = _editorConfigOptionsProvider.GetEditorConfigOptions(textView);
+ editorConfigOptions.UpdateFromEditorConfig(csharpConfig);
+
+ string template;
+ if (csharpConfig.UseFileScopedNamespaces)
+ {
+ // Generate file-scoped namespace
+ template = "using System;" + newLine +
+ $"using {libraryNameSpace};" + newLine +
+ newLine +
+ $"namespace {fileNamespace};" + newLine +
+ newLine +
+ "[Binding]" + newLine +
+ $"public class {className}" + newLine +
+ "{" + newLine +
+ combinedSnippet +
+ "}" + newLine;
+ }
+ else
+ {
+ // Generate block-scoped namespace (existing behavior)
+ template = "using System;" + newLine +
$"using {libraryNameSpace};" + newLine +
newLine +
$"namespace {fileNamespace}" + newLine +
@@ -141,6 +168,7 @@ private void SaveAsStepDefinitionClass(IProjectScope projectScope, string combin
combinedSnippet +
$"{indent}}}" + newLine +
"}" + newLine;
+ }
var targetFile = FileDetails
.FromPath(targetFolder, className + ".cs")
diff --git a/Tests/Reqnroll.VisualStudio.Tests/Configuration/CSharpCodeGenerationConfigurationTests.cs b/Tests/Reqnroll.VisualStudio.Tests/Configuration/CSharpCodeGenerationConfigurationTests.cs
new file mode 100644
index 00000000..b4994d98
--- /dev/null
+++ b/Tests/Reqnroll.VisualStudio.Tests/Configuration/CSharpCodeGenerationConfigurationTests.cs
@@ -0,0 +1,82 @@
+using Reqnroll.VisualStudio.Configuration;
+using Xunit;
+
+namespace Reqnroll.VisualStudio.Tests.Configuration;
+
+public class CSharpCodeGenerationConfigurationTests
+{
+ [Fact]
+ public void UseFileScopedNamespaces_WhenFileScopedSet_ReturnsTrue()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration
+ {
+ NamespaceDeclarationStyle = "file_scoped"
+ };
+
+ // Act & Assert
+ Assert.True(config.UseFileScopedNamespaces);
+ }
+
+ [Fact]
+ public void UseFileScopedNamespaces_WhenFileScopedWithSeveritySet_ReturnsTrue()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration
+ {
+ NamespaceDeclarationStyle = "file_scoped:warning"
+ };
+
+ // Act & Assert
+ Assert.True(config.UseFileScopedNamespaces);
+ }
+
+ [Fact]
+ public void UseFileScopedNamespaces_WhenBlockScopedSet_ReturnsFalse()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration
+ {
+ NamespaceDeclarationStyle = "block_scoped"
+ };
+
+ // Act & Assert
+ Assert.False(config.UseFileScopedNamespaces);
+ }
+
+ [Fact]
+ public void UseFileScopedNamespaces_WhenDefaultValue_ReturnsFalse()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration();
+
+ // Act & Assert
+ Assert.False(config.UseFileScopedNamespaces);
+ }
+
+ [Fact]
+ public void UseFileScopedNamespaces_WhenNullValue_ReturnsFalse()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration
+ {
+ NamespaceDeclarationStyle = null
+ };
+
+ // Act & Assert
+ Assert.False(config.UseFileScopedNamespaces);
+ }
+
+ [Fact]
+ public void UseFileScopedNamespaces_WhenUnknownValue_ReturnsFalse()
+ {
+ // Arrange
+ var config = new CSharpCodeGenerationConfiguration
+ {
+ NamespaceDeclarationStyle = "unknown_style"
+ };
+
+ // Act & Assert
+ Assert.False(config.UseFileScopedNamespaces);
+ }
+}
\ No newline at end of file
From 61bebbcb2d2e9171568e5014ec4b66bf9dd5f865 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 5 Aug 2025 21:17:06 +0000
Subject: [PATCH 03/15] Fix missing using statements in EditorConfig
implementation
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.../Configuration/CSharpCodeGenerationConfiguration.cs | 2 ++
Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
index ef6f7e3c..4935d5be 100644
--- a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
+++ b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
@@ -1,3 +1,5 @@
+using Reqnroll.VisualStudio.Editor.Services.EditorConfig;
+
namespace Reqnroll.VisualStudio.Configuration;
public class CSharpCodeGenerationConfiguration
diff --git a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
index b8c7bc0f..d77ecd3c 100644
--- a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
+++ b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
@@ -1,4 +1,6 @@
#nullable disable
+using Reqnroll.VisualStudio.Configuration;
+
namespace Reqnroll.VisualStudio.Editor.Commands;
[Export(typeof(IDeveroomFeatureEditorCommand))]
From 1004f481665c25ccee573b52813434e61f0ae18d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 6 Aug 2025 11:00:09 +0000
Subject: [PATCH 04/15] Remove redundant using statements to fix compilation
issues
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.../Configuration/CSharpCodeGenerationConfiguration.cs | 2 --
Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs | 1 -
2 files changed, 3 deletions(-)
diff --git a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
index 4935d5be..ef6f7e3c 100644
--- a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
+++ b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
@@ -1,5 +1,3 @@
-using Reqnroll.VisualStudio.Editor.Services.EditorConfig;
-
namespace Reqnroll.VisualStudio.Configuration;
public class CSharpCodeGenerationConfiguration
diff --git a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
index d77ecd3c..fefac866 100644
--- a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
+++ b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
@@ -1,5 +1,4 @@
#nullable disable
-using Reqnroll.VisualStudio.Configuration;
namespace Reqnroll.VisualStudio.Editor.Commands;
From ee827843d2d8e9a3df393fd7ea131868e8f96d59 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 7 Aug 2025 15:45:37 +0000
Subject: [PATCH 05/15] Minor formatting adjustment to trigger CI build
verification
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.../Configuration/CSharpCodeGenerationConfiguration.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
index ef6f7e3c..8398b493 100644
--- a/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
+++ b/Reqnroll.VisualStudio/Configuration/CSharpCodeGenerationConfiguration.cs
@@ -12,7 +12,7 @@ public class CSharpCodeGenerationConfiguration
///
/// Determines if file-scoped namespaces should be used based on the EditorConfig setting.
///
- public bool UseFileScopedNamespaces =>
- NamespaceDeclarationStyle != null &&
+ public bool UseFileScopedNamespaces =>
+ NamespaceDeclarationStyle != null &&
NamespaceDeclarationStyle.StartsWith("file_scoped", StringComparison.OrdinalIgnoreCase);
}
\ No newline at end of file
From ad7fb00254fba34df3763608b8077a5f83513bf8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 10 Aug 2025 21:10:14 +0000
Subject: [PATCH 06/15] Fix DefineStepsCommand constructor calls in tests to
include missing EditorConfigOptionsProvider parameter
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.../StepDefinitions/ProjectSystemSteps.cs | 3 ++-
.../Editor/Commands/DefineStepsCommandTests.cs | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/Tests/Reqnroll.VisualStudio.Specs/StepDefinitions/ProjectSystemSteps.cs b/Tests/Reqnroll.VisualStudio.Specs/StepDefinitions/ProjectSystemSteps.cs
index 17bc2a84..219e3d08 100644
--- a/Tests/Reqnroll.VisualStudio.Specs/StepDefinitions/ProjectSystemSteps.cs
+++ b/Tests/Reqnroll.VisualStudio.Specs/StepDefinitions/ProjectSystemSteps.cs
@@ -478,7 +478,8 @@ private void PerformCommand(string commandName, string parameter = null,
}
case "Define Steps":
{
- _invokedCommand = new DefineStepsCommand(_ideScope, aggregatorFactoryService, taggerProvider);
+ _invokedCommand = new DefineStepsCommand(_ideScope, aggregatorFactoryService, taggerProvider,
+ new StubEditorConfigOptionsProvider());
_invokedCommand.PreExec(_wpfTextView, _invokedCommand.Targets.First());
return;
}
diff --git a/Tests/Reqnroll.VisualStudio.Tests/Editor/Commands/DefineStepsCommandTests.cs b/Tests/Reqnroll.VisualStudio.Tests/Editor/Commands/DefineStepsCommandTests.cs
index fba8031c..95d2ec84 100644
--- a/Tests/Reqnroll.VisualStudio.Tests/Editor/Commands/DefineStepsCommandTests.cs
+++ b/Tests/Reqnroll.VisualStudio.Tests/Editor/Commands/DefineStepsCommandTests.cs
@@ -6,7 +6,8 @@ public class DefineStepsCommandTests : CommandTestBase
{
public DefineStepsCommandTests(ITestOutputHelper testOutputHelper)
: base(testOutputHelper, (ps, tp) =>
- new DefineStepsCommand(ps.IdeScope, new StubBufferTagAggregatorFactoryService(tp), tp),
+ new DefineStepsCommand(ps.IdeScope, new StubBufferTagAggregatorFactoryService(tp), tp,
+ new StubEditorConfigOptionsProvider()),
"ShowProblem: User Notification: ")
{
}
From 655c69b0939cc2e46c54ce5c6618b3dffd0c434f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 10 Aug 2025 21:48:07 +0000
Subject: [PATCH 07/15] Deduplicate template generation code in
DefineStepsCommand
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
.../Editor/Commands/DefineStepsCommand.cs | 42 +++++++++----------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
index fefac866..ded1d452 100644
--- a/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
+++ b/Reqnroll.VisualStudio/Editor/Commands/DefineStepsCommand.cs
@@ -140,35 +140,33 @@ private void SaveAsStepDefinitionClass(IProjectScope projectScope, string combin
var editorConfigOptions = _editorConfigOptionsProvider.GetEditorConfigOptions(textView);
editorConfigOptions.UpdateFromEditorConfig(csharpConfig);
- string template;
+ // Build template with common structure
+ var template = "using System;" + newLine +
+ $"using {libraryNameSpace};" + newLine +
+ newLine;
+
if (csharpConfig.UseFileScopedNamespaces)
{
// Generate file-scoped namespace
- template = "using System;" + newLine +
- $"using {libraryNameSpace};" + newLine +
- newLine +
- $"namespace {fileNamespace};" + newLine +
- newLine +
- "[Binding]" + newLine +
- $"public class {className}" + newLine +
- "{" + newLine +
- combinedSnippet +
- "}" + newLine;
+ template += $"namespace {fileNamespace};" + newLine +
+ newLine +
+ "[Binding]" + newLine +
+ $"public class {className}" + newLine +
+ "{" + newLine +
+ combinedSnippet +
+ "}" + newLine;
}
else
{
// Generate block-scoped namespace (existing behavior)
- template = "using System;" + newLine +
- $"using {libraryNameSpace};" + newLine +
- newLine +
- $"namespace {fileNamespace}" + newLine +
- "{" + newLine +
- $"{indent}[Binding]" + newLine +
- $"{indent}public class {className}" + newLine +
- $"{indent}{{" + newLine +
- combinedSnippet +
- $"{indent}}}" + newLine +
- "}" + newLine;
+ template += $"namespace {fileNamespace}" + newLine +
+ "{" + newLine +
+ $"{indent}[Binding]" + newLine +
+ $"{indent}public class {className}" + newLine +
+ $"{indent}{{" + newLine +
+ combinedSnippet +
+ $"{indent}}}" + newLine +
+ "}" + newLine;
}
var targetFile = FileDetails
From 3ac3a40b0af5199e15173d0b70c66087bbcd1d59 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 10 Aug 2025 22:35:13 +0000
Subject: [PATCH 08/15] Fix BufferGraphFactoryService GuardedOperations
parameter passing in test infrastructure
Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
---
Tests/Reqnroll.VisualStudio.VsxStubs/VsxStubObjects.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Tests/Reqnroll.VisualStudio.VsxStubs/VsxStubObjects.cs b/Tests/Reqnroll.VisualStudio.VsxStubs/VsxStubObjects.cs
index 916eb61d..e2871d9f 100644
--- a/Tests/Reqnroll.VisualStudio.VsxStubs/VsxStubObjects.cs
+++ b/Tests/Reqnroll.VisualStudio.VsxStubs/VsxStubObjects.cs
@@ -79,8 +79,8 @@ public static void Initialize()
CreateObject