Skip to content

Commit

Permalink
fix: update IsImmutable to identify valid types on framework (#388)
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison committed Apr 30, 2023
1 parent 1ad8dca commit b9a1f19
Show file tree
Hide file tree
Showing 14 changed files with 772 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/Riok.Mapperly/Helpers/SymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal static class SymbolExtensions
symbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attributeSymbol));

internal static bool IsImmutable(this ISymbol symbol) =>
symbol is INamedTypeSymbol namedSymbol && (namedSymbol.IsReadOnly || namedSymbol.SpecialType == SpecialType.System_String);
symbol is INamedTypeSymbol namedSymbol && (namedSymbol.IsUnmanagedType || namedSymbol.SpecialType == SpecialType.System_String);

internal static bool IsAccessible(this ISymbol symbol, bool allowProtected = false) =>
symbol.DeclaredAccessibility.HasFlag(Accessibility.Internal)
Expand Down
37 changes: 37 additions & 0 deletions test/Riok.Mapperly.IntegrationTests/DeepCloningMapperTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading.Tasks;
using FluentAssertions;
using Riok.Mapperly.IntegrationTests.Mapper;
using Riok.Mapperly.IntegrationTests.Models;
using VerifyXunit;
using Xunit;

namespace Riok.Mapperly.IntegrationTests
{
[UsesVerify]
public class DeepCloningMapperTest : BaseMapperTest
{
[Fact]
public Task SnapshotGeneratedSource()
{
var path = GetGeneratedMapperFilePath(nameof(DeepCloningMapper));
return Verifier.VerifyFile(path);
}

[Fact]
public Task RunMappingShouldWork()
{
var model = NewTestObj();
var dto = DeepCloningMapper.Copy(model);
return Verifier.Verify(dto);
}

[Fact]
public void RunIdMappingShouldWork()
{
var source = new IdObject { IdValue = 20 };
var copy = DeepCloningMapper.Copy(source);
source.Should().NotBeSameAs(copy);
copy.IdValue.Should().Be(20);
}
}
}
16 changes: 16 additions & 0 deletions test/Riok.Mapperly.IntegrationTests/Mapper/DeepCloningMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Riok.Mapperly.Abstractions;
using Riok.Mapperly.IntegrationTests.Models;

