mirror of
https://github.com/AlexMacocian/Sybil.git
synced 2026-07-15 15:19:59 +00:00
Setup Type Parameters support
This commit is contained in:
@@ -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, IInterface
|
||||
public sealed class TestClass<T> : BaseTestClass, IInterface where T : new(), class
|
||||
{
|
||||
[SomeAttribute5(null)]
|
||||
TestClass(string fieldString) : base(fieldString)
|
||||
@@ -29,7 +29,7 @@ public sealed class TestClass : BaseTestClass, IInterface
|
||||
public string PropertyString { private set; get; }
|
||||
|
||||
[SomeAttribute4(0.5F)]
|
||||
public string GetFieldString()
|
||||
public string GetFieldString<T>()
|
||||
{
|
||||
this.fieldString = 0;
|
||||
return this.fieldString;
|
||||
@@ -49,6 +49,11 @@ public sealed class TestClass : BaseTestClass, IInterface
|
||||
SyntaxBuilder.CreateClass("TestClass")
|
||||
.WithBaseClass("BaseTestClass")
|
||||
.WithInterface("IInterface")
|
||||
.WithTypeParameter(SyntaxBuilder.CreateTypeParameter("T"))
|
||||
.WithTypeParameterConstraint(
|
||||
SyntaxBuilder.CreateTypeParameterConstraint("T")
|
||||
.WithParameterlessConstructor()
|
||||
.WithClass())
|
||||
.WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute")
|
||||
.WithArgument("SomeIntProperty", 1)
|
||||
.WithArgument("SomeStringProperty", "Hello")
|
||||
@@ -87,6 +92,7 @@ public sealed class TestClass : BaseTestClass, IInterface
|
||||
.WithMethod(
|
||||
SyntaxBuilder.CreateMethod("string", "GetFieldString")
|
||||
.WithModifier("public")
|
||||
.WithTypeParameter(SyntaxBuilder.CreateTypeParameter("T"))
|
||||
.WithAttribute(SyntaxBuilder.CreateAttribute("SomeAttribute4")
|
||||
.WithArgument(0.5f))
|
||||
.WithBody("this.fieldString = 0;\r\nreturn this.fieldString;"))))
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
|
||||
namespace Sybil.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class TypeParameterBuilderTests
|
||||
{
|
||||
private const string TypeName = "T";
|
||||
|
||||
private readonly TypeParameterBuilder builder;
|
||||
|
||||
public TypeParameterBuilderTests()
|
||||
{
|
||||
this.builder = new TypeParameterBuilder(TypeName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Constructor_NullType_ThrowsArgumentNullException()
|
||||
{
|
||||
var action = () =>
|
||||
{
|
||||
_ = new TypeParameterBuilder(null);
|
||||
};
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_ReturnsPropertyDeclarationSyntax()
|
||||
{
|
||||
var syntax = this.builder.Build();
|
||||
|
||||
syntax.Should().NotBeNull().And.Subject.Should().BeOfType<TypeParameterSyntax>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
|
||||
namespace Sybil.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class TypeParameterConstraintBuilderTests
|
||||
{
|
||||
private const string TypeName = "T";
|
||||
private const string ConstraintType = "TType";
|
||||
private const string Expected = "where T : class, struct, new(), TType";
|
||||
|
||||
private readonly TypeParameterConstraintBuilder builder;
|
||||
|
||||
public TypeParameterConstraintBuilderTests()
|
||||
{
|
||||
this.builder = new TypeParameterConstraintBuilder(TypeName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Constructor_NullType_ThrowsArgumentNullException()
|
||||
{
|
||||
var action = () =>
|
||||
{
|
||||
_ = new TypeParameterConstraintBuilder(null);
|
||||
};
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithClass_ReturnsBuilder()
|
||||
{
|
||||
this.builder.WithClass().Should().BeOfType<TypeParameterConstraintBuilder>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithStruct_ReturnsBuilder()
|
||||
{
|
||||
this.builder.WithStruct().Should().BeOfType<TypeParameterConstraintBuilder>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithParameterlessConstructor_ReturnsBuilder()
|
||||
{
|
||||
this.builder.WithParameterlessConstructor().Should().BeOfType<TypeParameterConstraintBuilder>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithType_ReturnsBuilder()
|
||||
{
|
||||
this.builder.WithType(ConstraintType).Should().BeOfType<TypeParameterConstraintBuilder>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithType_NullType_ThrowsArgumentNullException()
|
||||
{
|
||||
var action = () =>
|
||||
{
|
||||
_ = this.builder.WithType(null);
|
||||
};
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_ReturnsPropertyDeclarationSyntax()
|
||||
{
|
||||
var syntax = this.builder.Build();
|
||||
|
||||
syntax.Should().NotBeNull().And.Subject.Should().BeOfType<TypeParameterConstraintClauseSyntax>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_ReturnsExpectedString()
|
||||
{
|
||||
var syntax = this.builder
|
||||
.WithClass()
|
||||
.WithStruct()
|
||||
.WithParameterlessConstructor()
|
||||
.WithType(ConstraintType)
|
||||
.Build();
|
||||
|
||||
var result = syntax.NormalizeWhitespace().ToFullString();
|
||||
|
||||
result.Should().Be(Expected);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ namespace Sybil
|
||||
private readonly List<FieldBuilder> Fields = new List<FieldBuilder>();
|
||||
private readonly List<PropertyBuilder> Properties = new List<PropertyBuilder>();
|
||||
private readonly List<MethodBuilder> Methods = new List<MethodBuilder>();
|
||||
private readonly List<TypeParameterBuilder> TypeParameters = new List<TypeParameterBuilder>();
|
||||
private readonly List<TypeParameterConstraintBuilder> TypeParameterConstraints = new List<TypeParameterConstraintBuilder>();
|
||||
|
||||
internal ClassBuilder(
|
||||
string className)
|
||||
@@ -98,6 +100,20 @@ namespace Sybil
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClassBuilder WithTypeParameter(TypeParameterBuilder typeParameterBuilder)
|
||||
{
|
||||
this.TypeParameters.Add(typeParameterBuilder ?? throw new ArgumentNullException(nameof(typeParameterBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClassBuilder WithTypeParameterConstraint(TypeParameterConstraintBuilder typeConstraintBuilder)
|
||||
{
|
||||
this.TypeParameterConstraints.Add(typeConstraintBuilder ?? throw new ArgumentNullException(nameof(typeConstraintBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClassDeclarationSyntax Build()
|
||||
{
|
||||
if (this.Attributes.Count > 0)
|
||||
@@ -105,6 +121,15 @@ namespace Sybil
|
||||
this.ClassDeclaration = this.ClassDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.Attributes.Select(p => p.Build()).ToArray())));
|
||||
}
|
||||
|
||||
if (this.TypeParameters.Count > 0)
|
||||
{
|
||||
this.ClassDeclaration = this.ClassDeclaration.AddTypeParameterListParameters(this.TypeParameters.Select(t => t.Build()).ToArray());
|
||||
if (this.TypeParameterConstraints.Count > 0)
|
||||
{
|
||||
this.ClassDeclaration = this.ClassDeclaration.AddConstraintClauses(this.TypeParameterConstraints.Select(t => t.Build()).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
return this.ClassDeclaration
|
||||
.AddMembers(this.Constructors.Select(p => p.Build()).ToArray())
|
||||
.AddMembers(this.Fields.Select(p => p.Build()).ToArray())
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Sybil
|
||||
|
||||
private readonly List<PropertyBuilder> Properties = new List<PropertyBuilder>();
|
||||
private readonly List<MethodBuilder> Methods = new List<MethodBuilder>();
|
||||
private readonly List<TypeParameterBuilder> TypeParameters = new List<TypeParameterBuilder>();
|
||||
private readonly List<TypeParameterConstraintBuilder> TypeParameterConstraints = new List<TypeParameterConstraintBuilder>();
|
||||
|
||||
internal InterfaceBuilder(
|
||||
string interfaceName)
|
||||
@@ -54,8 +56,31 @@ namespace Sybil
|
||||
return this;
|
||||
}
|
||||
|
||||
public InterfaceBuilder WithTypeParameter(TypeParameterBuilder typeParameterBuilder)
|
||||
{
|
||||
this.TypeParameters.Add(typeParameterBuilder ?? throw new ArgumentNullException(nameof(typeParameterBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public InterfaceBuilder WithTypeParameterConstraint(TypeParameterConstraintBuilder typeConstraintBuilder)
|
||||
{
|
||||
this.TypeParameterConstraints.Add(typeConstraintBuilder ?? throw new ArgumentNullException(nameof(typeConstraintBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public InterfaceDeclarationSyntax Build()
|
||||
{
|
||||
if (this.TypeParameters.Count > 0)
|
||||
{
|
||||
this.InterfaceDeclaration = this.InterfaceDeclaration.AddTypeParameterListParameters(this.TypeParameters.Select(t => t.Build()).ToArray());
|
||||
if (this.TypeParameterConstraints.Count > 0)
|
||||
{
|
||||
this.InterfaceDeclaration = this.InterfaceDeclaration.AddConstraintClauses(this.TypeParameterConstraints.Select(t => t.Build()).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
return this.InterfaceDeclaration
|
||||
.AddMembers(this.Properties.Select(p => p.Build()).ToArray())
|
||||
.AddMembers(this.Methods.Select(p => p.Build()).ToArray())
|
||||
|
||||
+26
-1
@@ -14,6 +14,8 @@ namespace Sybil
|
||||
private BlockSyntax BlockBody { get; set; }
|
||||
private ArrowExpressionClauseSyntax ArrowExpression { get; set; }
|
||||
private MethodDeclarationSyntax MethodDeclarationSyntax { get; set; }
|
||||
private readonly List<TypeParameterBuilder> TypeParameters = new List<TypeParameterBuilder>();
|
||||
private readonly List<TypeParameterConstraintBuilder> TypeParameterConstraints = new List<TypeParameterConstraintBuilder>();
|
||||
|
||||
internal MethodBuilder(
|
||||
string returnType, string name)
|
||||
@@ -115,6 +117,20 @@ namespace Sybil
|
||||
return this;
|
||||
}
|
||||
|
||||
public MethodBuilder WithTypeParameter(TypeParameterBuilder typeParameterBuilder)
|
||||
{
|
||||
this.TypeParameters.Add(typeParameterBuilder ?? throw new ArgumentNullException(nameof(typeParameterBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MethodBuilder WithTypeParameterConstraint(TypeParameterConstraintBuilder typeConstraintBuilder)
|
||||
{
|
||||
this.TypeParameterConstraints.Add(typeConstraintBuilder ?? throw new ArgumentNullException(nameof(typeConstraintBuilder)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MethodDeclarationSyntax Build()
|
||||
{
|
||||
if (this.attributeBuilders.Count > 0)
|
||||
@@ -122,13 +138,22 @@ namespace Sybil
|
||||
this.MethodDeclarationSyntax = this.MethodDeclarationSyntax.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(this.attributeBuilders.Select(p => p.Build()).ToArray())));
|
||||
}
|
||||
|
||||
if (this.TypeParameters.Count > 0)
|
||||
{
|
||||
this.MethodDeclarationSyntax = this.MethodDeclarationSyntax.AddTypeParameterListParameters(this.TypeParameters.Select(t => t.Build()).ToArray());
|
||||
if (this.TypeParameterConstraints.Count > 0)
|
||||
{
|
||||
this.MethodDeclarationSyntax = this.MethodDeclarationSyntax.AddConstraintClauses(this.TypeParameterConstraints.Select(t => t.Build()).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.BlockBody is null is false)
|
||||
{
|
||||
return this.MethodDeclarationSyntax
|
||||
.WithBody(this.BlockBody)
|
||||
.NormalizeWhitespace();
|
||||
}
|
||||
|
||||
|
||||
return this.MethodDeclarationSyntax
|
||||
.WithExpressionBody(this.ArrowExpression)
|
||||
.NormalizeWhitespace();
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>0.7.0</Version>
|
||||
<Version>0.8.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Sybil
|
||||
public static FieldBuilder CreateField(string fieldType, string fieldName) => new FieldBuilder(fieldType, fieldName);
|
||||
public static MethodBuilder CreateMethod(string returnType, string methodName) => new MethodBuilder(returnType, methodName);
|
||||
public static AttributeBuilder CreateAttribute(string attributeName) => new AttributeBuilder(attributeName);
|
||||
public static TypeParameterBuilder CreateTypeParameter(string typeName) => new TypeParameterBuilder(typeName);
|
||||
public static TypeParameterConstraintBuilder CreateTypeParameterConstraint(string typeName) => new TypeParameterConstraintBuilder(typeName);
|
||||
public static CompilationUnitBuilder CreateCompilationUnit() => new CompilationUnitBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
|
||||
namespace Sybil
|
||||
{
|
||||
public sealed class TypeParameterBuilder : IBuilder<TypeParameterSyntax>
|
||||
{
|
||||
private readonly string identifier;
|
||||
|
||||
internal TypeParameterBuilder(string identifier)
|
||||
{
|
||||
_ = identifier ?? throw new ArgumentNullException(nameof(identifier));
|
||||
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public TypeParameterSyntax Build()
|
||||
{
|
||||
return SyntaxFactory.TypeParameter(this.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
|
||||
namespace Sybil
|
||||
{
|
||||
public sealed class TypeParameterConstraintBuilder : IBuilder<TypeParameterConstraintClauseSyntax>
|
||||
{
|
||||
private TypeParameterConstraintClauseSyntax TypeParameterConstraintClauseSyntax { get; set; }
|
||||
|
||||
internal TypeParameterConstraintBuilder(string typeIdentifier)
|
||||
{
|
||||
_ = typeIdentifier ?? throw new ArgumentNullException(nameof(typeIdentifier));
|
||||
this.TypeParameterConstraintClauseSyntax = SyntaxFactory.TypeParameterConstraintClause(typeIdentifier);
|
||||
}
|
||||
|
||||
public TypeParameterConstraintBuilder WithClass()
|
||||
{
|
||||
this.TypeParameterConstraintClauseSyntax = this.TypeParameterConstraintClauseSyntax.AddConstraints(SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypeParameterConstraintBuilder WithStruct()
|
||||
{
|
||||
this.TypeParameterConstraintClauseSyntax = this.TypeParameterConstraintClauseSyntax.AddConstraints(SyntaxFactory.ClassOrStructConstraint(SyntaxKind.StructConstraint));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypeParameterConstraintBuilder WithParameterlessConstructor()
|
||||
{
|
||||
this.TypeParameterConstraintClauseSyntax = this.TypeParameterConstraintClauseSyntax.AddConstraints(SyntaxFactory.ConstructorConstraint());
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypeParameterConstraintBuilder WithType(string typeIdentifier)
|
||||
{
|
||||
this.TypeParameterConstraintClauseSyntax = this.TypeParameterConstraintClauseSyntax.AddConstraints(SyntaxFactory.TypeConstraint(SyntaxFactory.ParseTypeName(typeIdentifier ?? throw new ArgumentNullException(nameof(typeIdentifier)))));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypeParameterConstraintClauseSyntax Build()
|
||||
{
|
||||
return this.TypeParameterConstraintClauseSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user