Add factory method.
This commit is contained in:
parent
f607df6312
commit
1f517dd196
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MapTo.Extensions
|
||||||
|
{
|
||||||
|
internal static class StringBuilderExtensions
|
||||||
|
{
|
||||||
|
public static StringBuilder PadLeft(this StringBuilder builder, int width)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
builder.Append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static StringBuilder AppendOpeningBracket(this StringBuilder builder, int indent = 0)
|
||||||
|
{
|
||||||
|
return builder.AppendLine().PadLeft(indent).AppendFormat("{{{0}", Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static StringBuilder AppendClosingBracket(this StringBuilder builder, int indent = 0, bool padNewLine = true)
|
||||||
|
{
|
||||||
|
if (padNewLine)
|
||||||
|
{
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.PadLeft(indent).Append("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,9 +45,12 @@ namespace MapTo
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
// Namespace declaration
|
|
||||||
builder
|
builder
|
||||||
.AppendFileHeader()
|
.AppendFileHeader()
|
||||||
|
.GenerateUsings();
|
||||||
|
|
||||||
|
// Namespace declaration
|
||||||
|
builder
|
||||||
.AppendFormat("namespace {0}", model.Namespace)
|
.AppendFormat("namespace {0}", model.Namespace)
|
||||||
.AppendOpeningBracket();
|
.AppendOpeningBracket();
|
||||||
|
|
||||||
|
@ -57,8 +60,11 @@ namespace MapTo
|
||||||
.AppendFormat("{0} class {1}", model.ClassModifiers, model.ClassName)
|
.AppendFormat("{0} class {1}", model.ClassModifiers, model.ClassName)
|
||||||
.AppendOpeningBracket(Indent1);
|
.AppendOpeningBracket(Indent1);
|
||||||
|
|
||||||
// Constructor declaration
|
// Class body
|
||||||
builder.GenerateConstructor(model, out var mappedProperties);
|
builder
|
||||||
|
.GenerateConstructor(model, out var mappedProperties)
|
||||||
|
.AppendLine()
|
||||||
|
.GenerateFactoryMethod(model);
|
||||||
|
|
||||||
// End class declaration
|
// End class declaration
|
||||||
builder.AppendClosingBracket(Indent1);
|
builder.AppendClosingBracket(Indent1);
|
||||||
|
@ -69,6 +75,13 @@ namespace MapTo
|
||||||
return (builder.ToString(), $"{model.ClassName}.cs");
|
return (builder.ToString(), $"{model.ClassName}.cs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static StringBuilder GenerateUsings(this StringBuilder builder)
|
||||||
|
{
|
||||||
|
return builder
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
private static StringBuilder GenerateConstructor(this StringBuilder builder, MapModel model, out List<IPropertySymbol> mappedProperties)
|
private static StringBuilder GenerateConstructor(this StringBuilder builder, MapModel model, out List<IPropertySymbol> mappedProperties)
|
||||||
{
|
{
|
||||||
var destinationClassParameterName = model.DestinationClassName.ToCamelCase();
|
var destinationClassParameterName = model.DestinationClassName.ToCamelCase();
|
||||||
|
@ -76,7 +89,10 @@ namespace MapTo
|
||||||
builder
|
builder
|
||||||
.PadLeft(Indent2)
|
.PadLeft(Indent2)
|
||||||
.AppendFormat("public {0}({1} {2})", model.ClassName, model.DestinationClassName, destinationClassParameterName)
|
.AppendFormat("public {0}({1} {2})", model.ClassName, model.DestinationClassName, destinationClassParameterName)
|
||||||
.AppendOpeningBracket(Indent2);
|
.AppendOpeningBracket(Indent2)
|
||||||
|
.PadLeft(Indent3)
|
||||||
|
.AppendFormat("if ({0} == null) throw new ArgumentNullException(nameof({0}));", destinationClassParameterName)
|
||||||
|
.AppendLine();
|
||||||
|
|
||||||
mappedProperties = new List<IPropertySymbol>();
|
mappedProperties = new List<IPropertySymbol>();
|
||||||
foreach (var propertySymbol in model.DestinationTypeProperties)
|
foreach (var propertySymbol in model.DestinationTypeProperties)
|
||||||
|
@ -94,41 +110,24 @@ namespace MapTo
|
||||||
return builder.AppendClosingBracket(Indent2, padNewLine: false);
|
return builder.AppendClosingBracket(Indent2, padNewLine: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StringBuilder AppendOpeningBracket(this StringBuilder builder, int indent = 0)
|
private static StringBuilder GenerateFactoryMethod(this StringBuilder builder, MapModel model)
|
||||||
{
|
{
|
||||||
return builder.AppendLine().PadLeft(indent).AppendFormat("{{{0}", Environment.NewLine);
|
var destinationClassParameterName = model.DestinationClassName.ToCamelCase();
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuilder AppendClosingBracket(this StringBuilder builder, int indent = 0, bool padNewLine = true)
|
return builder
|
||||||
{
|
.AppendLine()
|
||||||
if (padNewLine)
|
.PadLeft(Indent2)
|
||||||
{
|
.AppendFormat("public static {0} From({1} {2})", model.ClassName, model.DestinationClassName, destinationClassParameterName)
|
||||||
builder.AppendLine();
|
.AppendOpeningBracket(Indent2)
|
||||||
}
|
.PadLeft(Indent3)
|
||||||
|
.AppendFormat("return {0} == null ? null : new {1}({0});", destinationClassParameterName, model.ClassName )
|
||||||
return builder.PadLeft(indent).Append("}");
|
.AppendClosingBracket(Indent2);
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuilder PadLeft(this StringBuilder builder, int width)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
builder.Append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StringBuilder AppendFileHeader(this StringBuilder builder)
|
private static StringBuilder AppendFileHeader(this StringBuilder builder)
|
||||||
{
|
{
|
||||||
return builder
|
return builder
|
||||||
.AppendLine("// <auto-generated />")
|
.AppendLine("// <auto-generated />");
|
||||||
.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetValueText(this NameSyntax? nameSyntax)
|
|
||||||
{
|
|
||||||
return (nameSyntax as IdentifierNameSyntax)?.Identifier.ValueText ?? string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -84,6 +84,7 @@ namespace Test
|
||||||
|
|
||||||
const string expectedResult = @"
|
const string expectedResult = @"
|
||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Test
|
namespace Test
|
||||||
{
|
{
|
||||||
|
@ -91,8 +92,7 @@ namespace Test
|
||||||
{
|
{
|
||||||
public Foo(Baz baz)
|
public Foo(Baz baz)
|
||||||
{
|
{
|
||||||
}
|
if (baz == null) throw new ArgumentNullException(nameof(baz));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace Test
|
||||||
// Assert
|
// Assert
|
||||||
diagnostics.ShouldBeSuccessful();
|
diagnostics.ShouldBeSuccessful();
|
||||||
compilation.SyntaxTrees.Count().ShouldBe(3);
|
compilation.SyntaxTrees.Count().ShouldBe(3);
|
||||||
compilation.SyntaxTrees.Last().ToString().ShouldBe(expectedResult.Trim());
|
compilation.SyntaxTrees.Last().ToString().ShouldStartWith(expectedResult.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -127,6 +127,7 @@ namespace Test
|
||||||
|
|
||||||
const string expectedResult = @"
|
const string expectedResult = @"
|
||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Test
|
namespace Test
|
||||||
{
|
{
|
||||||
|
@ -134,8 +135,7 @@ namespace Test
|
||||||
{
|
{
|
||||||
public Foo(Baz baz)
|
public Foo(Baz baz)
|
||||||
{
|
{
|
||||||
}
|
if (baz == null) throw new ArgumentNullException(nameof(baz));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ namespace Test
|
||||||
// Assert
|
// Assert
|
||||||
diagnostics.ShouldBeSuccessful();
|
diagnostics.ShouldBeSuccessful();
|
||||||
compilation.SyntaxTrees.Count().ShouldBe(3);
|
compilation.SyntaxTrees.Count().ShouldBe(3);
|
||||||
compilation.SyntaxTrees.Last().ToString().ShouldBe(expectedResult.Trim());
|
compilation.SyntaxTrees.Last().ToString().ShouldStartWith(expectedResult.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -159,6 +159,7 @@ namespace Test
|
||||||
{
|
{
|
||||||
public Foo(Baz baz)
|
public Foo(Baz baz)
|
||||||
{
|
{
|
||||||
|
if (baz == null) throw new ArgumentNullException(nameof(baz));
|
||||||
Prop1 = baz.Prop1;
|
Prop1 = baz.Prop1;
|
||||||
Prop2 = baz.Prop2;
|
Prop2 = baz.Prop2;
|
||||||
Prop3 = baz.Prop3;
|
Prop3 = baz.Prop3;
|
||||||
|
@ -174,6 +175,28 @@ namespace Test
|
||||||
compilation.SyntaxTrees.Last().ToString().ShouldContain(expectedResult.Trim());
|
compilation.SyntaxTrees.Last().ToString().ShouldContain(expectedResult.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void When_SourceTypeHasMatchingProperties_Should_CreateFromStaticMethod()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var source = GetSourceText();
|
||||||
|
|
||||||
|
const string expectedResult = @"
|
||||||
|
public static Foo From(Baz baz)
|
||||||
|
{
|
||||||
|
return baz == null ? null : new Foo(baz);
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
diagnostics.ShouldBeSuccessful();
|
||||||
|
compilation.SyntaxTrees.Count().ShouldBe(3);
|
||||||
|
compilation.SyntaxTrees.Last().ToString().ShouldContain(expectedResult.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetSourceText(bool includeAttributeNamespace = false)
|
private static string GetSourceText(bool includeAttributeNamespace = false)
|
||||||
{
|
{
|
||||||
return @$"
|
return @$"
|
||||||
|
|
Loading…
Reference in New Issue