namespace Riok.Mapperly.IntegrationTests.Mapper
{
[Mapper(UseDeepCloning = true)]
public static partial class DeepCloningMapper
{
public static partial IdObject Copy(IdObject src);

[MapperIgnoreSource(nameof(TestObject.IgnoredIntValue))]
[MapperIgnoreSource(nameof(TestObject.IgnoredStringValue))]
[MapperIgnoreSource(nameof(TestObject.ImmutableHashSetValue))]
public static partial TestObject Copy(TestObject src);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
CtorValue: 7,
CtorValue2: 100,
IntValue: 10,
IntInitOnlyValue: 3,
RequiredValue: 4,
StringValue: fooBar,
RenamedStringValue: fooBar2,
Flattening: {
IdValue: 10
},
NullableFlattening: {
IdValue: 100
},
UnflatteningIdValue: 20,
NullableUnflatteningIdValue: 200,
NestedNullable: {
IntValue: 100
},
NestedNullableTargetNotNullable: {},
StringNullableTargetNotNullable: fooBar3,
RecursiveObject: {
CtorValue: 5,
CtorValue2: 100,
RequiredValue: 4,
StringValue: ,
RenamedStringValue: ,
Flattening: {},
ImmutableArrayValue: null,
ImmutableQueueValue: [],
ImmutableStackValue: [],
EnumValue: Value10,
EnumName: Value30,
EnumReverseStringValue: DtoValue3
},
SourceTargetSameObjectType: {
CtorValue: 8,
CtorValue2: 100,
IntValue: 99,
RequiredValue: 98,
StringValue: ,
RenamedStringValue: ,
Flattening: {},
ImmutableArrayValue: null,
ImmutableQueueValue: [],
ImmutableStackValue: [],
EnumReverseStringValue:
},
NullableReadOnlyObjectCollection: [
{
IntValue: 10
},
{
IntValue: 20
}
],
StackValue: [
1,
2,
3
],
QueueValue: [
1,
2,
3
],
ImmutableArrayValue: [
1,
2,
3
],
ImmutableListValue: [
1,
2,
3
],
ImmutableQueueValue: [
1,
2,
3
],
ImmutableStackValue: [
1,
2,
3
],
ImmutableSortedSetValue: [
1,
2,
3
],
ImmutableDictionaryValue: {
1: 1,
2: 2,
3: 3
},
ImmutableSortedDictionaryValue: {
1: 1,
2: 2,
3: 3
},
EnumValue: Value10,
EnumName: Value10,
EnumRawValue: Value20,
EnumStringValue: Value30,
EnumReverseStringValue: DtoValue3,
SubObject: {
SubIntValue: 2,
BaseIntValue: 1
},
DateTimeValueTargetDateOnly: 2020-01-03 15:10:05 Utc,
DateTimeValueTargetTimeOnly: 2020-01-03 15:10:05 Utc
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#nullable enable
namespace Riok.Mapperly.IntegrationTests.Mapper
{
public static partial class DeepCloningMapper
{
public static partial global::Riok.Mapperly.IntegrationTests.Models.IdObject Copy(global::Riok.Mapperly.IntegrationTests.Models.IdObject src)
{
var target = new global::Riok.Mapperly.IntegrationTests.Models.IdObject();
target.IdValue = src.IdValue;
return target;
}

public static partial global::Riok.Mapperly.IntegrationTests.Models.TestObject Copy(global::Riok.Mapperly.IntegrationTests.Models.TestObject src)
{
var target = new global::Riok.Mapperly.IntegrationTests.Models.TestObject(src.CtorValue, ctorValue2: src.CtorValue2)
{
IntInitOnlyValue = src.IntInitOnlyValue,
RequiredValue = src.RequiredValue
};
if (src.NullableFlattening != null)
{
target.NullableFlattening = Copy(src.NullableFlattening);
}

if (src.NestedNullable != null)
{
target.NestedNullable = MapToTestObjectNested(src.NestedNullable);
}

if (src.NestedNullableTargetNotNullable != null)
{
target.NestedNullableTargetNotNullable = MapToTestObjectNested(src.NestedNullableTargetNotNullable);
}

if (src.RecursiveObject != null)
{
target.RecursiveObject = Copy(src.RecursiveObject);
}

if (src.SourceTargetSameObjectType != null)
{
target.SourceTargetSameObjectType = Copy(src.SourceTargetSameObjectType);
}

if (src.NullableReadOnlyObjectCollection != null)
{
target.NullableReadOnlyObjectCollection = global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(src.NullableReadOnlyObjectCollection, x => MapToTestObjectNested(x)));
}

if (src.SubObject != null)
{
target.SubObject = MapToInheritanceSubObject(src.SubObject);
}

target.IntValue = src.IntValue;
target.StringValue = src.StringValue;
target.RenamedStringValue = src.RenamedStringValue;
target.Flattening = Copy(src.Flattening);
target.UnflatteningIdValue = src.UnflatteningIdValue;
target.NullableUnflatteningIdValue = src.NullableUnflatteningIdValue;
target.StringNullableTargetNotNullable = src.StringNullableTargetNotNullable;
target.StackValue = new global::System.Collections.Generic.Stack<string>(src.StackValue);
target.QueueValue = new global::System.Collections.Generic.Queue<string>(src.QueueValue);
target.ImmutableArrayValue = global::System.Collections.Immutable.ImmutableArray.ToImmutableArray(src.ImmutableArrayValue);
target.ImmutableListValue = global::System.Collections.Immutable.ImmutableList.ToImmutableList(src.ImmutableListValue);
target.ImmutableQueueValue = global::System.Collections.Immutable.ImmutableQueue.CreateRange(src.ImmutableQueueValue);
target.ImmutableStackValue = global::System.Collections.Immutable.ImmutableStack.CreateRange(src.ImmutableStackValue);
target.ImmutableSortedSetValue = global::System.Collections.Immutable.ImmutableSortedSet.ToImmutableSortedSet(src.ImmutableSortedSetValue);
target.ImmutableDictionaryValue = global::System.Collections.Immutable.ImmutableDictionary.ToImmutableDictionary(src.ImmutableDictionaryValue);
target.ImmutableSortedDictionaryValue = global::System.Collections.Immutable.ImmutableSortedDictionary.ToImmutableSortedDictionary(src.ImmutableSortedDictionaryValue);
target.EnumValue = src.EnumValue;
target.EnumName = src.EnumName;
target.EnumRawValue = src.EnumRawValue;
target.EnumStringValue = src.EnumStringValue;
target.EnumReverseStringValue = src.EnumReverseStringValue;
target.DateTimeValueTargetDateOnly = src.DateTimeValueTargetDateOnly;
target.DateTimeValueTargetTimeOnly = src.DateTimeValueTargetTimeOnly;
return target;
}

private static global::Riok.Mapperly.IntegrationTests.Models.TestObjectNested MapToTestObjectNested(global::Riok.Mapperly.IntegrationTests.Models.TestObjectNested source)
{
var target = new global::Riok.Mapperly.IntegrationTests.Models.TestObjectNested();
target.IntValue = source.IntValue;
return target;
}

private static global::Riok.Mapperly.IntegrationTests.Models.InheritanceSubObject MapToInheritanceSubObject(global::Riok.Mapperly.IntegrationTests.Models.InheritanceSubObject source)
{
var target = new global::Riok.Mapperly.IntegrationTests.Models.InheritanceSubObject();
target.SubIntValue = source.SubIntValue;
target.BaseIntValue = source.BaseIntValue;
return target;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
CtorValue: 7,
CtorValue2: 100,
IntValue: 10,
IntInitOnlyValue: 3,
RequiredValue: 4,
StringValue: fooBar,
RenamedStringValue: fooBar2,
Flattening: {
IdValue: 10
},
NullableFlattening: {
IdValue: 100
},
UnflatteningIdValue: 20,
NullableUnflatteningIdValue: 200,
NestedNullable: {
IntValue: 100
},
NestedNullableTargetNotNullable: {},
StringNullableTargetNotNullable: fooBar3,
RecursiveObject: {
CtorValue: 5,
CtorValue2: 100,
RequiredValue: 4,
StringValue: ,
RenamedStringValue: ,
Flattening: {},
ImmutableArrayValue: null,
ImmutableQueueValue: [],
ImmutableStackValue: [],
EnumValue: Value10,
EnumName: Value30,
EnumReverseStringValue: DtoValue3
},
SourceTargetSameObjectType: {
CtorValue: 8,
CtorValue2: 100,
IntValue: 99,
RequiredValue: 98,
StringValue: ,
RenamedStringValue: ,
Flattening: {},
ImmutableArrayValue: null,
ImmutableQueueValue: [],
ImmutableStackValue: [],
EnumReverseStringValue:
},
NullableReadOnlyObjectCollection: [
{
IntValue: 10
},
{
IntValue: 20
}
],
StackValue: [
1,
2,
3
],
QueueValue: [
1,
2,
3
],
ImmutableArrayValue: [
1,
2,
3
],
ImmutableListValue: [
1,
2,
3
],
ImmutableQueueValue: [
1,
2,
3
],
ImmutableStackValue: [
1,
2,
3
],
ImmutableSortedSetValue: [
1,
2,
3
],
ImmutableDictionaryValue: {
1: 1,
2: 2,
3: 3
},
ImmutableSortedDictionaryValue: {
1: 1,
2: 2,
3: 3
},
EnumValue: Value10,
EnumName: Value10,
EnumRawValue: Value20,
EnumStringValue: Value30,
EnumReverseStringValue: DtoValue3,
SubObject: {
SubIntValue: 2,
BaseIntValue: 1
},
DateTimeValueTargetDateOnly: 2020-01-03 15:10:05 Utc,
DateTimeValueTargetTimeOnly: 2020-01-03 15:10:05 Utc
}
Loading

0 comments on commit b9a1f19

Please sign in to comment.