Skip to content

Commit

Permalink
feat: support partial base classes (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
latonz committed Mar 2, 2022
1 parent 85aba4b commit 900af9e
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 8 deletions.
Expand Up @@ -14,15 +14,19 @@ public static class UserMethodMappingBuilder
// extract user implemented and user defined mappings from mapper
foreach (var methodSymbol in ExtractMethods(mapperSymbol))
{
var mapping = BuilderUserDefinedMapping(ctx, methodSymbol) ?? BuildUserImplementedMapping(methodSymbol);
var mapping = BuilderUserDefinedMapping(ctx, methodSymbol) ?? BuildUserImplementedMapping(methodSymbol, false);
if (mapping != null)
yield return mapping;
}

// extract user implemented mappings from base methods
foreach (var method in ExtractBaseMethods(ctx.Compilation.ObjectType, mapperSymbol))
{
var mapping = BuildUserImplementedMapping(method);
// Partial method declarations are allowed for base classes,
// but still treated as user implemented methods,
// since the user should provide an implementation elsewhere.
// This is the case if a partial mapper class is extended.
var mapping = BuildUserImplementedMapping(method, true);
if (mapping != null)
yield return mapping;
}
Expand Down Expand Up @@ -58,9 +62,9 @@ private static IEnumerable<IMethodSymbol> ExtractBaseMethods(INamedTypeSymbol ob
&& !SymbolEqualityComparer.Default.Equals(x.ReceiverType, objectType));
}

private static TypeMapping? BuildUserImplementedMapping(IMethodSymbol m)
private static TypeMapping? BuildUserImplementedMapping(IMethodSymbol m, bool allowPartial)
{
return IsNewInstanceMappingMethod(m) && !m.IsAbstract && !m.IsPartialDefinition
return IsNewInstanceMappingMethod(m) && (allowPartial || !m.IsPartialDefinition)
? new UserImplementedMethodMapping(m)
: null;
}
Expand Down
11 changes: 7 additions & 4 deletions test/Riok.Mapperly.Tests/Mapping/UserMethodTest.cs
Expand Up @@ -106,17 +106,20 @@ public Task WithInvalidGenericSignatureShouldDiagnostic()
}

[Fact]
public Task WitClassBaseTypeShouldWork()
public Task WithClassBaseTypeShouldWork()
{
var source = @"
using System;
using System.Collections.Generic;
using Riok.Mapperly.Abstractions;
public class BaseMapper : BaseMapper3
[Mapper]
public partial class BaseMapper : BaseMapper3
{
public string MyMapping(int value)
=> $""my-to-string-{{value}}"";
protected partial short MyIntToShortMapping(int value);
}
public interface BaseMapper2 : BaseMapper3
Expand All @@ -137,8 +140,8 @@ public partial class MyMapper : BaseMapper, BaseMapper2
public partial B Map(A source);
}
class A { public int Value { get; set; } public int Value2 { get; set; } public int Value3 { get; set; } }
class B { public string Value { get; set; } public long Value2 { get; set; } public decimal Value3 { get; set; } }
class A { public int Value { get; set; } public int Value2 { get; set; } public int Value3 { get; set; } public int Value4 { get; set; } }
class B { public string Value { get; set; } public long Value2 { get; set; } public decimal Value3 { get; set; } public short Value4 { get; set; } }
";
return TestHelper.VerifyGenerator(source);
}
Expand Down
@@ -0,0 +1,9 @@
//HintName: BaseMapper.g.cs
#nullable enable
public partial class BaseMapper
{
protected partial short MyIntToShortMapping(int value)
{
return (short)value;
}
}
Expand Up @@ -8,6 +8,7 @@ public partial class MyMapper
target.Value = MyMapping(source.Value);
target.Value2 = ((BaseMapper2)this).MyMapping2(source.Value2);
target.Value3 = ((BaseMapper3)this).MyMapping3(source.Value3);
target.Value4 = MyIntToShortMapping(source.Value4);
return target;
}
}

0 comments on commit 900af9e

Please sign in to comment.