From df191bf0533fee3497b6787e54eab2def221efdd Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Wed, 10 Apr 2024 15:15:47 +0200 Subject: [PATCH] Add attributes to namespaces Fix builders with empty attributes --- README.md | 87 +++++++++++++++-------------- Sybil.IntegrationTests/FlowTests.cs | 5 +- Sybil/ClassBuilder.cs | 6 +- Sybil/ConstructorBuilder.cs | 6 +- Sybil/FieldBuilder.cs | 6 +- Sybil/MethodBuilder.cs | 7 ++- Sybil/NamespaceBuilder.cs | 15 +++++ Sybil/PropertyBuilder.cs | 6 +- 8 files changed, 89 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 38c484b..6f3835e 100644 --- a/README.md +++ b/README.md @@ -8,59 +8,62 @@ Sybil supports building of namespaces with classes, constructors, parameters, pr Example of creating a namespace with one class with one constructor and base class, multiple fields, properties and methods: ```C# var namespaceSyntax = SyntaxBuilder.CreateNamespace("TestNamespace") - .WithUsing("System") - .WithClass( - SyntaxBuilder.CreateClass("TestClass") - .WithBaseClass("BaseTestClass") - .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute") - .WithArgument("SomeIntProperty", 1) - .WithArgument("SomeStringProperty", "Hello") - .WithArgument("SomeEnumProperty", MyEnum.Value) - .WithArgument("SomeTypeProperty", typeof(string)) - .WithNullArgument("SomeNullProperty")) - .WithModifiers("public sealed") - .WithConstructor( - SyntaxBuilder.CreateConstructor("TestClass") - .WithBase( - SyntaxBuilder.CreateBaseConstructor() - .WithArgument("fieldString")) - .WithAttribute( - SyntaxBuilder.CreateAttribute("SomeAttribute5") - .WithNullArgument()) - .WithParameter("string", "fieldString") - .WithBody("this.fieldString = fieldString ?? throw new ArgumentNullException();")) - .WithField( - SyntaxBuilder.CreateField("string", "fieldString") - .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute2")) + .WithAttribute(SyntaxBuilder.CreateAttribute("InternalsVisibleTo") + .WithArgument("FlowTests")) + .WithUsing("System") + .WithClass( + SyntaxBuilder.CreateClass("TestClass") + .WithBaseClass("BaseTestClass") + .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute") + .WithArgument("SomeIntProperty", 1) + .WithArgument("SomeStringProperty", "Hello") + .WithArgument("SomeEnumProperty", MyEnum.Value) + .WithArgument("SomeTypeProperty", typeof(string)) + .WithNullArgument("SomeNullProperty")) + .WithModifiers("public sealed") + .WithConstructor( + SyntaxBuilder.CreateConstructor("TestClass") + .WithBase( + SyntaxBuilder.CreateBaseConstructor() + .WithArgument("fieldString")) + .WithAttribute( + SyntaxBuilder.CreateAttribute("SomeAttribute5") + .WithNullArgument()) + .WithParameter("string", "fieldString") + .WithBody("this.fieldString = fieldString ?? throw new ArgumentNullException();")) + .WithField( + SyntaxBuilder.CreateField("string", "fieldString") + .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute2")) + .WithModifier("private")) + .WithProperty( + SyntaxBuilder.CreateProperty("string", "PropertyString") + .WithModifier("public") + .WithAccessor( + SyntaxBuilder.CreateSetter() .WithModifier("private")) - .WithProperty( - SyntaxBuilder.CreateProperty("string", "PropertyString") - .WithModifier("public") - .WithAccessor( - SyntaxBuilder.CreateSetter() - .WithModifier("private")) - .WithAccessor( - SyntaxBuilder.CreateGetter()) - .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute3") - .WithArgument(typeof(string)))) - .WithMethod( - SyntaxBuilder.CreateMethod("string", "GetFieldString") - .WithModifier("public") - .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute4") - .WithArgument(0.5f)) - .WithBody("return this.fieldString;"))) - .Build(); + .WithAccessor( + SyntaxBuilder.CreateGetter()) + .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute3") + .WithArgument(typeof(string)))) + .WithMethod( + SyntaxBuilder.CreateMethod("string", "GetFieldString") + .WithModifier("public") + .WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute4") + .WithArgument(0.5f)) + .WithBody("return this.fieldString;"))) + .Build(); var namespaceString = namespaceSyntax.ToFullString(); ``` This generates the following syntax: ```C# +[InternalsVisibleTo(""FlowTests"")] namespace TestNamespace { using System; - [SomeAttribute(SomeIntProperty = 1, SomeStringProperty = "Hello", SomeEnumProperty = MyEnum.Value, SomeTypeProperty = typeof(String), SomeNullProperty = null)] + [SomeAttribute(SomeIntProperty = 1, SomeStringProperty = ""Hello"", SomeEnumProperty = MyEnum.Value, SomeTypeProperty = typeof(String), SomeNullProperty = null)] public sealed class TestClass : BaseTestClass { [SomeAttribute5(null)] diff --git a/Sybil.IntegrationTests/FlowTests.cs b/Sybil.IntegrationTests/FlowTests.cs index 025799b..99ae323 100644 --- a/Sybil.IntegrationTests/FlowTests.cs +++ b/Sybil.IntegrationTests/FlowTests.cs @@ -8,7 +8,8 @@ namespace Sybil.IntegrationTests; public sealed class FlowTests { private const string ExpectedNamespace = -@"namespace TestNamespace +@"[InternalsVisibleTo(""FlowTests"")] +namespace TestNamespace { using System; @@ -38,6 +39,8 @@ public sealed class FlowTests public void NewNamespace_GeneratesExpected() { var namespaceSyntax = SyntaxBuilder.CreateNamespace("TestNamespace") + .WithAttribute(SyntaxBuilder.CreateAttribute("InternalsVisibleTo") + .WithArgument("FlowTests")) .WithUsing("System") .WithClass( SyntaxBuilder.CreateClass("TestClass") diff --git a/Sybil/ClassBuilder.cs b/Sybil/ClassBuilder.cs index 915c9f2..2afd1af 100644 --- a/Sybil/ClassBuilder.cs +++ b/Sybil/ClassBuilder.cs @@ -90,8 +90,12 @@ namespace Sybil public ClassDeclarationSyntax Build() { + if (this.Attributes.Count > 0) + { + this.ClassDeclaration = this.ClassDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.Attributes.Select(p => p.Build()).ToArray()))); + } + return this.ClassDeclaration - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.Attributes.Select(p => p.Build()).ToArray()))) .AddMembers(this.Constructors.Select(p => p.Build()).ToArray()) .AddMembers(this.Fields.Select(p => p.Build()).ToArray()) .AddMembers(this.Properties.Select(p => p.Build()).ToArray()) diff --git a/Sybil/ConstructorBuilder.cs b/Sybil/ConstructorBuilder.cs index 8b12158..a29a7c7 100644 --- a/Sybil/ConstructorBuilder.cs +++ b/Sybil/ConstructorBuilder.cs @@ -97,8 +97,12 @@ namespace Sybil this.ConstructorDeclarationSyntax = this.ConstructorDeclarationSyntax.WithInitializer(this.baseConstructorBuilder.Build()); } + if (this.attributes.Count > 0) + { + this.ConstructorDeclarationSyntax = this.ConstructorDeclarationSyntax.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributes.Select(p => p.Build()).ToArray()))); + } + return this.ConstructorDeclarationSyntax - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributes.Select(p => p.Build()).ToArray()))) .NormalizeWhitespace(); } } diff --git a/Sybil/FieldBuilder.cs b/Sybil/FieldBuilder.cs index be503a2..066c2d6 100644 --- a/Sybil/FieldBuilder.cs +++ b/Sybil/FieldBuilder.cs @@ -52,8 +52,12 @@ namespace Sybil public FieldDeclarationSyntax Build() { + if (this.attributeBuilders.Count > 0) + { + this.FieldDeclarationSyntax = this.FieldDeclarationSyntax.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))); + } + return this.FieldDeclarationSyntax - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))) .NormalizeWhitespace(); } } diff --git a/Sybil/MethodBuilder.cs b/Sybil/MethodBuilder.cs index 6a6d9c5..c27a8cc 100644 --- a/Sybil/MethodBuilder.cs +++ b/Sybil/MethodBuilder.cs @@ -112,16 +112,19 @@ namespace Sybil public MethodDeclarationSyntax Build() { + if (this.attributeBuilders.Count > 0) + { + this.MethodDeclarationSyntax = this.MethodDeclarationSyntax.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))); + } + if (this.BlockBody is null is false) { return this.MethodDeclarationSyntax - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))) .WithBody(this.BlockBody) .NormalizeWhitespace(); } return this.MethodDeclarationSyntax - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))) .WithExpressionBody(this.ArrowExpression) .NormalizeWhitespace(); } diff --git a/Sybil/NamespaceBuilder.cs b/Sybil/NamespaceBuilder.cs index 422d0f3..c5d6347 100644 --- a/Sybil/NamespaceBuilder.cs +++ b/Sybil/NamespaceBuilder.cs @@ -9,6 +9,7 @@ namespace Sybil { public sealed class NamespaceBuilder : IBuilder { + private readonly List attributeBuilders = new List(); private readonly List classBuilders = new List(); private NamespaceDeclarationSyntax NamespaceDeclaration { get; set; } @@ -38,8 +39,22 @@ namespace Sybil return this; } + public NamespaceBuilder WithAttribute(AttributeBuilder attributeBuilder) + { + _ = attributeBuilder ?? throw new ArgumentNullException(nameof(attributeBuilder)); + + this.attributeBuilders.Add(attributeBuilder); + + return this; + } + public NamespaceDeclarationSyntax Build() { + if (this.attributeBuilders.Count > 0) + { + this.NamespaceDeclaration = this.NamespaceDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray()))); + } + return this.NamespaceDeclaration .AddMembers(this.classBuilders.Select(c => c.Build()).ToArray()) .NormalizeWhitespace(); diff --git a/Sybil/PropertyBuilder.cs b/Sybil/PropertyBuilder.cs index 2dc1926..9e4e2c2 100644 --- a/Sybil/PropertyBuilder.cs +++ b/Sybil/PropertyBuilder.cs @@ -60,9 +60,13 @@ namespace Sybil public PropertyDeclarationSyntax Build() { + if (this.attributes.Count > 0) + { + this.PropertyDeclarationSyntax = this.PropertyDeclarationSyntax.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributes.Select(p => p.Build()).ToArray()))); + } + return this.PropertyDeclarationSyntax .WithAccessorList(this.BuildAccessorList()) - .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributes.Select(p => p.Build()).ToArray()))) .NormalizeWhitespace(); }