Add extension method on source type to get the destination type.
This commit is contained in:
parent
0327ab41a6
commit
85099ed080
|
@ -63,7 +63,7 @@ namespace MapTo
|
||||||
|
|
||||||
return new MapModel(
|
return new MapModel(
|
||||||
ns: root.GetNamespace(),
|
ns: root.GetNamespace(),
|
||||||
classModifiers: classSyntax.GetClassModifier(),
|
classModifiers: classSyntax.Modifiers,
|
||||||
className: classSyntax.GetClassName(),
|
className: classSyntax.GetClassName(),
|
||||||
properties: classSymbol.GetAllMembersOfType<IPropertySymbol>(),
|
properties: classSymbol.GetAllMembersOfType<IPropertySymbol>(),
|
||||||
sourceNamespace: destinationTypeSymbol.ContainingNamespace.Name,
|
sourceNamespace: destinationTypeSymbol.ContainingNamespace.Name,
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace MapTo.Models
|
||||||
{
|
{
|
||||||
public class MapModel
|
public class MapModel
|
||||||
{
|
{
|
||||||
public MapModel(string? ns, string classModifiers, string className, IEnumerable<IPropertySymbol> properties, string sourceNamespace, string sourceClassName, IEnumerable<IPropertySymbol> sourceTypeProperties)
|
public MapModel(string? ns, SyntaxTokenList classModifiers, string className, IEnumerable<IPropertySymbol> properties, string sourceNamespace, string sourceClassName, IEnumerable<IPropertySymbol> sourceTypeProperties)
|
||||||
{
|
{
|
||||||
Namespace = ns;
|
Namespace = ns;
|
||||||
ClassModifiers = classModifiers;
|
ClassModifiers = classModifiers;
|
||||||
|
@ -18,7 +18,7 @@ namespace MapTo.Models
|
||||||
|
|
||||||
public string? Namespace { get; }
|
public string? Namespace { get; }
|
||||||
|
|
||||||
public string ClassModifiers { get; }
|
public SyntaxTokenList ClassModifiers { get; }
|
||||||
|
|
||||||
public string ClassName { get; }
|
public string ClassName { get; }
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ using System.Text;
|
||||||
using MapTo.Extensions;
|
using MapTo.Extensions;
|
||||||
using MapTo.Models;
|
using MapTo.Models;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
|
||||||
namespace MapTo
|
namespace MapTo
|
||||||
|
@ -47,30 +46,40 @@ namespace MapTo
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.AppendFileHeader()
|
.AppendFileHeader()
|
||||||
.GenerateUsings(model);
|
.GenerateUsings(model)
|
||||||
|
|
||||||
// Namespace declaration
|
// Namespace declaration
|
||||||
builder
|
|
||||||
.AppendFormat("namespace {0}", model.Namespace)
|
.AppendFormat("namespace {0}", model.Namespace)
|
||||||
.AppendOpeningBracket();
|
.AppendOpeningBracket()
|
||||||
|
|
||||||
// Class declaration
|
// Class declaration
|
||||||
builder
|
|
||||||
.PadLeft(Indent1)
|
.PadLeft(Indent1)
|
||||||
.AppendFormat("{0} class {1}", model.ClassModifiers, model.ClassName)
|
.AppendFormat("{0} class {1}", model.ClassModifiers.ToFullString().Trim(), model.ClassName)
|
||||||
.AppendOpeningBracket(Indent1);
|
.AppendOpeningBracket(Indent1)
|
||||||
|
|
||||||
// Class body
|
// Class body
|
||||||
builder
|
|
||||||
.GenerateConstructor(model, out var mappedProperties)
|
.GenerateConstructor(model, out var mappedProperties)
|
||||||
.AppendLine()
|
.AppendLine()
|
||||||
.GenerateFactoryMethod(model);
|
.GenerateFactoryMethod(model)
|
||||||
|
|
||||||
// End class declaration
|
// End class declaration
|
||||||
builder.AppendClosingBracket(Indent1);
|
.AppendClosingBracket(Indent1)
|
||||||
|
|
||||||
|
// Extensions Class declaration
|
||||||
|
.AppendLine()
|
||||||
|
.AppendLine()
|
||||||
|
.PadLeft(Indent1)
|
||||||
|
.AppendFormat("{0} static class {1}Extensions", model.ClassModifiers.FirstOrDefault().ToFullString().Trim(), model.SourceClassName)
|
||||||
|
.AppendOpeningBracket(Indent1)
|
||||||
|
|
||||||
|
// Extension class body
|
||||||
|
.GenerateSourceTypeExtensionMethod(model)
|
||||||
|
|
||||||
|
// End extensions class declaration
|
||||||
|
.AppendClosingBracket(Indent1)
|
||||||
|
|
||||||
// End namespace declaration
|
// End namespace declaration
|
||||||
builder.AppendClosingBracket();
|
.AppendClosingBracket();
|
||||||
|
|
||||||
return (builder.ToString(), $"{model.ClassName}.cs");
|
return (builder.ToString(), $"{model.ClassName}.cs");
|
||||||
}
|
}
|
||||||
|
@ -89,14 +98,14 @@ namespace MapTo
|
||||||
|
|
||||||
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.SourceClassName.ToCamelCase();
|
var sourceClassParameterName = model.SourceClassName.ToCamelCase();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.PadLeft(Indent2)
|
.PadLeft(Indent2)
|
||||||
.AppendFormat("public {0}({1} {2})", model.ClassName, model.SourceClassName, destinationClassParameterName)
|
.AppendFormat("public {0}({1} {2})", model.ClassName, model.SourceClassName, sourceClassParameterName)
|
||||||
.AppendOpeningBracket(Indent2)
|
.AppendOpeningBracket(Indent2)
|
||||||
.PadLeft(Indent3)
|
.PadLeft(Indent3)
|
||||||
.AppendFormat("if ({0} == null) throw new ArgumentNullException(nameof({0}));", destinationClassParameterName)
|
.AppendFormat("if ({0} == null) throw new ArgumentNullException(nameof({0}));", sourceClassParameterName)
|
||||||
.AppendLine();
|
.AppendLine();
|
||||||
|
|
||||||
mappedProperties = new List<IPropertySymbol>();
|
mappedProperties = new List<IPropertySymbol>();
|
||||||
|
@ -107,25 +116,38 @@ namespace MapTo
|
||||||
mappedProperties.Add(propertySymbol);
|
mappedProperties.Add(propertySymbol);
|
||||||
builder
|
builder
|
||||||
.PadLeft(Indent3)
|
.PadLeft(Indent3)
|
||||||
.AppendFormat("{0} = {1}.{2};{3}", propertySymbol.Name, destinationClassParameterName, propertySymbol.Name, Environment.NewLine);
|
.AppendFormat("{0} = {1}.{2};{3}", propertySymbol.Name, sourceClassParameterName, propertySymbol.Name, Environment.NewLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End constructor declaration
|
// End constructor declaration
|
||||||
return builder.AppendClosingBracket(Indent2, padNewLine: false);
|
return builder.AppendClosingBracket(Indent2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StringBuilder GenerateFactoryMethod(this StringBuilder builder, MapModel model)
|
private static StringBuilder GenerateFactoryMethod(this StringBuilder builder, MapModel model)
|
||||||
{
|
{
|
||||||
var destinationClassParameterName = model.SourceClassName.ToCamelCase();
|
var sourceClassParameterName = model.SourceClassName.ToCamelCase();
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
.AppendLine()
|
.AppendLine()
|
||||||
.PadLeft(Indent2)
|
.PadLeft(Indent2)
|
||||||
.AppendFormat("public static {0} From({1} {2})", model.ClassName, model.SourceClassName, destinationClassParameterName)
|
.AppendFormat("public static {0} From({1} {2})", model.ClassName, model.SourceClassName, sourceClassParameterName)
|
||||||
.AppendOpeningBracket(Indent2)
|
.AppendOpeningBracket(Indent2)
|
||||||
.PadLeft(Indent3)
|
.PadLeft(Indent3)
|
||||||
.AppendFormat("return {0} == null ? null : new {1}({0});", destinationClassParameterName, model.ClassName)
|
.AppendFormat("return {0} == null ? null : new {1}({0});", sourceClassParameterName, model.ClassName)
|
||||||
|
.AppendClosingBracket(Indent2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StringBuilder GenerateSourceTypeExtensionMethod(this StringBuilder builder, MapModel model)
|
||||||
|
{
|
||||||
|
var sourceClassParameterName = model.SourceClassName.ToCamelCase();
|
||||||
|
|
||||||
|
return builder
|
||||||
|
.PadLeft(Indent2)
|
||||||
|
.AppendFormat("public static {0} To{0}(this {1} {2})", model.ClassName, model.SourceClassName, sourceClassParameterName)
|
||||||
|
.AppendOpeningBracket(Indent2)
|
||||||
|
.PadLeft(Indent3)
|
||||||
|
.AppendFormat("return {0} == null ? null : new {1}({0})", sourceClassParameterName, model.ClassName)
|
||||||
.AppendClosingBracket(Indent2);
|
.AppendClosingBracket(Indent2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,31 @@ using Bazaar;
|
||||||
compilation.SyntaxTrees.Last().ToString().ShouldStartWith(expectedResult.Trim());
|
compilation.SyntaxTrees.Last().ToString().ShouldStartWith(expectedResult.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void When_SourceTypeHasMatchingProperties_Should_GenerateToExtensionMethodOnSourceType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var source = GetSourceText();
|
||||||
|
|
||||||
|
const string expectedResult = @"
|
||||||
|
public static class BazExtensions
|
||||||
|
{
|
||||||
|
public static Foo ToFoo(this 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, string sourceClassNamespace = "Test")
|
private static string GetSourceText(bool includeAttributeNamespace = false, string sourceClassNamespace = "Test")
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
Loading…
Reference in New Issue