Add interface builder

This commit is contained in:
2024-09-19 13:47:55 +02:00
parent 64f573a51f
commit bfdd2ce911
7 changed files with 238 additions and 2 deletions
+2 -1
View File
@@ -13,7 +13,7 @@ public sealed class FlowTests
[InternalsVisibleTo(""FlowTests"")]
namespace TestNamespace;
[SomeAttribute(SomeIntProperty = 1, SomeStringProperty = ""Hello"", SomeEnumProperty = MyEnum.Value, SomeTypeProperty = typeof(String), SomeNullProperty = null)]
public sealed class TestClass : BaseTestClass
public sealed class TestClass : BaseTestClass, IInterface
{
[SomeAttribute5(null)]
TestClass(string fieldString) : base(fieldString)
@@ -48,6 +48,7 @@ public sealed class TestClass : BaseTestClass
.WithClass(
SyntaxBuilder.CreateClass("TestClass")
.WithBaseClass("BaseTestClass")
.WithInterface("IInterface")
.WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute")
.WithArgument("SomeIntProperty", 1)
.WithArgument("SomeStringProperty", "Hello")
+35
View File
@@ -10,6 +10,7 @@ public class ClassBuilderTests
{
private const string Name = "Test";
private const string Base = "Base";
private const string IBase = "IBase";
private const string PublicClass =
@"public class Test
{
@@ -21,6 +22,10 @@ public class ClassBuilderTests
private const string ClassWithBase =
@"class Test : Base
{
}";
private const string ClassWithInterface =
@"class Test : IBase
{
}";
private readonly ClassBuilder builder;
@@ -142,6 +147,25 @@ public class ClassBuilderTests
returnedBuilder.Should().NotBeNull().And.Subject.Should().BeOfType<ClassBuilder>();
}
[TestMethod]
public void WithInterface_NullInterface_ThrowsArgumentNullException()
{
var action = () =>
{
this.builder.WithInterface(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void WithInterface_InterfaceValid_ReturnsBuilder()
{
var returnedBuilder = this.builder.WithInterface(Base);
returnedBuilder.Should().NotBeNull().And.Subject.Should().BeOfType<ClassBuilder>();
}
[TestMethod]
public void Build_ReturnsClassDeclarationSyntax()
{
@@ -176,4 +200,15 @@ public class ClassBuilderTests
result.Should().Be(ClassWithBase);
}
[TestMethod]
public void WithInterface_ReturnsExpectedString()
{
var result = this.builder
.WithInterface(IBase)
.Build()
.ToFullString();
result.Should().Be(ClassWithInterface);
}
}
+124
View File
@@ -0,0 +1,124 @@
using FluentAssertions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace Sybil.Tests;
[TestClass]
public class InterfaceBuilderTests
{
private const string Name = "ITest";
private const string PublicInterface =
@"public interface ITest
{
}";
private const string Interface =
@"interface ITest
{
}";
private readonly InterfaceBuilder builder;
public InterfaceBuilderTests()
{
this.builder = new InterfaceBuilder(Name);
}
[TestMethod]
public void Constructor_NullName_ThrowArgumentNullException()
{
var action = () =>
{
_ = new InterfaceBuilder(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void WithModifier_ModifierNull_ThrowsArgumentNullException()
{
var action = () =>
{
this.builder.WithModifier(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void WithModifier_ModifierValid_ReturnsBuilder()
{
var returnedBuilder = this.builder.WithModifier("public");
returnedBuilder.Should().NotBeNull().And.Subject.Should().Be(this.builder);
}
[TestMethod]
public void WithModifiers_ModifiersNull_ThrowsArgumentNullException()
{
var action = () =>
{
this.builder.WithModifiers(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void WithModifiers_ModifiersValid_ReturnsBuilder()
{
var returnedBuilder = this.builder.WithModifiers("public static");
returnedBuilder.Should().NotBeNull().And.Subject.Should().Be(this.builder);
}
[TestMethod]
public void WithProperty_NullPropertyBuilder_ThrowsArgumentNullException()
{
var action = () =>
{
this.builder.WithProperty(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void WithMethod_NullMethodBuilder_ThrowsArgumentNullException()
{
var action = () =>
{
this.builder.WithMethod(null);
};
action.Should().Throw<ArgumentNullException>();
}
[TestMethod]
public void Build_ReturnsInterfaceDeclarationSyntax()
{
var syntax = this.builder.Build();
syntax.Should().NotBeNull().And.Subject.Should().BeOfType<InterfaceDeclarationSyntax>();
}
[TestMethod]
public void WithModifier_ReturnsExpectedString()
{
var result = this.builder.WithModifier("public").Build().ToFullString();
result.Should().Be(PublicInterface);
}
[TestMethod]
public void Build_ReturnsExpectedString()
{
var result = this.builder
.Build()
.ToFullString();
result.Should().Be(Interface);
}
}
+10
View File
@@ -35,6 +35,16 @@ namespace Sybil
return this;
}
public ClassBuilder WithInterface(string interfaceName)
{
_ = string.IsNullOrWhiteSpace(interfaceName) ? throw new ArgumentNullException(nameof(interfaceName)) : interfaceName;
this.ClassDeclaration = this.ClassDeclaration.AddBaseListTypes(
SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(interfaceName)));
return this;
}
public ClassBuilder WithModifier(string modifier)
{
_ = string.IsNullOrWhiteSpace(modifier) ? throw new ArgumentNullException(nameof(modifier)) : modifier;
+65
View File
@@ -0,0 +1,65 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
namespace Sybil
{
public sealed class InterfaceBuilder : IBuilder<InterfaceDeclarationSyntax>
{
private InterfaceDeclarationSyntax InterfaceDeclaration { get; set; }
private readonly List<PropertyBuilder> Properties = new List<PropertyBuilder>();
private readonly List<MethodBuilder> Methods = new List<MethodBuilder>();
internal InterfaceBuilder(
string interfaceName)
{
_ = string.IsNullOrWhiteSpace(interfaceName) ? throw new ArgumentNullException(nameof(interfaceName)) : interfaceName;
this.InterfaceDeclaration = SyntaxFactory.InterfaceDeclaration(interfaceName);
}
public InterfaceBuilder WithModifier(string modifier)
{
_ = string.IsNullOrWhiteSpace(modifier) ? throw new ArgumentNullException(nameof(modifier)) : modifier;
this.InterfaceDeclaration = this.InterfaceDeclaration.AddModifiers(SyntaxFactory.ParseToken(modifier));
return this;
}
public InterfaceBuilder WithModifiers(string modifiers)
{
_ = string.IsNullOrWhiteSpace(modifiers) ? throw new ArgumentNullException(nameof(modifiers)) : modifiers;
this.InterfaceDeclaration = this.InterfaceDeclaration.AddModifiers(SyntaxFactory.ParseTokens(modifiers).ToArray());
return this;
}
public InterfaceBuilder WithProperty(PropertyBuilder propertyBuilder)
{
this.Properties.Add(propertyBuilder ?? throw new ArgumentNullException(nameof(propertyBuilder)));
return this;
}
public InterfaceBuilder WithMethod(MethodBuilder methodBuilder)
{
this.Methods.Add(methodBuilder ?? throw new ArgumentNullException(nameof(methodBuilder)));
return this;
}
public InterfaceDeclarationSyntax Build()
{
return this.InterfaceDeclaration
.AddMembers(this.Properties.Select(p => p.Build()).ToArray())
.AddMembers(this.Methods.Select(p => p.Build()).ToArray())
.NormalizeWhitespace();
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>0.6.0</Version>
<Version>0.7.0</Version>
</PropertyGroup>
<PropertyGroup>
+1
View File
@@ -7,6 +7,7 @@ namespace Sybil
public static NamespaceBuilder CreateNamespace(string @namespace) => new NamespaceBuilder(@namespace, false);
public static NamespaceBuilder CreateFileScopedNamespace(string @namespace) => new NamespaceBuilder(@namespace, true);
public static ClassBuilder CreateClass(string className) => new ClassBuilder(className);
public static InterfaceBuilder CreateInterface(string interfaceName) => new InterfaceBuilder(interfaceName);
public static ConstructorBuilder CreateConstructor(string className) => new ConstructorBuilder(className);
public static BaseConstructorBuilder CreateBaseConstructor() => new BaseConstructorBuilder();
public static PropertyBuilder CreateProperty(string typeName, string propertyName) => new PropertyBuilder(typeName, propertyName);