From 469422afef7ed0d86c9d77f781c99c5914984815 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:31:21 +0000 Subject: [PATCH 1/6] Initial plan From f32643ff2dcacbf18e44c057800874fd361385c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:38:04 +0000 Subject: [PATCH 2/6] Update README with new KeywordOptionConfigurator API examples Co-authored-by: fengb3 <45181245+fengb3@users.noreply.github.com> --- README.md | 104 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1031055..ce98aa9 100644 --- a/README.md +++ b/README.md @@ -39,18 +39,16 @@ var code = Create() .Using("System") .Namespace(ns => { ns.Name = "MyProject"; - ns.Class(cls => { - cls.Name = "Person"; - cls.AutoProperty(p => { - p.WithKeyword("public") - .WithType("string") - .WithName("Name"); - }); - cls.AutoProperty(p => { - p.WithKeyword("public") - .WithType("int") - .WithName("Age"); - }); + ns.Public.Class(cls => { + cls.WithName("Person"); + cls.Public.AutoProperty(p => p + .WithType("string") + .WithName("Name") + ); + cls.Public.AutoProperty(p => p + .WithType("int") + .WithName("Age") + ); }); }) .Build(); @@ -111,12 +109,10 @@ var code = Create() .Using("System") .Namespace(ns => { ns.Name = "MyApp"; - ns.Class(cls => { - cls.Name = "Calculator"; - cls.WithKeyword("public"); - cls.Method(method => { + ns.Public.Class(cls => { + cls.WithName("Calculator"); + cls.Public.Method(method => { method.WithName("Add") - .WithKeyword("public") .WithReturnType("int") .WithParameters("int a", "int b") .AppendLine("return a + b;"); @@ -148,6 +144,78 @@ namespace MyApp +### Using Keyword Configurator + +The new `KeywordOptionConfigurator` API provides a fluent way to specify access modifiers and other keywords: + +
+
+ +**API Calling**: +```csharp +using Fengb3.EasyCodeBuilder.Csharp; + +var @namespace = new NamespaceOption() + .WithName("MyNamespace") + .Public.Class(cls => { + cls.WithName("MyClass"); + }); + +var code = @namespace.Build(); +``` + +
+
+ +**Generated Code**: +```csharp +namespace MyNamespace +{ + public class MyClass + { + } +} +``` + +
+
+ +You can also use the keyword configurator with auto-properties: + +
+
+ +**API Calling**: +```csharp +using Fengb3.EasyCodeBuilder.Csharp; +using static Fengb3.EasyCodeBuilder.Csharp.Code; + +var @class = Create() + .Class(cls => cls + .WithName("MyClass") + .Public.AutoProperty(prop => prop + .WithName("MyProperty") + .WithType(typeof(int).FullName ?? "int") + ) + ); + +var classCode = @class.Build(); +``` + +
+
+ +**Generated Code**: +```csharp +class MyClass +{ + public System.Int32 MyProperty { get; set; } +} +``` + +
+
+ ### Using Constructors
@@ -317,6 +385,8 @@ EasyCodeBuilder v0.1.0 uses a configuration-based approach where you: The library provides fluent extension methods for common operations: - **`WithName()`**, **`WithKeyword()`**, **`WithType()`** - Configure basic properties +- **`Public`**, **`Private`**, **`Internal`**, **`Static`** - Keyword configurator properties for fluent keyword specification +- **`KeywordConfigurator`** - Access the keyword configurator for advanced chaining with `Parent` property - **`Using()`** - Add using statements - **`Namespace()`**, **`Class()`**, **`Method()`** - Add structural elements - **`AutoProperty()`**, **`Constructor()`** - Add members From 22cca36ef4e36a8d7c1be48f01bba2a43b3e3fe7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:40:43 +0000 Subject: [PATCH 3/6] Add verification tests for README examples Co-authored-by: fengb3 <45181245+fengb3@users.noreply.github.com> --- .../Csharp/ReadmeExamplesVerificationTests.cs | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs diff --git a/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs b/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs new file mode 100644 index 0000000..9d8b7b2 --- /dev/null +++ b/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs @@ -0,0 +1,151 @@ +using System; +using Fengb3.EasyCodeBuilder.Csharp; +using Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations; +using Xunit.Abstractions; + +namespace EasyCodeBuilder.Test.Csharp; + +/// +/// Tests to verify that the README examples work correctly +/// +public class ReadmeExamplesVerificationTests +{ + private readonly ITestOutputHelper _testOutputHelper; + public ReadmeExamplesVerificationTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [Fact] + public void TestBasicUsageExample() + { + // This verifies the "Basic Usage" example in README + var code = Code.Create() + .Using("System") + .Namespace(ns => { + ns.Name = "MyProject"; + ns.Public.Class(cls => { + cls.WithName("Person"); + cls.Public.AutoProperty(p => p + .WithType("string") + .WithName("Name") + ); + cls.Public.AutoProperty(p => p + .WithType("int") + .WithName("Age") + ); + }); + }) + .Build(); + + const string expected = + """ + using System; + + namespace MyProject + { + public class Person + { + public string Name { get; set; } + public int Age { get; set; } + } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } + + [Fact] + public void TestGenerateClassWithMethodsExample() + { + // This verifies the "Generate a Class with Methods" example in README + var code = Code.Create() + .Using("System") + .Namespace(ns => { + ns.Name = "MyApp"; + ns.Public.Class(cls => { + cls.WithName("Calculator"); + cls.Public.Method(method => { + method.WithName("Add") + .WithReturnType("int") + .WithParameters("int a", "int b") + .AppendLine("return a + b;"); + }); + }); + }) + .Build(); + + const string expected = + """ + using System; + + namespace MyApp + { + public class Calculator + { + public int Add(int a, int b) + { + return a + b; + } + } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } + + [Fact] + public void TestKeywordConfiguratorPublicClassExample() + { + // This verifies the first "Using Keyword Configurator" example in README + var @namespace = new NamespaceOption() + .WithName("MyNamespace") + .Public.Class(cls => { + cls.WithName("MyClass"); + }); + + var code = @namespace.Build(); + + const string expected = + """ + namespace MyNamespace + { + public class MyClass + { + } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } + + [Fact] + public void TestKeywordConfiguratorAutoPropertyExample() + { + // This verifies the second "Using Keyword Configurator" example in README + var @class = Code.Create() + .Class(cls => cls + .WithName("MyClass") + .Public.AutoProperty(prop => prop + .WithName("MyProperty") + .WithType(typeof(int).FullName ?? "int") + ) + ); + + var classCode = @class.Build(); + + const string expected = + """ + class MyClass + { + public System.Int32 MyProperty { get; set; } + } + """; + + Assert.Equal(expected.Trim(), classCode.Trim()); + _testOutputHelper.WriteLine(classCode); + } +} From 63d8b929adc9b6ab36518fad57ca77bee89f5ea1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:43:30 +0000 Subject: [PATCH 4/6] Add import note and fix using statements in README examples Co-authored-by: fengb3 <45181245+fengb3@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ce98aa9..43aa13b 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ namespace MyApp ### Using Keyword Configurator -The new `KeywordOptionConfigurator` API provides a fluent way to specify access modifiers and other keywords: +The new `KeywordOptionConfigurator` API provides a fluent way to specify access modifiers and other keywords. Note: You need to import `Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations` to use these extension methods.
@@ -154,6 +154,7 @@ The new `KeywordOptionConfigurator` API provides a fluent way to specify access **API Calling**: ```csharp using Fengb3.EasyCodeBuilder.Csharp; +using Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations; var @namespace = new NamespaceOption() .WithName("MyNamespace") From 3604733ff66037485a482ee1f489b69214e87958 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:54:51 +0000 Subject: [PATCH 5/6] Update all README examples to use KeywordOptionConfigurator API where applicable Co-authored-by: fengb3 <45181245+fengb3@users.noreply.github.com> --- .../Csharp/ReadmeExamplesVerificationTests.cs | 144 +++++++++++++++++ README.md | 150 +++++++++++------- 2 files changed, 241 insertions(+), 53 deletions(-) diff --git a/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs b/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs index 9d8b7b2..2b1f117 100644 --- a/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs +++ b/EasyCodeBuilder.Test/Csharp/ReadmeExamplesVerificationTests.cs @@ -148,4 +148,148 @@ class MyClass Assert.Equal(expected.Trim(), classCode.Trim()); _testOutputHelper.WriteLine(classCode); } + + [Fact] + public void TestUsingConstructorsExample() + { + // This verifies the "Using Constructors" example in README + var classOption = new TypeOption() + .WithTypeKind(TypeOption.Type.Class) + .WithName("Person") + .WithKeyword("public"); + + classOption.Constructor(ctor => { + ctor.WithKeyword("public") + .WithParameter("string name") + .WithParameter("int age") + .AppendLine("Name = name;") + .AppendLine("Age = age;"); + }); + + classOption.Public.AutoProperty(p => p + .WithType("string") + .WithName("Name")); + + classOption.Public.AutoProperty(p => p + .WithType("int") + .WithName("Age")); + + var code = classOption.Build(); + + const string expected = + """ + public class Person + { + public Person(string name, int age) + { + Name = name; + Age = age; + } + public string Name { get; set; } + public int Age { get; set; } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } + + [Fact] + public void TestControlStructuresForLoopExample() + { + // This verifies the "Control Structures - For Loop" example in README + var classOption = new TypeOption() + .WithTypeKind(TypeOption.Type.Class) + .WithName("NumberPrinter"); + + classOption.Public.Method(method => { + method.WithName("PrintNumbers") + .WithReturnType("void") + .For(@for => { + @for.WithInitializer("int i = 0") + .WithCondition("i < 10") + .WithIterator("i++") + .AppendLine("Console.WriteLine(i);"); + }); + }); + + var code = classOption.Build(); + + const string expected = + """ + class NumberPrinter + { + public void PrintNumbers() + { + for (int i = 0; i < 10; i++) + { + Console.WriteLine(i); + } + } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } + + [Fact] + public void TestControlStructuresSwitchStatementExample() + { + // This verifies the "Control Structures - Switch Statement" example in README + var classOption = new TypeOption() + .WithTypeKind(TypeOption.Type.Class) + .WithName("DayHelper"); + + classOption.Public.Method(method => { + method.WithName("GetDayName") + .WithReturnType("string") + .WithParameters("int day"); + + method.Switch(@switch => { + @switch.Expression = "day"; + @switch.Case(@case => { + @case.Value = "1"; + @case.AppendLine("return \"Monday\";"); + }); + @switch.Case(@case => { + @case.Value = "2"; + @case.AppendLine("return \"Tuesday\";"); + }); + @switch.Default(@default => + @default.AppendLine("return \"Unknown\";") + ); + }); + }); + + var code = classOption.Build(); + + const string expected = + """ + class DayHelper + { + public string GetDayName(int day) + { + switch (day) + { + case 1: + { + return "Monday"; + } + case 2: + { + return "Tuesday"; + } + default: + { + return "Unknown"; + } + } + } + } + """; + + Assert.Equal(expected.Trim(), code.Trim()); + _testOutputHelper.WriteLine(code); + } } diff --git a/README.md b/README.md index 43aa13b..ffb19f5 100644 --- a/README.md +++ b/README.md @@ -224,27 +224,32 @@ class MyClass **API Calling**: ```csharp -using static Fengb3.EasyCodeBuilder.Csharp.Code; +using Fengb3.EasyCodeBuilder.Csharp; +using Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations; +// Create a public class using KeywordConfigurator approach var classOption = new TypeOption() .WithTypeKind(TypeOption.Type.Class) .WithName("Person") - .WithKeyword("public") - .Constructor(ctor => { - ctor.WithKeyword("public") - .WithParameter("string name") // WithParameter for constructors - .WithParameter("int age") // WithParameter for constructors - .AppendLine("Name = name;") - .AppendLine("Age = age;"); - }) - .AutoProperty(p => p - .WithKeyword("public") - .WithType("string") - .WithName("Name")) - .AutoProperty(p => p - .WithKeyword("public") - .WithType("int") - .WithName("Age")); + .WithKeyword("public"); // TypeOption's public keyword + +// Add constructor (note: Constructor doesn't support KeywordConfigurator yet) +classOption.Constructor(ctor => { + ctor.WithKeyword("public") + .WithParameter("string name") + .WithParameter("int age") + .AppendLine("Name = name;") + .AppendLine("Age = age;"); +}); + +// Use KeywordConfigurator for properties +classOption.Public.AutoProperty(p => p + .WithType("string") + .WithName("Name")); + +classOption.Public.AutoProperty(p => p + .WithType("int") + .WithName("Age")); var code = classOption.Build(); ``` @@ -276,20 +281,26 @@ public class Person **API Calling**: ```csharp -using static Fengb3.EasyCodeBuilder.Csharp.Code; +using Fengb3.EasyCodeBuilder.Csharp; +using Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations; -var method = new MethodOption() - .WithName("PrintNumbers") - .WithReturnType("void") - .WithKeyword("public") - .For(@for => { - @for.WithInitializer("int i = 0") - .WithCondition("i < 10") - .WithIterator("i++") - .AppendLine("Console.WriteLine(i);"); - }); +// Create a method using KeywordConfigurator for public access +var classOption = new TypeOption() + .WithTypeKind(TypeOption.Type.Class) + .WithName("NumberPrinter"); + +classOption.Public.Method(method => { + method.WithName("PrintNumbers") + .WithReturnType("void") + .For(@for => { + @for.WithInitializer("int i = 0") + .WithCondition("i < 10") + .WithIterator("i++") + .AppendLine("Console.WriteLine(i);"); + }); +}); -var code = method.Build(); +var code = classOption.Build(); ```
@@ -297,11 +308,14 @@ var code = method.Build(); **Generated Code**: ```csharp -public void PrintNumbers() +class NumberPrinter { - for (int i = 0; i < 10; i++) + public void PrintNumbers() { - Console.WriteLine(i); + for (int i = 0; i < 10; i++) + { + Console.WriteLine(i); + } } } ``` @@ -316,30 +330,36 @@ public void PrintNumbers() **API Calling**: ```csharp -using static Fengb3.EasyCodeBuilder.Csharp.Code; +using Fengb3.EasyCodeBuilder.Csharp; +using Fengb3.EasyCodeBuilder.Csharp.OptionConfigurations; -var method = new MethodOption() - .WithName("GetDayName") - .WithReturnType("string") - .WithKeyword("public") - .WithParameters("int day"); // WithParameters for methods - -method.Switch(@switch => { - @switch.Expression = "day"; - @switch.Case(@case => { - @case.Value = "1"; - @case.AppendLine("return \"Monday\";"); - }); - @switch.Case(@case => { - @case.Value = "2"; - @case.AppendLine("return \"Tuesday\";"); +// Create a class with a public method using KeywordConfigurator +var classOption = new TypeOption() + .WithTypeKind(TypeOption.Type.Class) + .WithName("DayHelper"); + +classOption.Public.Method(method => { + method.WithName("GetDayName") + .WithReturnType("string") + .WithParameters("int day"); // WithParameters for methods + + method.Switch(@switch => { + @switch.Expression = "day"; + @switch.Case(@case => { + @case.Value = "1"; + @case.AppendLine("return \"Monday\";"); + }); + @switch.Case(@case => { + @case.Value = "2"; + @case.AppendLine("return \"Tuesday\";"); + }); + @switch.Default(@default => + @default.AppendLine("return \"Unknown\";") + ); }); - @switch.Default(@default => - @default.AppendLine("return \"Unknown\";") - ); }); -var code = method.Build(); +var code = classOption.Build(); ```
@@ -347,7 +367,31 @@ var code = method.Build(); **Generated Code**: ```csharp -public string GetDayName(int day) +class DayHelper +{ + public string GetDayName(int day) + { + switch (day) + { + case 1: + { + return "Monday"; + } + case 2: + { + return "Tuesday"; + } + default: + { + return "Unknown"; + } + } + } +} +``` + +
+ { switch (day) { From 24b31176042e1e63411dc5472eb81203934f500f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:56:21 +0000 Subject: [PATCH 6/6] Remove orphaned code block from Switch Statement example Co-authored-by: fengb3 <45181245+fengb3@users.noreply.github.com> --- README.md | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/README.md b/README.md index ffb19f5..cb11f55 100644 --- a/README.md +++ b/README.md @@ -390,27 +390,6 @@ class DayHelper } ``` - - -{ - switch (day) - { - case 1: - { - return "Monday"; - } - case 2: - { - return "Tuesday"; - } - default: - { - return "Unknown"; - } - } -} -``` -