diff --git a/src/Riok.Mapperly.Abstractions/MapperAttribute.cs b/src/Riok.Mapperly.Abstractions/MapperAttribute.cs index dd472f63f80..4b842b610eb 100644 --- a/src/Riok.Mapperly.Abstractions/MapperAttribute.cs +++ b/src/Riok.Mapperly.Abstractions/MapperAttribute.cs @@ -101,5 +101,5 @@ public class MapperAttribute : Attribute /// /// Defines the maximum recursive depth that an IQueryable mapping will use. /// - public int RecursiveDepth { get; set; } = 8; + public int MaxRecursiveDepth { get; set; } = 8; } diff --git a/src/Riok.Mapperly.Abstractions/MapperMaxRecursiveDepthAttribute.cs b/src/Riok.Mapperly.Abstractions/MapperMaxRecursiveDepthAttribute.cs new file mode 100644 index 00000000000..1f1e6b230bc --- /dev/null +++ b/src/Riok.Mapperly.Abstractions/MapperMaxRecursiveDepthAttribute.cs @@ -0,0 +1,22 @@ +namespace Riok.Mapperly.Abstractions; + +/// +/// Defines the maximum recursive depth that an IQueryable mapping will use. +/// +[AttributeUsage(AttributeTargets.Method)] +public sealed class MapperMaxRecursiveDepthAttribute : Attribute +{ + /// + /// Defines the maximum recursive depth that an IQueryable mapping will use. + /// + /// The maximum recursive depth used when mapping IQueryable members. + public MapperMaxRecursiveDepthAttribute(int maxRecursiveDepth) + { + MaxRecursiveDepth = maxRecursiveDepth; + } + + /// + /// The maximum recursive depth used when mapping IQueryable members. + /// + public int MaxRecursiveDepth { get; } +} diff --git a/src/Riok.Mapperly.Abstractions/MapperRecursiveDepth.cs b/src/Riok.Mapperly.Abstractions/MapperRecursiveDepth.cs deleted file mode 100644 index 178e538254d..00000000000 --- a/src/Riok.Mapperly.Abstractions/MapperRecursiveDepth.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Riok.Mapperly.Abstractions; - -/// -/// Defines the strategy used when emitting warnings for unmapped members. -/// -[AttributeUsage(AttributeTargets.Method)] -public sealed class MapperRecursiveDepthAttribute : Attribute -{ - /// - /// Defines the maximum recursive depth that an IQueryable mapping will use. - /// - /// The maximum recursive depth used when mapping IQueryable members. - public MapperRecursiveDepthAttribute(int recursiveDepth) - { - RecursiveDepth = recursiveDepth; - } - - /// - /// The maximum recursive depth used when mapping IQueryable members. - /// - public int RecursiveDepth { get; } -} diff --git a/src/Riok.Mapperly/Configuration/MapperConfiguration.cs b/src/Riok.Mapperly/Configuration/MapperConfiguration.cs index a6be6915e07..394809b0b81 100644 --- a/src/Riok.Mapperly/Configuration/MapperConfiguration.cs +++ b/src/Riok.Mapperly/Configuration/MapperConfiguration.cs @@ -107,5 +107,5 @@ public record MapperConfiguration /// /// Defines the maximum recursive depth that an IQueryable mapping will use. /// - public int? RecursiveDepth { get; init; } + public int? MaxRecursiveDepth { get; init; } } diff --git a/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs b/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs index 51995a776dc..dd1195b806f 100644 --- a/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs +++ b/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs @@ -54,7 +54,8 @@ public static MapperAttribute Merge(MapperConfiguration mapperConfiguration, Map mapper.IncludedMembers = mapperConfiguration.IncludedMembers ?? defaultMapperConfiguration.IncludedMembers ?? mapper.IncludedMembers; - mapper.RecursiveDepth = mapperConfiguration.RecursiveDepth ?? defaultMapperConfiguration.RecursiveDepth ?? mapper.RecursiveDepth; + mapper.MaxRecursiveDepth = + mapperConfiguration.MaxRecursiveDepth ?? defaultMapperConfiguration.MaxRecursiveDepth ?? mapper.MaxRecursiveDepth; return mapper; } diff --git a/src/Riok.Mapperly/Configuration/MapperConfigurationReader.cs b/src/Riok.Mapperly/Configuration/MapperConfigurationReader.cs index d34f9bad8e2..6aa7d442168 100644 --- a/src/Riok.Mapperly/Configuration/MapperConfigurationReader.cs +++ b/src/Riok.Mapperly/Configuration/MapperConfigurationReader.cs @@ -34,7 +34,7 @@ MapperConfiguration defaultMapperConfiguration Array.Empty(), Mapper.IgnoreObsoleteMembersStrategy, Mapper.RequiredMappingStrategy, - Mapper.RecursiveDepth + Mapper.MaxRecursiveDepth ), Array.Empty() ); @@ -80,9 +80,10 @@ private PropertiesMappingConfiguration BuildPropertiesConfig(IMethodSymbol metho var requiredMapping = _dataAccessor.Access(method).FirstOrDefault() is not { } methodWarnUnmapped ? _defaultConfiguration.Properties.RequiredMappingStrategy : methodWarnUnmapped.RequiredMappingStrategy; - var recursiveDepth = _dataAccessor.Access(method).FirstOrDefault() is not { } methodRecursiveDepth - ? _defaultConfiguration.Properties.RecursiveDepth - : methodRecursiveDepth.RecursiveDepth; + var maxRecursiveDepth = _dataAccessor.Access(method).FirstOrDefault() + is not { } methodMaxRecursiveDepth + ? _defaultConfiguration.Properties.MaxRecursiveDepth + : methodMaxRecursiveDepth.MaxRecursiveDepth; return new PropertiesMappingConfiguration( ignoredSourceProperties, @@ -90,7 +91,7 @@ private PropertiesMappingConfiguration BuildPropertiesConfig(IMethodSymbol metho explicitMappings, ignoreObsolete, requiredMapping, - recursiveDepth + maxRecursiveDepth ); } diff --git a/src/Riok.Mapperly/Configuration/PropertiesMappingConfiguration.cs b/src/Riok.Mapperly/Configuration/PropertiesMappingConfiguration.cs index 25ba82d5f8d..3daf5919ca9 100644 --- a/src/Riok.Mapperly/Configuration/PropertiesMappingConfiguration.cs +++ b/src/Riok.Mapperly/Configuration/PropertiesMappingConfiguration.cs @@ -8,5 +8,5 @@ public record PropertiesMappingConfiguration( IReadOnlyCollection ExplicitMappings, IgnoreObsoleteMembersStrategy IgnoreObsoleteMembersStrategy, RequiredMappingStrategy RequiredMappingStrategy, - int RecursiveDepth + int MaxRecursiveDepth ); diff --git a/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs b/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs index 0cbd4fa8dc7..a69d685a79a 100644 --- a/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/InlineExpressionMappingBuilderContext.cs @@ -16,7 +16,7 @@ public class InlineExpressionMappingBuilderContext : MappingBuilderContext { private readonly MappingCollection _inlineExpressionMappings; private readonly MappingBuilderContext _parentContext; - private readonly ImmutableDictionary<(ISymbol, ISymbol), int> _parentTypes; + private readonly ImmutableDictionary _parentTypes; public InlineExpressionMappingBuilderContext(MappingBuilderContext ctx, ITypeSymbol sourceType, ITypeSymbol targetType) : this(ctx, (ctx.FindMapping(sourceType, targetType) as IUserMapping)?.Method, sourceType, targetType) { } @@ -34,13 +34,13 @@ ITypeSymbol target _parentTypes = ctx is InlineExpressionMappingBuilderContext inlineCtx ? inlineCtx._parentTypes - : ImmutableDictionary.Create<(ISymbol, ISymbol), int>(new SymbolTupleEqualityComparer()); + : ImmutableDictionary.Create(); } private InlineExpressionMappingBuilderContext( InlineExpressionMappingBuilderContext ctx, IMethodSymbol? userSymbol, - ImmutableDictionary<(ISymbol, ISymbol), int> parentTypes, + ImmutableDictionary parentTypes, ITypeSymbol source, ITypeSymbol target, bool clearDerivedTypes @@ -73,9 +73,9 @@ conversionType is not MappingConversionType.EnumToString and not MappingConversi public override INewInstanceMapping? FindMapping(ITypeSymbol sourceType, ITypeSymbol targetType) { // check for recursive loop returning null to prevent a loop or default when recursive limit is reached. - if (_parentTypes.TryGetValue((sourceType, targetType), out var count)) + if (_parentTypes.TryGetValue(new(sourceType, targetType), out var count)) { - return count >= Configuration.Properties.RecursiveDepth ? new DefaultMemberMapping(sourceType, targetType) : null; + return count >= Configuration.Properties.MaxRecursiveDepth ? new DefaultMemberMapping(sourceType, targetType) : null; } if (_inlineExpressionMappings.Find(sourceType, targetType) is { } mapping) @@ -170,9 +170,8 @@ protected override MappingBuilderContext ContextForMapping( MappingBuildingOptions options ) { - var newParentTypes = _parentTypes.TryGetValue((sourceType, targetType), out var count) - ? _parentTypes.SetItem((sourceType, targetType), count + 1) - : _parentTypes.SetItem((sourceType, targetType), 1); + var mappingRecursionCount = _parentTypes.GetValueOrDefault(new(sourceType, targetType)); + var newParentTypes = _parentTypes.SetItem(new(sourceType, targetType), mappingRecursionCount + 1); return new InlineExpressionMappingBuilderContext( this, userSymbol, diff --git a/src/Riok.Mapperly/Helpers/SymbolTupleEqualityComparer.cs b/src/Riok.Mapperly/Helpers/SymbolTupleEqualityComparer.cs deleted file mode 100644 index bae827a79c8..00000000000 --- a/src/Riok.Mapperly/Helpers/SymbolTupleEqualityComparer.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace Riok.Mapperly.Helpers; - -public class SymbolTupleEqualityComparer : IEqualityComparer<(ISymbol, ISymbol)> -{ - public bool Equals((ISymbol, ISymbol) x, (ISymbol, ISymbol) y) - { - return SymbolEqualityComparer.Default.Equals(x.Item1, y.Item1) && SymbolEqualityComparer.Default.Equals(x.Item2, y.Item2); - } - - public int GetHashCode((ISymbol, ISymbol) obj) - { - return HashCode.Combine( - SymbolEqualityComparer.Default.GetHashCode(obj.Item1), - SymbolEqualityComparer.Default.GetHashCode(obj.Item2) - ); - } -}