diff --git a/src/Riok.Mapperly/Configuration/AttributeDataAccessor.cs b/src/Riok.Mapperly/Configuration/AttributeDataAccessor.cs index 5e1ca3cbe9..afcfd9064a 100644 --- a/src/Riok.Mapperly/Configuration/AttributeDataAccessor.cs +++ b/src/Riok.Mapperly/Configuration/AttributeDataAccessor.cs @@ -8,18 +8,11 @@ namespace Riok.Mapperly.Configuration; /// /// Creates instances by resolving attribute data from provided symbols. /// -public class AttributeDataAccessor +public class AttributeDataAccessor(SymbolAccessor symbolAccessor) { private const string NameOfOperatorName = "nameof"; private const char FullNameOfPrefix = '@'; - private readonly SymbolAccessor _symbolAccessor; - - public AttributeDataAccessor(SymbolAccessor symbolAccessor) - { - _symbolAccessor = symbolAccessor; - } - public TData AccessSingle(ISymbol symbol) where TAttribute : Attribute where TData : notnull => Access(symbol).Single(); @@ -29,7 +22,7 @@ public TData AccessSingle(ISymbol symbol) where TData : notnull => Access(symbol).FirstOrDefault(); public bool HasAttribute(ISymbol symbol) - where TAttribute : Attribute => _symbolAccessor.HasAttribute(symbol); + where TAttribute : Attribute => symbolAccessor.HasAttribute(symbol); public IEnumerable Access(ISymbol symbol) where TAttribute : Attribute => Access(symbol); @@ -49,7 +42,7 @@ public IEnumerable Access(ISymbol symbol) where TAttribute : Attribute where TData : notnull { - var attrDatas = _symbolAccessor.GetAttributes(symbol); + var attrDatas = symbolAccessor.GetAttributes(symbol); foreach (var attrData in attrDatas) { yield return Access(attrData); diff --git a/src/Riok.Mapperly/Configuration/EnumConfiguration.cs b/src/Riok.Mapperly/Configuration/EnumConfiguration.cs index 054751b447..8ea51ae569 100644 --- a/src/Riok.Mapperly/Configuration/EnumConfiguration.cs +++ b/src/Riok.Mapperly/Configuration/EnumConfiguration.cs @@ -7,17 +7,12 @@ namespace Riok.Mapperly.Configuration; /// Represents the /// with enum values as typed constants. /// -public class EnumConfiguration +public class EnumConfiguration(EnumMappingStrategy strategy) { - public EnumConfiguration(EnumMappingStrategy strategy) - { - Strategy = strategy; - } - /// /// The strategy to be used to map enums. /// - public EnumMappingStrategy Strategy { get; } + public EnumMappingStrategy Strategy { get; } = strategy; /// /// Whether the case should be ignored during mappings. diff --git a/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityMember.cs b/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityMember.cs index cf4452daf6..7cbbd6bfc1 100644 --- a/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityMember.cs +++ b/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityMember.cs @@ -12,24 +12,15 @@ namespace Riok.Mapperly.Descriptors.Enumerables.EnsureCapacity; /// target.EnsureCapacity(source.Length + target.Count); /// /// -public class EnsureCapacityMember : EnsureCapacityInfo +public class EnsureCapacityMember(string targetAccessor, string sourceAccessor) : EnsureCapacityInfo { - private readonly string _targetAccessor; - private readonly string _sourceAccessor; - - public EnsureCapacityMember(string targetAccessor, string sourceAccessor) - { - _targetAccessor = targetAccessor; - _sourceAccessor = sourceAccessor; - } - public override StatementSyntax Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { return EnsureCapacityStatement( ctx.SyntaxFactory, target, - MemberAccess(ctx.Source, _sourceAccessor), - MemberAccess(target, _targetAccessor) + MemberAccess(ctx.Source, sourceAccessor), + MemberAccess(target, targetAccessor) ); } } diff --git a/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityNonEnumerated.cs b/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityNonEnumerated.cs index 091c6449d3..c7c09e33d2 100644 --- a/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityNonEnumerated.cs +++ b/src/Riok.Mapperly/Descriptors/Enumerables/EnsureCapacity/EnsureCapacityNonEnumerated.cs @@ -18,21 +18,13 @@ namespace Riok.Mapperly.Descriptors.Enumerables.EnsureCapacity; /// target.EnsureCapacity(sourceCount + target.Count); /// /// -public class EnsureCapacityNonEnumerated : EnsureCapacityInfo +public class EnsureCapacityNonEnumerated(string targetAccessor, IMethodSymbol getNonEnumeratedMethod) : EnsureCapacityInfo { private const string SourceCountVariableName = "sourceCount"; - private readonly string _targetAccessor; - private readonly IMethodSymbol _getNonEnumeratedMethod; - - public EnsureCapacityNonEnumerated(string targetAccessor, IMethodSymbol getNonEnumeratedMethod) - { - _targetAccessor = targetAccessor; - _getNonEnumeratedMethod = getNonEnumeratedMethod; - } public override StatementSyntax Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { - var targetCount = MemberAccess(target, _targetAccessor); + var targetCount = MemberAccess(target, targetAccessor); var countIdentifier = Identifier(ctx.NameBuilder.New(SourceCountVariableName)); var countIdentifierName = IdentifierName(countIdentifier); @@ -42,7 +34,7 @@ public override StatementSyntax Build(TypeMappingBuildContext ctx, ExpressionSyn var outVarArgument = Argument(DeclarationExpression(VarIdentifier, SingleVariableDesignation(countIdentifier))) .WithRefOrOutKeyword(TrailingSpacedToken(SyntaxKind.OutKeyword)); - var getNonEnumeratedInvocation = StaticInvocation(_getNonEnumeratedMethod, enumerableArgument, outVarArgument); + var getNonEnumeratedInvocation = StaticInvocation(getNonEnumeratedMethod, enumerableArgument, outVarArgument); var ensureCapacity = EnsureCapacityStatement(ctx.SyntaxFactory.AddIndentation(), target, countIdentifierName, targetCount); return ctx.SyntaxFactory.If(getNonEnumeratedInvocation, ensureCapacity); } diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/MembersContainerBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/MembersContainerBuilderContext.cs index da1b86e280..ee775e6b9d 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/MembersContainerBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/MembersContainerBuilderContext.cs @@ -8,14 +8,13 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext; /// An implementation. /// /// The type of mapping. -public class MembersContainerBuilderContext : MembersMappingBuilderContext, IMembersContainerBuilderContext +public class MembersContainerBuilderContext(MappingBuilderContext builderContext, T mapping) + : MembersMappingBuilderContext(builderContext, mapping), + IMembersContainerBuilderContext where T : IMemberAssignmentTypeMapping { private readonly Dictionary _nullDelegateMappings = new(); - public MembersContainerBuilderContext(MappingBuilderContext builderContext, T mapping) - : base(builderContext, mapping) { } - public void AddMemberAssignmentMapping(IMemberAssignmentMapping memberMapping) => AddMemberAssignmentMapping(Mapping, memberMapping); public void AddNullDelegateMemberAssignmentMapping(IMemberAssignmentMapping memberMapping) diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceBuilderContext.cs index f906fdce1b..cf34999962 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceBuilderContext.cs @@ -7,12 +7,11 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext; /// An implementation of . /// /// The type of the mapping. -public class NewInstanceBuilderContext : MembersMappingBuilderContext, INewInstanceBuilderContext +public class NewInstanceBuilderContext(MappingBuilderContext builderContext, T mapping) + : MembersMappingBuilderContext(builderContext, mapping), + INewInstanceBuilderContext where T : INewInstanceObjectMemberMapping { - public NewInstanceBuilderContext(MappingBuilderContext builderContext, T mapping) - : base(builderContext, mapping) { } - public void AddInitMemberMapping(MemberAssignmentMapping mapping) { SetSourceMemberMapped(mapping.SourcePath); diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceContainerBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceContainerBuilderContext.cs index 349fb8fcaa..725b809782 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceContainerBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewInstanceContainerBuilderContext.cs @@ -8,12 +8,11 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext; /// which supports containers (). /// /// -public class NewInstanceContainerBuilderContext : MembersContainerBuilderContext, INewInstanceBuilderContext +public class NewInstanceContainerBuilderContext(MappingBuilderContext builderContext, T mapping) + : MembersContainerBuilderContext(builderContext, mapping), + INewInstanceBuilderContext where T : INewInstanceObjectMemberMapping, IMemberAssignmentTypeMapping { - public NewInstanceContainerBuilderContext(MappingBuilderContext builderContext, T mapping) - : base(builderContext, mapping) { } - public void AddInitMemberMapping(MemberAssignmentMapping mapping) { SetSourceMemberMapped(mapping.SourcePath); diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleConstructorBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleConstructorBuilderContext.cs index 1d93bddf1b..6293643c64 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleConstructorBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleConstructorBuilderContext.cs @@ -7,12 +7,11 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext; /// An implementation of . /// /// The type of the mapping. -public class NewValueTupleConstructorBuilderContext : MembersMappingBuilderContext, INewValueTupleBuilderContext +public class NewValueTupleConstructorBuilderContext(MappingBuilderContext builderContext, T mapping) + : MembersMappingBuilderContext(builderContext, mapping), + INewValueTupleBuilderContext where T : INewValueTupleMapping { - public NewValueTupleConstructorBuilderContext(MappingBuilderContext builderContext, T mapping) - : base(builderContext, mapping) { } - public void AddTupleConstructorParameterMapping(ValueTupleConstructorParameterMapping mapping) { MemberConfigsByRootTargetName.Remove(mapping.Parameter.Name); diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleExpressionBuilderContext.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleExpressionBuilderContext.cs index 4fc59ba51e..2aca5007c4 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleExpressionBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/BuilderContext/NewValueTupleExpressionBuilderContext.cs @@ -7,12 +7,11 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext; /// An implementation of . /// /// The type of the mapping. -public class NewValueTupleExpressionBuilderContext : MembersContainerBuilderContext, INewValueTupleBuilderContext +public class NewValueTupleExpressionBuilderContext(MappingBuilderContext builderContext, T mapping) + : MembersContainerBuilderContext(builderContext, mapping), + INewValueTupleBuilderContext where T : INewValueTupleMapping, IMemberAssignmentTypeMapping { - public NewValueTupleExpressionBuilderContext(MappingBuilderContext builderContext, T mapping) - : base(builderContext, mapping) { } - public void AddTupleConstructorParameterMapping(ValueTupleConstructorParameterMapping mapping) { if (MemberConfigsByRootTargetName.TryGetValue(mapping.Parameter.Name, out var value)) diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MappingBodyBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MappingBodyBuilder.cs index 5f01f5bff2..9648885876 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MappingBodyBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MappingBodyBuilder.cs @@ -7,18 +7,11 @@ namespace Riok.Mapperly.Descriptors.MappingBodyBuilders; /// /// Builds bodies mappings (the body of the mapping methods). /// -public class MappingBodyBuilder +public class MappingBodyBuilder(MappingCollection mappings) { - private readonly MappingCollection _mappings; - - public MappingBodyBuilder(MappingCollection mappings) - { - _mappings = mappings; - } - public void BuildMappingBodies(CancellationToken cancellationToken) { - foreach (var (typeMapping, ctx) in _mappings.DequeueMappingsToBuildBody()) + foreach (var (typeMapping, ctx) in mappings.DequeueMappingsToBuildBody()) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/ExistingTargetMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/ExistingTargetMappingBuilder.cs index 3e5010dcf3..b7ec867ac2 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/ExistingTargetMappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/ExistingTargetMappingBuilder.cs @@ -2,7 +2,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; -public class ExistingTargetMappingBuilder +public class ExistingTargetMappingBuilder(MappingCollection mappings) { private delegate IExistingTargetMapping? BuildExistingTargetMapping(MappingBuilderContext context); @@ -16,16 +16,9 @@ public class ExistingTargetMappingBuilder NewInstanceObjectPropertyMappingBuilder.TryBuildExistingTargetMapping, }; - private readonly MappingCollection _mappings; - - public ExistingTargetMappingBuilder(MappingCollection mappings) - { - _mappings = mappings; - } - public IExistingTargetMapping? Find(TypeMappingKey mappingKey) { - return _mappings.FindExistingInstanceMapping(mappingKey); + return mappings.FindExistingInstanceMapping(mappingKey); } public IExistingTargetMapping? Build(MappingBuilderContext ctx, bool resultIsReusable) @@ -37,10 +30,10 @@ public ExistingTargetMappingBuilder(MappingCollection mappings) if (resultIsReusable) { - _mappings.AddExistingTargetMapping(mapping, ctx.MappingKey.Configuration); + mappings.AddExistingTargetMapping(mapping, ctx.MappingKey.Configuration); } - _mappings.EnqueueToBuildBody(mapping, ctx); + mappings.EnqueueToBuildBody(mapping, ctx); return mapping; } diff --git a/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs index 1f159c7107..82fc8a4d89 100644 --- a/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/MappingBuilders/MappingBuilder.cs @@ -3,7 +3,7 @@ namespace Riok.Mapperly.Descriptors.MappingBuilders; -public class MappingBuilder +public class MappingBuilder(MappingCollection mappings) { private delegate INewInstanceMapping? BuildMapping(MappingBuilderContext context); @@ -31,17 +31,10 @@ public class MappingBuilder NewInstanceObjectPropertyMappingBuilder.TryBuildMapping, }; - private readonly MappingCollection _mappings; - - public MappingBuilder(MappingCollection mappings) - { - _mappings = mappings; - } - /// - public IReadOnlyCollection UserMappings => _mappings.UserMappings; + public IReadOnlyCollection UserMappings => mappings.UserMappings; - public INewInstanceMapping? Find(TypeMappingKey mapping) => _mappings.Find(mapping); + public INewInstanceMapping? Find(TypeMappingKey mapping) => mappings.Find(mapping); public INewInstanceMapping? Build(MappingBuilderContext ctx, bool resultIsReusable) { @@ -52,10 +45,10 @@ public MappingBuilder(MappingCollection mappings) if (resultIsReusable) { - _mappings.AddNewInstanceMapping(mapping, ctx.MappingKey.Configuration); + mappings.AddNewInstanceMapping(mapping, ctx.MappingKey.Configuration); } - _mappings.EnqueueToBuildBody(mapping, ctx); + mappings.EnqueueToBuildBody(mapping, ctx); return mapping; } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs index 86613f96bf..d213e3e43c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs @@ -8,13 +8,10 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping from an array to an array of the same type by using Array.Clone. /// -public class ArrayCloneMapping : NewInstanceMapping +public class ArrayCloneMapping(ITypeSymbol sourceType, ITypeSymbol targetType) : NewInstanceMapping(sourceType, targetType) { private const string CloneMethodName = nameof(Array.Clone); - public ArrayCloneMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - : base(sourceType, targetType) { } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { return CastExpression(FullyQualifiedIdentifier(TargetType), InvocationExpression(MemberAccess(ctx.Source, CloneMethodName))); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForEachMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForEachMapping.cs index 575702c6bb..7e5801bc29 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForEachMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForEachMapping.cs @@ -10,30 +10,18 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// Represents an enumerable to array mapping which works by initialising an array, looping through the source, /// mapping each element and adding it to the target array. /// -public class ArrayForEachMapping : MethodMapping +public class ArrayForEachMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping elementMapping, + ITypeSymbol targetArrayElementType, + string countPropertyName +) : MethodMapping(sourceType, targetType) { private const string TargetVariableName = "target"; private const string LoopItemVariableName = "item"; private const string LoopCounterName = "i"; - private readonly INewInstanceMapping _elementMapping; - private readonly ITypeSymbol _targetArrayElementType; - private readonly string _countPropertyName; - - public ArrayForEachMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping elementMapping, - ITypeSymbol targetArrayElementType, - string countPropertyName - ) - : base(sourceType, targetType) - { - _elementMapping = elementMapping; - _targetArrayElementType = targetArrayElementType; - _countPropertyName = countPropertyName; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { var targetVariableName = ctx.NameBuilder.New(TargetVariableName); @@ -41,10 +29,10 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // var target = new T[source.Count]; var sourceLengthArrayRank = ArrayRankSpecifier( - SingletonSeparatedList(MemberAccess(ctx.Source, _countPropertyName)) + SingletonSeparatedList(MemberAccess(ctx.Source, countPropertyName)) ); var targetInitializationValue = CreateArray( - ArrayType(FullyQualifiedIdentifier(_targetArrayElementType)).WithRankSpecifiers(SingletonList(sourceLengthArrayRank)) + ArrayType(FullyQualifiedIdentifier(targetArrayElementType)).WithRankSpecifiers(SingletonList(sourceLengthArrayRank)) ); yield return ctx.SyntaxFactory.DeclareLocalVariable(targetVariableName, targetInitializationValue); @@ -53,7 +41,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // target[i] = Map(item); var (loopItemCtx, loopItemVariableName) = ctx.WithNewSource(LoopItemVariableName); - var convertedSourceItemExpression = _elementMapping.Build(loopItemCtx.AddIndentation()); + var convertedSourceItemExpression = elementMapping.Build(loopItemCtx.AddIndentation()); var assignment = Assignment( ElementAccess(IdentifierName(targetVariableName), IdentifierName(loopCounterVariableName)), diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs index 064d1196e2..ea75711b2b 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs @@ -5,27 +5,17 @@ namespace Riok.Mapperly.Descriptors.Mappings; -public class ArrayForMapping : MethodMapping +public class ArrayForMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping elementMapping, + ITypeSymbol targetArrayElementType +) : MethodMapping(sourceType, targetType) { private const string TargetVariableName = "target"; private const string LoopCounterName = "i"; private const string ArrayLengthProperty = nameof(Array.Length); - private readonly INewInstanceMapping _elementMapping; - private readonly ITypeSymbol _targetArrayElementType; - - public ArrayForMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping elementMapping, - ITypeSymbol targetArrayElementType - ) - : base(sourceType, targetType) - { - _elementMapping = elementMapping; - _targetArrayElementType = targetArrayElementType; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { var targetVariableName = ctx.NameBuilder.New(TargetVariableName); @@ -36,13 +26,13 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c SingletonSeparatedList(MemberAccess(ctx.Source, ArrayLengthProperty)) ); var targetInitializationValue = CreateArray( - ArrayType(FullyQualifiedIdentifier(_targetArrayElementType)).WithRankSpecifiers(SingletonList(sourceLengthArrayRank)) + ArrayType(FullyQualifiedIdentifier(targetArrayElementType)).WithRankSpecifiers(SingletonList(sourceLengthArrayRank)) ); yield return ctx.SyntaxFactory.DeclareLocalVariable(targetVariableName, targetInitializationValue); // target[i] = Map(source[i]); var forLoopBuilderCtx = ctx.WithSource(ElementAccess(ctx.Source, IdentifierName(loopCounterVariableName))); - var mappedIndexedSourceValue = _elementMapping.Build(forLoopBuilderCtx.AddIndentation()); + var mappedIndexedSourceValue = elementMapping.Build(forLoopBuilderCtx.AddIndentation()); var assignment = Assignment( ElementAccess(IdentifierName(targetVariableName), IdentifierName(loopCounterVariableName)), mappedIndexedSourceValue diff --git a/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs index d6ede730c3..5f9e24c646 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs @@ -8,19 +8,12 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a cast mapping. /// -public class CastMapping : NewInstanceMapping +public class CastMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping? delegateMapping = null) + : NewInstanceMapping(sourceType, targetType) { - private readonly INewInstanceMapping? _delegateMapping; - - public CastMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping? delegateMapping = null) - : base(sourceType, targetType) - { - _delegateMapping = delegateMapping; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { - var objToCast = _delegateMapping != null ? _delegateMapping.Build(ctx) : ctx.Source; + var objToCast = delegateMapping != null ? delegateMapping.Build(ctx) : ctx.Source; return CastExpression(FullyQualifiedIdentifier(TargetType), objToCast); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs index 79256ab9e7..1773dba296 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs @@ -7,10 +7,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping where the target type has the source as single ctor argument. /// -public class CtorMapping : NewInstanceMapping +public class CtorMapping(ITypeSymbol sourceType, ITypeSymbol targetType) : NewInstanceMapping(sourceType, targetType) { - public CtorMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - : base(sourceType, targetType) { } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => CreateInstance(TargetType, ctx.Source); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs index d8c1acbcea..ba6a57a382 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DelegateMapping.cs @@ -9,15 +9,8 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = Map(source); /// /// -public class DelegateMapping : NewInstanceMapping +public class DelegateMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) + : NewInstanceMapping(sourceType, targetType) { - private readonly INewInstanceMapping _delegateMapping; - - public DelegateMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) - : base(sourceType, targetType) - { - _delegateMapping = delegateMapping; - } - - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => _delegateMapping.Build(ctx); + public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => delegateMapping.Build(ctx); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs index 0fb5e0ee7a..4b8fdbba52 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeIfExpressionMapping.cs @@ -9,24 +9,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A derived type mapping maps one base type or interface to another /// by implementing a if with instance checks over known types and performs the provided mapping for each type. /// -public class DerivedTypeIfExpressionMapping : NewInstanceMapping +public class DerivedTypeIfExpressionMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + IReadOnlyCollection typeMappings +) : NewInstanceMapping(sourceType, targetType) { - private readonly IReadOnlyCollection _typeMappings; - - public DerivedTypeIfExpressionMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - IReadOnlyCollection typeMappings - ) - : base(sourceType, targetType) - { - _typeMappings = typeMappings; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { // source is A x ? MapToA(x) : - var typeExpressions = _typeMappings + var typeExpressions = typeMappings .Reverse() .Aggregate( DefaultLiteral(), diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs index bc4a55aa2a..cbe11bf1ab 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DerivedTypeSwitchMapping.cs @@ -10,18 +10,11 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A derived type mapping maps one base type or interface to another /// by implementing a type switch over known types and performs the provided mapping for each type. /// -public class DerivedTypeSwitchMapping : NewInstanceMapping +public class DerivedTypeSwitchMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IReadOnlyCollection typeMappings) + : NewInstanceMapping(sourceType, targetType) { private const string GetTypeMethodName = nameof(GetType); - private readonly IReadOnlyCollection _typeMappings; - - public DerivedTypeSwitchMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IReadOnlyCollection typeMappings) - : base(sourceType, targetType) - { - _typeMappings = typeMappings; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { // _ => throw new ArgumentException(msg, nameof(ctx.Source)), @@ -36,9 +29,7 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx) // source switch { A x => MapToADto(x), B x => MapToBDto(x) } var (typeArmContext, typeArmVariableName) = ctx.WithNewSource(); - var arms = _typeMappings - .Select(x => BuildSwitchArm(typeArmVariableName, x.SourceType, x.Build(typeArmContext))) - .Append(fallbackArm); + var arms = typeMappings.Select(x => BuildSwitchArm(typeArmVariableName, x.SourceType, x.Build(typeArmContext))).Append(fallbackArm); return ctx.SyntaxFactory.Switch(ctx.Source, arms); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs index d628563250..3cbf793fda 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/DirectAssignmentMapping.cs @@ -7,11 +7,8 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// Represents a direct assignment mapping. /// Source and target types need to be the same types. /// -public class DirectAssignmentMapping : NewInstanceMapping +public class DirectAssignmentMapping(ITypeSymbol type) : NewInstanceMapping(type, type) { - public DirectAssignmentMapping(ITypeSymbol type) - : base(type, type) { } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => ctx.Source; public override bool IsSynthetic => true; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumCastMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumCastMapping.cs index cdcfb073e0..b6a1a9042a 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumCastMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumCastMapping.cs @@ -9,12 +9,14 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// An enum cast mapping which casts the source to the target type and optionally checks whether the target is defined. /// If it is not defined an optional fallback value is used. /// -public class EnumCastMapping : CastMapping +public class EnumCastMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + EnumCastMapping.CheckDefinedMode checkDefinedMode, + IReadOnlyCollection targetEnumMembers, + EnumFallbackValueMapping fallback +) : CastMapping(sourceType, targetType) { - private readonly CheckDefinedMode _checkDefinedMode; - private readonly IReadOnlyCollection _targetEnumMembers; - private readonly EnumFallbackValueMapping _fallback; - public enum CheckDefinedMode { /// @@ -33,34 +35,20 @@ public enum CheckDefinedMode Flags } - public EnumCastMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - CheckDefinedMode checkDefinedMode, - IReadOnlyCollection targetEnumMembers, - EnumFallbackValueMapping fallback - ) - : base(sourceType, targetType) - { - _checkDefinedMode = checkDefinedMode; - _targetEnumMembers = targetEnumMembers; - _fallback = fallback; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { var casted = base.Build(ctx); - if (_checkDefinedMode == CheckDefinedMode.NoCheck) + if (checkDefinedMode == CheckDefinedMode.NoCheck) return casted; var valueDefinedCondition = BuildIsDefinedCondition(casted); - return Conditional(valueDefinedCondition, casted, _fallback.Build(ctx)); + return Conditional(valueDefinedCondition, casted, fallback.Build(ctx)); } private ExpressionSyntax BuildIsDefinedCondition(ExpressionSyntax convertedSourceValue) { - var allEnumMembers = _targetEnumMembers.Select(x => MemberAccess(FullyQualifiedIdentifier(TargetType), x.Name)); - return _checkDefinedMode switch + var allEnumMembers = targetEnumMembers.Select(x => MemberAccess(FullyQualifiedIdentifier(TargetType), x.Name)); + return checkDefinedMode switch { // (TargetEnum)v is TargetEnum.A or TargetEnum.B or ... CheckDefinedMode.Value @@ -72,7 +60,7 @@ private ExpressionSyntax BuildIsDefinedCondition(ExpressionSyntax convertedSourc convertedSourceValue, ParenthesizedExpression(BitwiseAnd(convertedSourceValue, ParenthesizedExpression(BitwiseOr(allEnumMembers)))) ), - _ => throw new ArgumentOutOfRangeException($"{nameof(_checkDefinedMode)} has an unknown value {_checkDefinedMode}") + _ => throw new ArgumentOutOfRangeException($"{nameof(checkDefinedMode)} has an unknown value {checkDefinedMode}") }; } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs index cc415523b0..3d95e85d55 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFallbackValueMapping.cs @@ -9,30 +9,21 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Enum fallback value which is used if no enum value matched. /// Either throws or returns the fallback value. /// -public class EnumFallbackValueMapping : NewInstanceMapping +public class EnumFallbackValueMapping( + ITypeSymbol source, + ITypeSymbol target, + INewInstanceMapping? fallbackMapping = null, + IFieldSymbol? fallbackMember = null +) : NewInstanceMapping(source, target) { - private readonly INewInstanceMapping? _fallbackMapping; - - public EnumFallbackValueMapping( - ITypeSymbol source, - ITypeSymbol target, - INewInstanceMapping? fallbackMapping = null, - IFieldSymbol? fallbackMember = null - ) - : base(source, target) - { - _fallbackMapping = fallbackMapping; - FallbackMember = fallbackMember; - } - - public IFieldSymbol? FallbackMember { get; } + public IFieldSymbol? FallbackMember { get; } = fallbackMember; public SwitchExpressionArmSyntax BuildDiscardArm(TypeMappingBuildContext ctx) => SwitchArm(DiscardPattern(), Build(ctx)); public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { - if (_fallbackMapping != null) - return _fallbackMapping.Build(ctx); + if (fallbackMapping != null) + return fallbackMapping.Build(ctx); if (FallbackMember == null) return ThrowArgumentOutOfRangeException(ctx.Source, $"The value of enum {SourceType.Name} is not supported"); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs index d038a40952..6064060ecc 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringParseMapping.cs @@ -11,32 +11,23 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Less efficient than /// but works in . /// -public class EnumFromStringParseMapping : NewInstanceMapping +public class EnumFromStringParseMapping(ITypeSymbol sourceType, ITypeSymbol targetType, bool genericParseMethodSupported, bool ignoreCase) + : NewInstanceMapping(sourceType, targetType) { private const string EnumClassName = "System.Enum"; private const string ParseMethodName = "Parse"; - private readonly bool _genericParseMethodSupported; - private readonly bool _ignoreCase; - - public EnumFromStringParseMapping(ITypeSymbol sourceType, ITypeSymbol targetType, bool genericParseMethodSupported, bool ignoreCase) - : base(sourceType, targetType) - { - _genericParseMethodSupported = genericParseMethodSupported; - _ignoreCase = ignoreCase; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { // System.Enum.Parse(source, ignoreCase) - if (_genericParseMethodSupported) + if (genericParseMethodSupported) { return GenericInvocation( EnumClassName, ParseMethodName, new[] { FullyQualifiedIdentifier(TargetType) }, ctx.Source, - BooleanLiteral(_ignoreCase) + BooleanLiteral(ignoreCase) ); } @@ -45,7 +36,7 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx) MemberAccess(EnumClassName, ParseMethodName), TypeOfExpression(FullyQualifiedIdentifier(TargetType)), ctx.Source, - BooleanLiteral(_ignoreCase) + BooleanLiteral(ignoreCase) ); return CastExpression(FullyQualifiedIdentifier(TargetType), enumParseInvocation); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringSwitchMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringSwitchMapping.cs index b9868c3689..3e94637792 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringSwitchMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumFromStringSwitchMapping.cs @@ -12,35 +12,23 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Uses a switch expression for performance reasons (in comparison to ). /// Optimized version of . /// -public class EnumFromStringSwitchMapping : MethodMapping +public class EnumFromStringSwitchMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + IEnumerable enumMembers, + bool ignoreCase, + EnumFallbackValueMapping fallbackMapping +) : MethodMapping(sourceType, targetType) { private const string IgnoreCaseSwitchDesignatedVariableName = "s"; private const string StringEqualsMethodName = nameof(string.Equals); private const string StringComparisonFullName = "System.StringComparison.OrdinalIgnoreCase"; - private readonly IEnumerable _enumMembers; - private readonly bool _ignoreCase; - private readonly EnumFallbackValueMapping _fallbackMapping; - - public EnumFromStringSwitchMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - IEnumerable enumMembers, - bool ignoreCase, - EnumFallbackValueMapping fallbackMapping - ) - : base(sourceType, targetType) - { - _enumMembers = enumMembers; - _ignoreCase = ignoreCase; - _fallbackMapping = fallbackMapping; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { // switch for each name to the enum value - var arms = _ignoreCase ? BuildArmsIgnoreCase(ctx) : _enumMembers.Select(BuildArm); - arms = arms.Append(_fallbackMapping.BuildDiscardArm(ctx)); + var arms = ignoreCase ? BuildArmsIgnoreCase(ctx) : enumMembers.Select(BuildArm); + arms = arms.Append(fallbackMapping.BuildDiscardArm(ctx)); var switchExpr = ctx.SyntaxFactory.Switch(ctx.Source, arms); yield return ctx.SyntaxFactory.Return(switchExpr); @@ -49,7 +37,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c private IEnumerable BuildArmsIgnoreCase(TypeMappingBuildContext ctx) { var ignoreCaseSwitchDesignatedVariableName = ctx.NameBuilder.New(IgnoreCaseSwitchDesignatedVariableName); - return _enumMembers.Select(f => BuildArmIgnoreCase(ignoreCaseSwitchDesignatedVariableName, f)); + return enumMembers.Select(f => BuildArmIgnoreCase(ignoreCaseSwitchDesignatedVariableName, f)); } private SwitchExpressionArmSyntax BuildArmIgnoreCase(string ignoreCaseSwitchDesignatedVariableName, IFieldSymbol field) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumNameMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumNameMapping.cs index 8f48d61e75..1c642c3357 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumNameMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumNameMapping.cs @@ -10,28 +10,18 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Uses a switch expression. Only supports defined enum values and no flags. /// The name has to match exactly. /// -public class EnumNameMapping : MethodMapping +public class EnumNameMapping( + ITypeSymbol source, + ITypeSymbol target, + IReadOnlyDictionary enumMemberMappings, + EnumFallbackValueMapping fallback +) : MethodMapping(source, target) { - private readonly IReadOnlyDictionary _enumMemberMappings; - private readonly EnumFallbackValueMapping _fallback; - - public EnumNameMapping( - ITypeSymbol source, - ITypeSymbol target, - IReadOnlyDictionary enumMemberMappings, - EnumFallbackValueMapping fallback - ) - : base(source, target) - { - _enumMemberMappings = enumMemberMappings; - _fallback = fallback; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { // switch for each name to the enum value // eg: Enum1.Value1 => Enum2.Value1, - var arms = _enumMemberMappings.Select(x => BuildArm(x.Key, x.Value)).Append(_fallback.BuildDiscardArm(ctx)); + var arms = enumMemberMappings.Select(x => BuildArm(x.Key, x.Value)).Append(fallback.BuildDiscardArm(ctx)); var switchExpr = ctx.SyntaxFactory.Switch(ctx.Source, arms); yield return ctx.SyntaxFactory.Return(switchExpr); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumToStringMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumToStringMapping.cs index 705b0d13bf..d001231b32 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumToStringMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/Enums/EnumToStringMapping.cs @@ -11,18 +11,11 @@ namespace Riok.Mapperly.Descriptors.Mappings.Enums; /// Uses a switch expression for performance reasons (in comparison to ). /// Only supports defined enum values and no flags. /// -public class EnumToStringMapping : MethodMapping +public class EnumToStringMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IEnumerable enumMembers) + : MethodMapping(sourceType, targetType) { private const string ToStringMethodName = nameof(Enum.ToString); - private readonly IEnumerable _enumMembers; - - public EnumToStringMapping(ITypeSymbol sourceType, ITypeSymbol targetType, IEnumerable enumMembers) - : base(sourceType, targetType) - { - _enumMembers = enumMembers; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { // fallback switch arm: _ => source.ToString() @@ -30,7 +23,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // switch for each name to the enum value // eg: Enum1.Value1 => "Value1" - var arms = _enumMembers.Select(BuildArm).Append(fallbackArm); + var arms = enumMembers.Select(BuildArm).Append(fallbackArm); var switchExpr = ctx.SyntaxFactory.Switch(ctx.Source, arms); yield return ctx.SyntaxFactory.Return(switchExpr); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs index 6446f67d68..fb4265b42d 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMapping.cs @@ -6,17 +6,11 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// /// A default implementation of . /// -public abstract class ExistingTargetMapping : IExistingTargetMapping +public abstract class ExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol targetType) : IExistingTargetMapping { - protected ExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - { - SourceType = sourceType; - TargetType = targetType; - } + public ITypeSymbol SourceType { get; } = sourceType; - public ITypeSymbol SourceType { get; } - - public ITypeSymbol TargetType { get; } + public ITypeSymbol TargetType { get; } = targetType; public virtual bool CallableByOtherMappings => true; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMappingMethodWrapper.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMappingMethodWrapper.cs index c6a59bec55..1fb93c2977 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMappingMethodWrapper.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ExistingTargetMappingMethodWrapper.cs @@ -6,25 +6,18 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// /// Wraps an as . /// -public abstract class ExistingTargetMappingMethodWrapper : MethodMapping +public abstract class ExistingTargetMappingMethodWrapper(IExistingTargetMapping mapping) + : MethodMapping(mapping.SourceType, mapping.TargetType) { private const string TargetVariableName = "target"; - private readonly IExistingTargetMapping _mapping; - - protected ExistingTargetMappingMethodWrapper(IExistingTargetMapping mapping) - : base(mapping.SourceType, mapping.TargetType) - { - _mapping = mapping; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { var targetVariableName = ctx.NameBuilder.New(TargetVariableName); yield return ctx.SyntaxFactory.DeclareLocalVariable(targetVariableName, CreateTargetInstance(ctx)); - foreach (var statement in _mapping.Build(ctx, IdentifierName(targetVariableName))) + foreach (var statement in mapping.Build(ctx, IdentifierName(targetVariableName))) { yield return statement; } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs index aa5f7df5dc..46f01b304b 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachAddEnumerableExistingTargetMapping.cs @@ -9,38 +9,26 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// Represents a foreach enumerable mapping which works by looping through the source, /// mapping each element and adding it to the target collection. /// -public class ForEachAddEnumerableExistingTargetMapping : ExistingTargetMapping +public class ForEachAddEnumerableExistingTargetMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping elementMapping, + string insertMethodName, + EnsureCapacityInfo? ensureCapacityBuilder +) : ExistingTargetMapping(sourceType, targetType) { private const string LoopItemVariableName = "item"; - private readonly INewInstanceMapping _elementMapping; - private readonly string _insertMethodName; - private readonly EnsureCapacityInfo? _ensureCapacityBuilder; - - public ForEachAddEnumerableExistingTargetMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping elementMapping, - string insertMethodName, - EnsureCapacityInfo? ensureCapacityBuilder - ) - : base(sourceType, targetType) - { - _elementMapping = elementMapping; - _insertMethodName = insertMethodName; - _ensureCapacityBuilder = ensureCapacityBuilder; - } - public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { - if (_ensureCapacityBuilder != null) + if (ensureCapacityBuilder != null) { - yield return _ensureCapacityBuilder.Build(ctx, target); + yield return ensureCapacityBuilder.Build(ctx, target); } var (loopItemCtx, loopItemVariableName) = ctx.WithNewSource(LoopItemVariableName); - var convertedSourceItemExpression = _elementMapping.Build(loopItemCtx); - var addMethod = MemberAccess(target, _insertMethodName); + var convertedSourceItemExpression = elementMapping.Build(loopItemCtx); + var addMethod = MemberAccess(target, insertMethodName); var body = Invocation(addMethod, convertedSourceItemExpression); yield return ctx.SyntaxFactory.ForEach(loopItemVariableName, ctx.Source, body); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs index 390020ff40..9180945bcb 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ForEachSetDictionaryExistingTargetMapping.cs @@ -10,39 +10,25 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// Represents a foreach dictionary mapping which works by looping through the source, /// mapping each element and set it to the target collection. /// -public class ForEachSetDictionaryExistingTargetMapping : ExistingTargetMapping +public class ForEachSetDictionaryExistingTargetMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping, + INamedTypeSymbol? explicitCast, + EnsureCapacityInfo? ensureCapacity +) : ExistingTargetMapping(sourceType, targetType) { private const string LoopItemVariableName = "item"; private const string ExplicitCastVariableName = "targetDict"; private const string KeyPropertyName = nameof(KeyValuePair.Key); private const string ValuePropertyName = nameof(KeyValuePair.Value); - private readonly INewInstanceMapping _keyMapping; - private readonly INewInstanceMapping _valueMapping; - private readonly INamedTypeSymbol? _explicitCast; - private readonly EnsureCapacityInfo? _ensureCapacity; - - public ForEachSetDictionaryExistingTargetMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping keyMapping, - INewInstanceMapping valueMapping, - INamedTypeSymbol? explicitCast, - EnsureCapacityInfo? ensureCapacity - ) - : base(sourceType, targetType) - { - _keyMapping = keyMapping; - _valueMapping = valueMapping; - _explicitCast = explicitCast; - _ensureCapacity = ensureCapacity; - } - public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { - if (_explicitCast != null) + if (explicitCast != null) { - var type = FullyQualifiedIdentifier(_explicitCast); + var type = FullyQualifiedIdentifier(explicitCast); var cast = CastExpression(type, target); var castedVariable = ctx.NameBuilder.New(ExplicitCastVariableName); @@ -51,15 +37,15 @@ public override IEnumerable Build(TypeMappingBuildContext ctx, yield return ctx.SyntaxFactory.DeclareLocalVariable(castedVariable, cast); } - if (_ensureCapacity != null) + if (ensureCapacity != null) { - yield return _ensureCapacity.Build(ctx, target); + yield return ensureCapacity.Build(ctx, target); } var loopItemVariableName = ctx.NameBuilder.New(LoopItemVariableName); - var convertedKeyExpression = _keyMapping.Build(ctx.WithSource(MemberAccess(loopItemVariableName, KeyPropertyName))); - var convertedValueExpression = _valueMapping.Build(ctx.WithSource(MemberAccess(loopItemVariableName, ValuePropertyName))); + var convertedKeyExpression = keyMapping.Build(ctx.WithSource(MemberAccess(loopItemVariableName, KeyPropertyName))); + var convertedValueExpression = valueMapping.Build(ctx.WithSource(MemberAccess(loopItemVariableName, ValuePropertyName))); var assignment = Assignment(ElementAccess(target, convertedKeyExpression), convertedValueExpression); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/NullDelegateExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/NullDelegateExistingTargetMapping.cs index ac18599d0d..66662831fb 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/NullDelegateExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/NullDelegateExistingTargetMapping.cs @@ -10,27 +10,19 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// Does not call the when /// the target or source is null. /// -public class NullDelegateExistingTargetMapping : ExistingTargetMapping +public class NullDelegateExistingTargetMapping( + ITypeSymbol nullableSourceType, + ITypeSymbol nullableTargetType, + IExistingTargetMapping delegateMapping +) : ExistingTargetMapping(nullableSourceType, nullableTargetType) { - private readonly IExistingTargetMapping _delegateMapping; - - public NullDelegateExistingTargetMapping( - ITypeSymbol nullableSourceType, - ITypeSymbol nullableTargetType, - IExistingTargetMapping delegateMapping - ) - : base(nullableSourceType, nullableTargetType) - { - _delegateMapping = delegateMapping; - } - public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { // if the source or target type is nullable, add a null guard. if (!SourceType.IsNullable() && !TargetType.IsNullable()) - return _delegateMapping.Build(ctx, target); + return delegateMapping.Build(ctx, target); - var body = _delegateMapping.Build(ctx.AddIndentation(), target).ToArray(); + var body = delegateMapping.Build(ctx.AddIndentation(), target).ToArray(); // if body is empty don't generate an if statement if (body.Length == 0) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs index 072ea33bf0..59465071e8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/ObjectMemberExistingTargetMapping.cs @@ -7,17 +7,14 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// Represents a complex object mapping implemented in its own method. /// Maps each property from the source to the target. /// -public class ObjectMemberExistingTargetMapping : MemberAssignmentMappingContainer, IExistingTargetMapping, IMemberAssignmentTypeMapping +public class ObjectMemberExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + : MemberAssignmentMappingContainer, + IExistingTargetMapping, + IMemberAssignmentTypeMapping { - public ObjectMemberExistingTargetMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - { - SourceType = sourceType; - TargetType = targetType; - } + public ITypeSymbol SourceType { get; } = sourceType; - public ITypeSymbol SourceType { get; } - - public ITypeSymbol TargetType { get; } + public ITypeSymbol TargetType { get; } = targetType; public bool CallableByOtherMappings => true; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/SourceObjectMemberDelegateExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/SourceObjectMemberDelegateExistingTargetMapping.cs index ad33991bc7..01066bb039 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/SourceObjectMemberDelegateExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ExistingTarget/SourceObjectMemberDelegateExistingTargetMapping.cs @@ -11,26 +11,16 @@ namespace Riok.Mapperly.Descriptors.Mappings.ExistingTarget; /// Map(source.Span, target); /// /// -public class SourceObjectMemberDelegateExistingTargetMapping : ExistingTargetMapping +public class SourceObjectMemberDelegateExistingTargetMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + string memberName, + IExistingTargetMapping delegateMapping +) : ExistingTargetMapping(sourceType, targetType) { - private readonly string _memberName; - private readonly IExistingTargetMapping _delegateMapping; - - public SourceObjectMemberDelegateExistingTargetMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - string memberName, - IExistingTargetMapping delegateMapping - ) - : base(sourceType, targetType) - { - _memberName = memberName; - _delegateMapping = delegateMapping; - } - public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { - var member = MemberAccess(ctx.Source, _memberName); - return _delegateMapping.Build(ctx.WithSource(member), target); + var member = MemberAccess(ctx.Source, memberName); + return delegateMapping.Build(ctx.WithSource(member), target); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs index a63fdd0dbe..be165dba4f 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ForEachSetDictionaryMapping.cs @@ -11,40 +11,31 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// Represents a foreach dictionary mapping which works by looping through the source, /// mapping each element and setting it to the target collection. /// -public class ForEachSetDictionaryMapping : ExistingTargetMappingMethodWrapper +public class ForEachSetDictionaryMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping, + bool sourceHasCount, + ITypeSymbol? typeToInstantiate = null, + ObjectFactory? objectFactory = null, + INamedTypeSymbol? explicitCast = null, + EnsureCapacityInfo? ensureCapacity = null +) + : ExistingTargetMappingMethodWrapper( + new ForEachSetDictionaryExistingTargetMapping(sourceType, targetType, keyMapping, valueMapping, explicitCast, ensureCapacity) + ) { private const string CountPropertyName = nameof(IDictionary.Count); - private readonly bool _sourceHasCount; - private readonly ObjectFactory? _objectFactory; - private readonly ITypeSymbol _typeToInstantiate; - - public ForEachSetDictionaryMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping keyMapping, - INewInstanceMapping valueMapping, - bool sourceHasCount, - ITypeSymbol? typeToInstantiate = null, - ObjectFactory? objectFactory = null, - INamedTypeSymbol? explicitCast = null, - EnsureCapacityInfo? ensureCapacity = null - ) - : base( - new ForEachSetDictionaryExistingTargetMapping(sourceType, targetType, keyMapping, valueMapping, explicitCast, ensureCapacity) - ) - { - _sourceHasCount = sourceHasCount; - _objectFactory = objectFactory; - _typeToInstantiate = typeToInstantiate ?? targetType; - } + private readonly ITypeSymbol _typeToInstantiate = typeToInstantiate ?? targetType; protected override ExpressionSyntax CreateTargetInstance(TypeMappingBuildContext ctx) { - if (_objectFactory != null) - return _objectFactory.CreateType(SourceType, _typeToInstantiate, ctx.Source); + if (objectFactory != null) + return objectFactory.CreateType(SourceType, _typeToInstantiate, ctx.Source); - if (_sourceHasCount) + if (sourceHasCount) return CreateInstance(_typeToInstantiate, MemberAccess(ctx.Source, CountPropertyName)); return CreateInstance(_typeToInstantiate); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs index aeb2838043..e74cc6f8b6 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqConstructorMapping.cs @@ -7,43 +7,31 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping where the target type accepts IEnumerable as a single argument. /// -public class LinqConstructorMapping : NewInstanceMapping +public class LinqConstructorMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INamedTypeSymbol targetTypeToConstruct, + INewInstanceMapping elementMapping, + string? selectMethod +) : NewInstanceMapping(sourceType, targetType) { - private readonly INamedTypeSymbol _targetTypeToConstruct; - private readonly INewInstanceMapping _elementMapping; - private readonly string? _selectMethod; - - public LinqConstructorMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INamedTypeSymbol targetTypeToConstruct, - INewInstanceMapping elementMapping, - string? selectMethod - ) - : base(sourceType, targetType) - { - _targetTypeToConstruct = targetTypeToConstruct; - _elementMapping = elementMapping; - _selectMethod = selectMethod; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { ExpressionSyntax mappedSource; // Select / Map if needed - if (_selectMethod != null) + if (selectMethod != null) { var (lambdaCtx, lambdaSourceName) = ctx.WithNewScopedSource(); - var sourceMapExpression = _elementMapping.Build(lambdaCtx); + var sourceMapExpression = elementMapping.Build(lambdaCtx); var convertLambda = Lambda(lambdaSourceName, sourceMapExpression); - mappedSource = Invocation(_selectMethod, ctx.Source, convertLambda); + mappedSource = Invocation(selectMethod, ctx.Source, convertLambda); } else { - mappedSource = _elementMapping.Build(ctx); + mappedSource = elementMapping.Build(ctx); } - return CreateInstance(_targetTypeToConstruct, mappedSource); + return CreateInstance(targetTypeToConstruct, mappedSource); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs index c7876cae62..1a863ee359 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqDictionaryMapping.cs @@ -7,46 +7,34 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping which works by using linq (select + collect). /// -public class LinqDictionaryMapping : NewInstanceMapping +public class LinqDictionaryMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + string collectMethod, + INewInstanceMapping keyMapping, + INewInstanceMapping valueMapping +) : NewInstanceMapping(sourceType, targetType) { private const string KeyPropertyName = nameof(KeyValuePair.Key); private const string ValuePropertyName = nameof(KeyValuePair.Value); - private readonly string _collectMethod; - private readonly INewInstanceMapping _keyMapping; - private readonly INewInstanceMapping _valueMapping; - - public LinqDictionaryMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - string collectMethod, - INewInstanceMapping keyMapping, - INewInstanceMapping valueMapping - ) - : base(sourceType, targetType) - { - _collectMethod = collectMethod; - _keyMapping = keyMapping; - _valueMapping = valueMapping; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { // if key and value types do not change then use a simple call // ie: source.ToImmutableDictionary(); - if (_keyMapping.IsSynthetic && _valueMapping.IsSynthetic) - return Invocation(_collectMethod, ctx.Source); + if (keyMapping.IsSynthetic && valueMapping.IsSynthetic) + return Invocation(collectMethod, ctx.Source); // create expressions mapping the key and value and then create the final expression // ie: source.ToImmutableDictionary(x => x.Key, x => (int)x.Value); var (keyLambdaCtx, keyLambdaParamName) = ctx.WithNewScopedSource(src => MemberAccess(src, KeyPropertyName)); - var keyMapExpression = _keyMapping.Build(keyLambdaCtx); + var keyMapExpression = keyMapping.Build(keyLambdaCtx); var keyExpression = Lambda(keyLambdaParamName, keyMapExpression); var (valueLambdaCtx, valueLambdaParamName) = ctx.WithNewScopedSource(src => MemberAccess(src, ValuePropertyName)); - var valueMapExpression = _valueMapping.Build(valueLambdaCtx); + var valueMapExpression = valueMapping.Build(valueLambdaCtx); var valueExpression = Lambda(valueLambdaParamName, valueMapExpression); - return Invocation(_collectMethod, ctx.Source, keyExpression, valueExpression); + return Invocation(collectMethod, ctx.Source, keyExpression, valueExpression); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs index 0e1b39d757..739310c2e5 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/LinqEnumerableMapping.cs @@ -7,43 +7,31 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents an enumerable mapping which works by using linq (select + collect). /// -public class LinqEnumerableMapping : NewInstanceMapping +public class LinqEnumerableMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + INewInstanceMapping elementMapping, + string? selectMethod, + string? collectMethod +) : NewInstanceMapping(sourceType, targetType) { - private readonly INewInstanceMapping _elementMapping; - private readonly string? _selectMethod; - private readonly string? _collectMethod; - - public LinqEnumerableMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - INewInstanceMapping elementMapping, - string? selectMethod, - string? collectMethod - ) - : base(sourceType, targetType) - { - _elementMapping = elementMapping; - _selectMethod = selectMethod; - _collectMethod = collectMethod; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { ExpressionSyntax mappedSource; // Select / Map if needed - if (_selectMethod != null) + if (selectMethod != null) { var (lambdaCtx, lambdaSourceName) = ctx.WithNewScopedSource(); - var sourceMapExpression = _elementMapping.Build(lambdaCtx); + var sourceMapExpression = elementMapping.Build(lambdaCtx); var convertLambda = Lambda(lambdaSourceName, sourceMapExpression); - mappedSource = Invocation(_selectMethod, ctx.Source, convertLambda); + mappedSource = Invocation(selectMethod, ctx.Source, convertLambda); } else { - mappedSource = _elementMapping.Build(ctx); + mappedSource = elementMapping.Build(ctx); } - return _collectMethod == null ? mappedSource : Invocation(_collectMethod, mappedSource); + return collectMethod == null ? mappedSource : Invocation(collectMethod, mappedSource); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ConstructorParameterMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ConstructorParameterMapping.cs index 61c84894ba..f8a4a61cac 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ConstructorParameterMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ConstructorParameterMapping.cs @@ -5,20 +5,17 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; -public class ConstructorParameterMapping +public class ConstructorParameterMapping( + IParameterSymbol parameter, + NullMemberMapping delegateMapping, + bool selfOrPreviousIsUnmappedOptional +) { - private readonly bool _selfOrPreviousIsUnmappedOptional; + private readonly bool _selfOrPreviousIsUnmappedOptional = selfOrPreviousIsUnmappedOptional; - public ConstructorParameterMapping(IParameterSymbol parameter, NullMemberMapping delegateMapping, bool selfOrPreviousIsUnmappedOptional) - { - DelegateMapping = delegateMapping; - Parameter = parameter; - _selfOrPreviousIsUnmappedOptional = selfOrPreviousIsUnmappedOptional; - } - - public IParameterSymbol Parameter { get; } + public IParameterSymbol Parameter { get; } = parameter; - public NullMemberMapping DelegateMapping { get; } + public NullMemberMapping DelegateMapping { get; } = delegateMapping; public ArgumentSyntax BuildArgument(TypeMappingBuildContext ctx) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMapping.cs index 3b4224dc41..8a74677ec8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMapping.cs @@ -9,20 +9,13 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// (eg. target.A = source.B) /// [DebuggerDisplay("MemberAssignmentMapping({SourcePath.FullName} => {TargetPath.FullName})")] -public class MemberAssignmentMapping : IMemberAssignmentMapping +public class MemberAssignmentMapping(SetterMemberPath targetPath, IMemberMapping mapping) : IMemberAssignmentMapping { - private readonly IMemberMapping _mapping; - private readonly SetterMemberPath _targetPath; - - public MemberAssignmentMapping(SetterMemberPath targetPath, IMemberMapping mapping) - { - _targetPath = targetPath; - _mapping = mapping; - } + private readonly IMemberMapping _mapping = mapping; public GetterMemberPath SourcePath => _mapping.SourcePath; - public MemberPath TargetPath => _targetPath; + public MemberPath TargetPath => targetPath; public IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) => ctx.SyntaxFactory.SingleStatement(BuildExpression(ctx, targetAccess)); @@ -32,7 +25,7 @@ public ExpressionSyntax BuildExpression(TypeMappingBuildContext ctx, ExpressionS var mappedValue = _mapping.Build(ctx); // target.SetValue(source.Value); or target.Value = source.Value; - return _targetPath.BuildAssignment(targetAccess, mappedValue); + return targetPath.BuildAssignment(targetAccess, mappedValue); } public override bool Equals(object? obj) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMappingContainer.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMappingContainer.cs index 87744146f1..4189c8e141 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMappingContainer.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberAssignmentMappingContainer.cs @@ -5,16 +5,10 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// /// A default implementation for . /// -public abstract class MemberAssignmentMappingContainer : IMemberAssignmentMappingContainer +public abstract class MemberAssignmentMappingContainer(IMemberAssignmentMappingContainer? parent = null) : IMemberAssignmentMappingContainer { private readonly HashSet _delegateMappings = new(); private readonly HashSet _childContainers = new(); - private readonly IMemberAssignmentMappingContainer? _parent; - - protected MemberAssignmentMappingContainer(IMemberAssignmentMappingContainer? parent = null) - { - _parent = parent; - } public virtual IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) { @@ -32,7 +26,7 @@ public void AddMemberMappingContainer(IMemberAssignmentMappingContainer containe } public bool HasMemberMappingContainer(IMemberAssignmentMappingContainer container) => - _childContainers.Contains(container) || _parent?.HasMemberMappingContainer(container) == true; + _childContainers.Contains(container) || parent?.HasMemberMappingContainer(container) == true; public void AddMemberMapping(IMemberAssignmentMapping mapping) { @@ -43,5 +37,5 @@ public void AddMemberMapping(IMemberAssignmentMapping mapping) } public bool HasMemberMapping(IMemberAssignmentMapping mapping) => - _delegateMappings.Contains(mapping) || _parent?.HasMemberMapping(mapping) == true; + _delegateMappings.Contains(mapping) || parent?.HasMemberMapping(mapping) == true; } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberExistingTargetMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberExistingTargetMapping.cs index 6fdc65503f..ea63c77563 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberExistingTargetMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberExistingTargetMapping.cs @@ -7,26 +7,17 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// /// A which maps to an existing target instance. /// -public class MemberExistingTargetMapping : IMemberAssignmentMapping +public class MemberExistingTargetMapping(IExistingTargetMapping delegateMapping, GetterMemberPath sourcePath, GetterMemberPath targetPath) + : IMemberAssignmentMapping { - private readonly IExistingTargetMapping _delegateMapping; - private readonly GetterMemberPath _targetPath; + public GetterMemberPath SourcePath { get; } = sourcePath; - public MemberExistingTargetMapping(IExistingTargetMapping delegateMapping, GetterMemberPath sourcePath, GetterMemberPath targetPath) - { - _delegateMapping = delegateMapping; - SourcePath = sourcePath; - _targetPath = targetPath; - } - - public GetterMemberPath SourcePath { get; } - - public MemberPath TargetPath => _targetPath; + public MemberPath TargetPath => targetPath; public IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) { var source = SourcePath.BuildAccess(ctx.Source); - var target = _targetPath.BuildAccess(targetAccess); - return _delegateMapping.Build(ctx.WithSource(source), target); + var target = targetPath.BuildAccess(targetAccess); + return delegateMapping.Build(ctx.WithSource(source), target); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs index 84a252afaf..0745b5c988 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberMapping.cs @@ -7,30 +7,18 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// Represents a simple implementation without any null handling. /// (eg. MapToD(source.A.B) or MapToD(source?.A?.B)). /// -public class MemberMapping : IMemberMapping +public class MemberMapping( + INewInstanceMapping delegateMapping, + GetterMemberPath sourcePath, + bool nullConditionalAccess, + bool addValuePropertyOnNullable +) : IMemberMapping { - private readonly INewInstanceMapping _delegateMapping; - private readonly bool _nullConditionalAccess; - private readonly bool _addValuePropertyOnNullable; - - public MemberMapping( - INewInstanceMapping delegateMapping, - GetterMemberPath sourcePath, - bool nullConditionalAccess, - bool addValuePropertyOnNullable - ) - { - _delegateMapping = delegateMapping; - SourcePath = sourcePath; - _nullConditionalAccess = nullConditionalAccess; - _addValuePropertyOnNullable = addValuePropertyOnNullable; - } - - public GetterMemberPath SourcePath { get; } + public GetterMemberPath SourcePath { get; } = sourcePath; public ExpressionSyntax Build(TypeMappingBuildContext ctx) { - ctx = ctx.WithSource(SourcePath.BuildAccess(ctx.Source, _addValuePropertyOnNullable, _nullConditionalAccess)); - return _delegateMapping.Build(ctx); + ctx = ctx.WithSource(SourcePath.BuildAccess(ctx.Source, addValuePropertyOnNullable, nullConditionalAccess)); + return delegateMapping.Build(ctx); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullAssignmentInitializerMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullAssignmentInitializerMapping.cs index f1c687d0dc..18c5243b3b 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullAssignmentInitializerMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullAssignmentInitializerMapping.cs @@ -9,14 +9,9 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// A member initializer which initializes null members to new objects. /// [DebuggerDisplay("MemberNullAssignmentInitializerMapping({_pathToInitialize} ??= new())")] -public class MemberNullAssignmentInitializerMapping : MemberAssignmentMappingContainer +public class MemberNullAssignmentInitializerMapping(SetterMemberPath pathToInitialize) : MemberAssignmentMappingContainer { - private readonly SetterMemberPath _pathToInitialize; - - public MemberNullAssignmentInitializerMapping(SetterMemberPath pathToInitialize) - { - _pathToInitialize = pathToInitialize; - } + private readonly SetterMemberPath _pathToInitialize = pathToInitialize; public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullDelegateAssignmentMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullDelegateAssignmentMapping.cs index df08150dda..efb8808778 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullDelegateAssignmentMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MemberNullDelegateAssignmentMapping.cs @@ -9,24 +9,15 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// a member mapping container, which performs a null check before the mappings. /// [DebuggerDisplay("MemberNullDelegateAssignmentMapping({_nullConditionalSourcePath} != null)")] -public class MemberNullDelegateAssignmentMapping : MemberAssignmentMappingContainer +public class MemberNullDelegateAssignmentMapping( + GetterMemberPath nullConditionalSourcePath, + IMemberAssignmentMappingContainer parent, + bool throwInsteadOfConditionalNullMapping, + bool needsNullSafeAccess +) : MemberAssignmentMappingContainer(parent) { - private readonly GetterMemberPath _nullConditionalSourcePath; - private readonly bool _throwInsteadOfConditionalNullMapping; - private readonly bool _needsNullSafeAccess; - - public MemberNullDelegateAssignmentMapping( - GetterMemberPath nullConditionalSourcePath, - IMemberAssignmentMappingContainer parent, - bool throwInsteadOfConditionalNullMapping, - bool needsNullSafeAccess - ) - : base(parent) - { - _needsNullSafeAccess = needsNullSafeAccess; - _nullConditionalSourcePath = nullConditionalSourcePath; - _throwInsteadOfConditionalNullMapping = throwInsteadOfConditionalNullMapping; - } + private readonly GetterMemberPath _nullConditionalSourcePath = nullConditionalSourcePath; + private readonly bool _throwInsteadOfConditionalNullMapping = throwInsteadOfConditionalNullMapping; public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) { @@ -34,7 +25,7 @@ public override IEnumerable Build(TypeMappingBuildContext ctx, // target.Value = Map(Source.Name); // else // throw ... - var sourceNullConditionalAccess = _nullConditionalSourcePath.BuildAccess(ctx.Source, false, _needsNullSafeAccess, true); + var sourceNullConditionalAccess = _nullConditionalSourcePath.BuildAccess(ctx.Source, false, needsNullSafeAccess, true); var nameofSourceAccess = _nullConditionalSourcePath.BuildAccess(ctx.Source, false, false, true); var condition = IsNotNull(sourceNullConditionalAccess); var conditionCtx = ctx.AddIndentation(); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MethodMemberNullAssignmentInitializerMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MethodMemberNullAssignmentInitializerMapping.cs index 0a2eafd22c..2909461e7c 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MethodMemberNullAssignmentInitializerMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/MethodMemberNullAssignmentInitializerMapping.cs @@ -10,22 +10,16 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// A member initializer which initializes null members to new objects. /// [DebuggerDisplay("MemberNullAssignmentInitializerMapping({_targetPathToInitialize} ??= new())")] -public class MethodMemberNullAssignmentInitializerMapping : MemberAssignmentMappingContainer +public class MethodMemberNullAssignmentInitializerMapping(SetterMemberPath targetPathToInitialize, GetterMemberPath sourcePathToInitialize) + : MemberAssignmentMappingContainer { - private readonly SetterMemberPath _targetPathToInitialize; - private readonly GetterMemberPath _sourcePathToInitialize; - - public MethodMemberNullAssignmentInitializerMapping(SetterMemberPath targetPathToInitialize, GetterMemberPath sourcePathToInitialize) - { - _targetPathToInitialize = targetPathToInitialize; - _sourcePathToInitialize = sourcePathToInitialize; - } + private readonly SetterMemberPath _targetPathToInitialize = targetPathToInitialize; public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax targetAccess) { // target.Value ?? new() var initializer = SyntaxFactoryHelper.Coalesce( - _sourcePathToInitialize.BuildAccess(targetAccess), + sourcePathToInitialize.BuildAccess(targetAccess), SyntaxFactory.ImplicitObjectCreationExpression() ); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs index bc159fdd74..af16a1efe8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/NullMemberMapping.cs @@ -12,29 +12,18 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; /// (eg. source?.A?.B ?? null-substitute or source?.A?.B != null ? MapToD(source.A.B) : null-substitute) /// [DebuggerDisplay("NullMemberMapping({SourcePath}: {_delegateMapping})")] -public class NullMemberMapping : IMemberMapping +public class NullMemberMapping( + INewInstanceMapping delegateMapping, + GetterMemberPath sourcePath, + ITypeSymbol targetType, + NullFallbackValue nullFallback, + bool useNullConditionalAccess +) : IMemberMapping { - private readonly INewInstanceMapping _delegateMapping; - private readonly ITypeSymbol _targetType; - private readonly NullFallbackValue _nullFallback; - private readonly bool _useNullConditionalAccess; + private readonly INewInstanceMapping _delegateMapping = delegateMapping; + private readonly NullFallbackValue _nullFallback = nullFallback; - public NullMemberMapping( - INewInstanceMapping delegateMapping, - GetterMemberPath sourcePath, - ITypeSymbol targetType, - NullFallbackValue nullFallback, - bool useNullConditionalAccess - ) - { - SourcePath = sourcePath; - _delegateMapping = delegateMapping; - _nullFallback = nullFallback; - _useNullConditionalAccess = useNullConditionalAccess; - _targetType = targetType; - } - - public GetterMemberPath SourcePath { get; } + public GetterMemberPath SourcePath { get; } = sourcePath; public ExpressionSyntax Build(TypeMappingBuildContext ctx) { @@ -53,22 +42,22 @@ public ExpressionSyntax Build(TypeMappingBuildContext ctx) // source.A?.B == null ? : Map(source.A.B.Value) // use simplified coalesce expression for synthetic mappings: // source.A?.B ?? - if (_delegateMapping.IsSynthetic && (_useNullConditionalAccess || !SourcePath.IsAnyObjectPathNullable())) + if (_delegateMapping.IsSynthetic && (useNullConditionalAccess || !SourcePath.IsAnyObjectPathNullable())) { var nullConditionalSourceAccess = SourcePath.BuildAccess(ctx.Source, nullConditional: true); var nameofSourceAccess = SourcePath.BuildAccess(ctx.Source, nullConditional: false); var mapping = _delegateMapping.Build(ctx.WithSource(nullConditionalSourceAccess)); - return _nullFallback == NullFallbackValue.Default && _targetType.IsNullable() + return _nullFallback == NullFallbackValue.Default && targetType.IsNullable() ? mapping - : Coalesce(mapping, NullSubstitute(_targetType, nameofSourceAccess, _nullFallback)); + : Coalesce(mapping, NullSubstitute(targetType, nameofSourceAccess, _nullFallback)); } - var notNullCondition = _useNullConditionalAccess + var notNullCondition = useNullConditionalAccess ? IsNotNull(SourcePath.BuildAccess(ctx.Source, nullConditional: true, skipTrailingNonNullable: true)) : SourcePath.BuildNonNullConditionWithoutConditionalAccess(ctx.Source)!; var sourceMemberAccess = SourcePath.BuildAccess(ctx.Source, true); ctx = ctx.WithSource(sourceMemberAccess); - return Conditional(notNullCondition, _delegateMapping.Build(ctx), NullSubstitute(_targetType, sourceMemberAccess, _nullFallback)); + return Conditional(notNullCondition, _delegateMapping.Build(ctx), NullSubstitute(targetType, sourceMemberAccess, _nullFallback)); } protected bool Equals(NullMemberMapping other) => diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeFieldAccessor.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeFieldAccessor.cs index f8ee2bcd62..ecf8d03651 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeFieldAccessor.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeFieldAccessor.cs @@ -16,23 +16,15 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings.UnsafeAccess; /// public extern static int GetValue(this global::MyClass source); /// /// -public class UnsafeFieldAccessor : IUnsafeAccessor +public class UnsafeFieldAccessor(IFieldSymbol value, string methodName) : IUnsafeAccessor { private const string DefaultTargetParameterName = "target"; - private readonly string _targetType; - private readonly string _result; - private readonly string _memberName; + private readonly string _targetType = value.ContainingType.FullyQualifiedIdentifierName(); + private readonly string _result = value.Type.FullyQualifiedIdentifierName(); + private readonly string _memberName = value.Name; - public UnsafeFieldAccessor(IFieldSymbol value, string methodName) - { - MethodName = methodName; - _targetType = value.ContainingType.FullyQualifiedIdentifierName(); - _result = value.Type.FullyQualifiedIdentifierName(); - _memberName = value.Name; - } - - public string MethodName { get; } + public string MethodName { get; } = methodName; public MethodDeclarationSyntax BuildMethod(SourceEmitterContext ctx) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeGetPropertyAccessor.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeGetPropertyAccessor.cs index 683838ca1a..013586c4f0 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeGetPropertyAccessor.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeGetPropertyAccessor.cs @@ -15,23 +15,15 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings.UnsafeAccess; /// public extern static int GetValue(this global::MyClass source); /// /// -public class UnsafeGetPropertyAccessor : IUnsafeAccessor +public class UnsafeGetPropertyAccessor(IPropertySymbol result, string methodName) : IUnsafeAccessor { private const string DefaultSourceParameterName = "source"; - private readonly string _result; - private readonly string _sourceType; - private readonly string _memberName; + private readonly string _result = result.Type.FullyQualifiedIdentifierName(); + private readonly string _sourceType = result.ContainingType.FullyQualifiedIdentifierName(); + private readonly string _memberName = result.Name; - public UnsafeGetPropertyAccessor(IPropertySymbol result, string methodName) - { - _sourceType = result.ContainingType.FullyQualifiedIdentifierName(); - _result = result.Type.FullyQualifiedIdentifierName(); - _memberName = result.Name; - MethodName = methodName; - } - - public string MethodName { get; } + public string MethodName { get; } = methodName; public MethodDeclarationSyntax BuildMethod(SourceEmitterContext ctx) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeSetPropertyAccessor.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeSetPropertyAccessor.cs index 1a2011fad0..d5126105ca 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeSetPropertyAccessor.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/UnsafeAccess/UnsafeSetPropertyAccessor.cs @@ -16,24 +16,16 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings.UnsafeAccess; /// public extern static void SetValue(this global::MyClass source, int value); /// /// -public class UnsafeSetPropertyAccessor : IUnsafeAccessor +public class UnsafeSetPropertyAccessor(IPropertySymbol value, string methodName) : IUnsafeAccessor { private const string DefaultTargetParameterName = "target"; private const string DefaultValueParameterName = "value"; - private readonly string _targetType; - private readonly string _valueType; - private readonly string _memberName; + private readonly string _targetType = value.ContainingType.FullyQualifiedIdentifierName(); + private readonly string _valueType = value.Type.FullyQualifiedIdentifierName(); + private readonly string _memberName = value.Name; - public UnsafeSetPropertyAccessor(IPropertySymbol value, string methodName) - { - MethodName = methodName; - _targetType = value.ContainingType.FullyQualifiedIdentifierName(); - _valueType = value.Type.FullyQualifiedIdentifierName(); - _memberName = value.Name; - } - - public string MethodName { get; } + public string MethodName { get; } = methodName; public MethodDeclarationSyntax BuildMethod(SourceEmitterContext ctx) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ValueTupleConstructorParameterMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ValueTupleConstructorParameterMapping.cs index 1c0b659eb7..83e44edb2e 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ValueTupleConstructorParameterMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/ValueTupleConstructorParameterMapping.cs @@ -5,17 +5,11 @@ namespace Riok.Mapperly.Descriptors.Mappings.MemberMappings; -public class ValueTupleConstructorParameterMapping +public class ValueTupleConstructorParameterMapping(IFieldSymbol parameter, NullMemberMapping delegateMapping) { - public ValueTupleConstructorParameterMapping(IFieldSymbol parameter, NullMemberMapping delegateMapping) - { - DelegateMapping = delegateMapping; - Parameter = parameter; - } - - public IFieldSymbol Parameter { get; } + public IFieldSymbol Parameter { get; } = parameter; - public NullMemberMapping DelegateMapping { get; } + public NullMemberMapping DelegateMapping { get; } = delegateMapping; public ArgumentSyntax BuildArgument(TypeMappingBuildContext ctx, bool emitFieldName) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs index 3968fc0f23..87a733f29b 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceMapping.cs @@ -6,17 +6,11 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// [DebuggerDisplay("{GetType().Name}({SourceType} => {TargetType})")] -public abstract class NewInstanceMapping : INewInstanceMapping +public abstract class NewInstanceMapping(ITypeSymbol sourceType, ITypeSymbol targetType) : INewInstanceMapping { - protected NewInstanceMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - { - SourceType = sourceType; - TargetType = targetType; - } + public ITypeSymbol SourceType { get; } = sourceType; - public ITypeSymbol SourceType { get; } - - public ITypeSymbol TargetType { get; } + public ITypeSymbol TargetType { get; } = targetType; public virtual MappingBodyBuildingPriority BodyBuildingPriority => MappingBodyBuildingPriority.Default; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectFactoryMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectFactoryMemberMapping.cs index 1c93e789d4..82f11afe39 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectFactoryMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectFactoryMemberMapping.cs @@ -9,29 +9,20 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// An object mapping creating the target instance via an object factory. /// -public class NewInstanceObjectFactoryMemberMapping : ObjectMemberMethodMapping +public class NewInstanceObjectFactoryMemberMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + ObjectFactory objectFactory, + bool enableReferenceHandling +) : ObjectMemberMethodMapping(sourceType, targetType) { private const string TargetVariableName = "target"; - private readonly ObjectFactory _objectFactory; - private readonly bool _enableReferenceHandling; - - public NewInstanceObjectFactoryMemberMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - ObjectFactory objectFactory, - bool enableReferenceHandling - ) - : base(sourceType, targetType) - { - _objectFactory = objectFactory; - _enableReferenceHandling = enableReferenceHandling; - } public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { var targetVariableName = ctx.NameBuilder.New(TargetVariableName); - if (_enableReferenceHandling) + if (enableReferenceHandling) { // TryGetReference yield return ReferenceHandlingSyntaxFactoryHelper.TryGetReference(ctx, this); @@ -40,12 +31,12 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // var target = CreateMyObject(); yield return ctx.SyntaxFactory.DeclareLocalVariable( targetVariableName, - _objectFactory.CreateType(SourceType, TargetType, ctx.Source) + objectFactory.CreateType(SourceType, TargetType, ctx.Source) ); // set the reference as soon as it is created, // as property mappings could refer to the same instance. - if (_enableReferenceHandling) + if (enableReferenceHandling) { // SetReference yield return ctx.SyntaxFactory.ExpressionStatement( diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs index d4ba5119ee..5c1b32fabf 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMapping.cs @@ -10,14 +10,13 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// mapping properties via ctor, object initializer but not by assigning. /// /// -public class NewInstanceObjectMemberMapping : NewInstanceMapping, INewInstanceObjectMemberMapping +public class NewInstanceObjectMemberMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + : NewInstanceMapping(sourceType, targetType), + INewInstanceObjectMemberMapping { private readonly HashSet _constructorPropertyMappings = new(); private readonly HashSet _initPropertyMappings = new(); - public NewInstanceObjectMemberMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - : base(sourceType, targetType) { } - public void AddConstructorParameterMapping(ConstructorParameterMapping mapping) => _constructorPropertyMappings.Add(mapping); public void AddInitMemberMapping(MemberAssignmentMapping mapping) => _initPropertyMappings.Add(mapping); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMethodMapping.cs index d3c0550818..a6e3e63131 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewInstanceObjectMemberMethodMapping.cs @@ -11,18 +11,13 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// An object mapping creating the target instance via a new() call, /// mapping properties via ctor, object initializer and by assigning. /// -public class NewInstanceObjectMemberMethodMapping : ObjectMemberMethodMapping, INewInstanceObjectMemberMapping +public class NewInstanceObjectMemberMethodMapping(ITypeSymbol sourceType, ITypeSymbol targetType, bool enableReferenceHandling) + : ObjectMemberMethodMapping(sourceType, targetType), + INewInstanceObjectMemberMapping { private const string TargetVariableName = "target"; private readonly HashSet _constructorPropertyMappings = new(); private readonly HashSet _initPropertyMappings = new(); - private readonly bool _enableReferenceHandling; - - public NewInstanceObjectMemberMethodMapping(ITypeSymbol sourceType, ITypeSymbol targetType, bool enableReferenceHandling) - : base(sourceType, targetType) - { - _enableReferenceHandling = enableReferenceHandling; - } public void AddConstructorParameterMapping(ConstructorParameterMapping mapping) => _constructorPropertyMappings.Add(mapping); @@ -32,7 +27,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c { var targetVariableName = ctx.NameBuilder.New(TargetVariableName); - if (_enableReferenceHandling) + if (enableReferenceHandling) { // TryGetReference yield return ReferenceHandlingSyntaxFactoryHelper.TryGetReference(ctx, this); @@ -55,7 +50,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // set the reference as soon as it is created, // as property mappings could refer to the same instance. - if (_enableReferenceHandling) + if (enableReferenceHandling) { // SetReference yield return ctx.SyntaxFactory.ExpressionStatement( diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs index 652d641f28..63e7f2559e 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleConstructorMapping.cs @@ -10,14 +10,13 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// mapping properties via ctor, but not by assigning. /// /// -public class NewValueTupleConstructorMapping : NewInstanceMapping, INewValueTupleMapping +public class NewValueTupleConstructorMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + : NewInstanceMapping(sourceType, targetType), + INewValueTupleMapping { private const string ValueTupleName = "global::System.ValueTuple"; private readonly HashSet _constructorPropertyMappings = new(); - public NewValueTupleConstructorMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - : base(sourceType, targetType) { } - public void AddConstructorParameterMapping(ValueTupleConstructorParameterMapping mapping) => _constructorPropertyMappings.Add(mapping); public override ExpressionSyntax Build(TypeMappingBuildContext ctx) diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleExpressionMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleExpressionMapping.cs index 86d435ac55..2fcaf66ad5 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleExpressionMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NewValueTupleExpressionMapping.cs @@ -11,24 +11,19 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// mapping properties via ctor, not by assigning. /// /// -public class NewValueTupleExpressionMapping : ObjectMemberMethodMapping, INewValueTupleMapping +public class NewValueTupleExpressionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, int argumentCount) + : ObjectMemberMethodMapping(sourceType, targetType), + INewValueTupleMapping { - private readonly int _argumentCount; private const string TargetVariableName = "target"; private readonly HashSet _constructorPropertyMappings = new(); - public NewValueTupleExpressionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, int argumentCount) - : base(sourceType, targetType) - { - _argumentCount = argumentCount; - } - public void AddConstructorParameterMapping(ValueTupleConstructorParameterMapping mapping) => _constructorPropertyMappings.Add(mapping); public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { // generate error if constructor argument don't match - if (_constructorPropertyMappings.Count != _argumentCount) + if (_constructorPropertyMappings.Count != argumentCount) { return ctx.SyntaxFactory.ThrowMappingNotImplementedExceptionStatement(); } @@ -39,7 +34,7 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx) public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { // generate error if constructor argument don't match - if (_constructorPropertyMappings.Count != _argumentCount) + if (_constructorPropertyMappings.Count != argumentCount) { yield return ctx.SyntaxFactory.ExpressionStatement(ctx.SyntaxFactory.ThrowMappingNotImplementedExceptionStatement()); yield break; diff --git a/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMethodMapping.cs index 3037c3484d..ac0aa34de8 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/NullDelegateMethodMapping.cs @@ -9,39 +9,29 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// Null aware delegate mapping for s. /// Abstracts handling null values of the delegated mapping. /// -public class NullDelegateMethodMapping : MethodMapping +public class NullDelegateMethodMapping( + ITypeSymbol nullableSourceType, + ITypeSymbol nullableTargetType, + MethodMapping delegateMapping, + NullFallbackValue nullFallbackValue +) : MethodMapping(nullableSourceType, nullableTargetType) { - private readonly MethodMapping _delegateMapping; - private readonly NullFallbackValue _nullFallbackValue; - - public NullDelegateMethodMapping( - ITypeSymbol nullableSourceType, - ITypeSymbol nullableTargetType, - MethodMapping delegateMapping, - NullFallbackValue nullFallbackValue - ) - : base(nullableSourceType, nullableTargetType) - { - _delegateMapping = delegateMapping; - _nullFallbackValue = nullFallbackValue; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { - var body = _delegateMapping.BuildBody(ctx); + var body = delegateMapping.BuildBody(ctx); return AddPreNullHandling(ctx, body); } private IEnumerable AddPreNullHandling(TypeMappingBuildContext ctx, IEnumerable body) { - if (!SourceType.IsNullable() || _delegateMapping.SourceType.IsNullable()) + if (!SourceType.IsNullable() || delegateMapping.SourceType.IsNullable()) return body; // source is nullable and the mapping method cannot handle nulls, // call mapping only if source is not null. // if (source == null) // return ; - var fallbackExpression = NullSubstitute(TargetType, ctx.Source, _nullFallbackValue); + var fallbackExpression = NullSubstitute(TargetType, ctx.Source, nullFallbackValue); var ifExpression = ctx.SyntaxFactory.IfNullReturnOrThrow(ctx.Source, fallbackExpression); return body.Prepend(ifExpression); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ObjectMemberMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ObjectMemberMethodMapping.cs index 0d5c4510e2..bd4b095855 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ObjectMemberMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ObjectMemberMethodMapping.cs @@ -9,15 +9,11 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A mapping from type to another by mapping each property. /// A implementation of . /// -public abstract class ObjectMemberMethodMapping : MethodMapping, IMemberAssignmentTypeMapping +public abstract class ObjectMemberMethodMapping(ITypeSymbol sourceType, ITypeSymbol targetType) + : MethodMapping(sourceType, targetType), + IMemberAssignmentTypeMapping { - private readonly ObjectMemberExistingTargetMapping _mapping; - - protected ObjectMemberMethodMapping(ITypeSymbol sourceType, ITypeSymbol targetType) - : base(sourceType, targetType) - { - _mapping = new ObjectMemberExistingTargetMapping(sourceType, targetType); - } + private readonly ObjectMemberExistingTargetMapping _mapping = new(sourceType, targetType); public bool HasMemberMapping(IMemberAssignmentMapping mapping) => _mapping.HasMemberMapping(mapping); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs index 8df39604ba..f8b5ac972d 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/QueryableProjectionMapping.cs @@ -9,19 +9,12 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// A projections queryable mapping /// to map from one generic to another. /// -public class QueryableProjectionMapping : MethodMapping +public class QueryableProjectionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) + : MethodMapping(sourceType, targetType) { private const string QueryableReceiverName = "System.Linq.Queryable"; private const string SelectMethodName = nameof(Queryable.Select); - private readonly INewInstanceMapping _delegateMapping; - - public QueryableProjectionMapping(ITypeSymbol sourceType, ITypeSymbol targetType, INewInstanceMapping delegateMapping) - : base(sourceType, targetType) - { - _delegateMapping = delegateMapping; - } - public override IEnumerable BuildBody(TypeMappingBuildContext ctx) { // disable nullable reference types for expressions, as for ORMs nullables usually don't apply @@ -30,8 +23,8 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // #nullable enable var (lambdaCtx, lambdaSourceName) = ctx.WithNewScopedSource(); - var delegateMapping = _delegateMapping.Build(lambdaCtx); - var projectionLambda = Lambda(lambdaSourceName, delegateMapping); + var delegateMappingSyntax = delegateMapping.Build(lambdaCtx); + var projectionLambda = Lambda(lambdaSourceName, delegateMappingSyntax); var select = StaticInvocation(QueryableReceiverName, SelectMethodName, ctx.Source, projectionLambda); var returnStatement = ctx.SyntaxFactory.Return(select); return new[] diff --git a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs index 838e443070..26f1c4a7bf 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMemberMapping.cs @@ -12,26 +12,16 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = Map(source.Span); /// /// -public class SourceObjectMemberMapping : NewInstanceMapping +public class SourceObjectMemberMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + string memberName, + INewInstanceMapping? delegateMapping = null +) : NewInstanceMapping(sourceType, targetType) { - private readonly string _memberName; - private readonly INewInstanceMapping? _delegateMapping; - - public SourceObjectMemberMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - string memberName, - INewInstanceMapping? delegateMapping = null - ) - : base(sourceType, targetType) - { - _memberName = memberName; - _delegateMapping = delegateMapping; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { - var sourceExpression = MemberAccess(ctx.Source, _memberName); - return _delegateMapping == null ? sourceExpression : _delegateMapping.Build(ctx.WithSource(sourceExpression)); + var sourceExpression = MemberAccess(ctx.Source, memberName); + return delegateMapping == null ? sourceExpression : delegateMapping.Build(ctx.WithSource(sourceExpression)); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs index fcd2cfe176..e9ef5d1ece 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/SourceObjectMethodMapping.cs @@ -12,27 +12,17 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = Map(source.ToArray()); /// /// -public class SourceObjectMethodMapping : NewInstanceMapping +public class SourceObjectMethodMapping( + ITypeSymbol sourceType, + ITypeSymbol targetType, + string methodName, + INewInstanceMapping? delegateMapping = null +) : NewInstanceMapping(sourceType, targetType) { - private readonly string _methodName; - private readonly INewInstanceMapping? _delegateMapping; - - public SourceObjectMethodMapping( - ITypeSymbol sourceType, - ITypeSymbol targetType, - string methodName, - INewInstanceMapping? delegateMapping = null - ) - : base(sourceType, targetType) - { - _methodName = methodName; - _delegateMapping = delegateMapping; - } - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { - var sourceExpression = Invocation(MemberAccess(ctx.Source, _methodName), BuildArguments(ctx).ToArray()); - return _delegateMapping == null ? sourceExpression : _delegateMapping.Build(ctx.WithSource(sourceExpression)); + var sourceExpression = Invocation(MemberAccess(ctx.Source, methodName), BuildArguments(ctx).ToArray()); + return delegateMapping == null ? sourceExpression : delegateMapping.Build(ctx.WithSource(sourceExpression)); } protected virtual IEnumerable BuildArguments(TypeMappingBuildContext ctx) => Enumerable.Empty(); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs index abde7a856a..16e742ee20 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/StaticMethodMapping.cs @@ -7,15 +7,7 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// /// Represents a mapping which works by invoking a static method with the source as only argument. /// -public class StaticMethodMapping : NewInstanceMapping +public class StaticMethodMapping(IMethodSymbol method) : NewInstanceMapping(method.Parameters.Single().Type, method.ReturnType) { - private readonly IMethodSymbol _method; - - public StaticMethodMapping(IMethodSymbol method) - : base(method.Parameters.Single().Type, method.ReturnType) - { - _method = method; - } - - public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => StaticInvocation(_method, ctx.Source); + public override ExpressionSyntax Build(TypeMappingBuildContext ctx) => StaticInvocation(method, ctx.Source); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/ToStringMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/ToStringMapping.cs index 1d14502562..fe413383d0 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/ToStringMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/ToStringMapping.cs @@ -11,22 +11,15 @@ namespace Riok.Mapperly.Descriptors.Mappings; /// target = source.ToString(); /// /// -public class ToStringMapping : SourceObjectMethodMapping +public class ToStringMapping(ITypeSymbol sourceType, ITypeSymbol targetType, string? stringFormat = null) + : SourceObjectMethodMapping(sourceType, targetType, nameof(ToString)) { - private readonly string? _stringFormat; - - public ToStringMapping(ITypeSymbol sourceType, ITypeSymbol targetType, string? stringFormat = null) - : base(sourceType, targetType, nameof(ToString)) - { - _stringFormat = stringFormat; - } - protected override IEnumerable BuildArguments(TypeMappingBuildContext ctx) { - if (_stringFormat == null) + if (stringFormat == null) yield break; - yield return StringLiteral(_stringFormat); + yield return StringLiteral(stringFormat); yield return NullLiteral(); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedExistingTargetMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedExistingTargetMethodMapping.cs index 5e82670dc9..a3ab669211 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedExistingTargetMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedExistingTargetMethodMapping.cs @@ -12,30 +12,21 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// /// Represents a mapping method declared but not implemented by the user which reuses an existing target object instance. /// -public class UserDefinedExistingTargetMethodMapping : MethodMapping, IUserMapping +public class UserDefinedExistingTargetMethodMapping( + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter targetParameter, + MethodParameter? referenceHandlerParameter, + bool enableReferenceHandling +) : MethodMapping(method, sourceParameter, referenceHandlerParameter, targetParameter.Type), IUserMapping { - private readonly bool _enableReferenceHandling; private IExistingTargetMapping? _delegateMapping; - public UserDefinedExistingTargetMethodMapping( - IMethodSymbol method, - MethodParameter sourceParameter, - MethodParameter targetParameter, - MethodParameter? referenceHandlerParameter, - bool enableReferenceHandling - ) - : base(method, sourceParameter, referenceHandlerParameter, targetParameter.Type) - { - _enableReferenceHandling = enableReferenceHandling; - Method = method; - TargetParameter = targetParameter; - } - - public IMethodSymbol Method { get; } + public IMethodSymbol Method { get; } = method; public void SetDelegateMapping(IExistingTargetMapping delegateMapping) => _delegateMapping = delegateMapping; - private MethodParameter TargetParameter { get; } + private MethodParameter TargetParameter { get; } = targetParameter; public override bool CallableByOtherMappings => false; @@ -60,7 +51,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // if reference handling is enabled and no reference handler parameter is declared // a new reference handler is instantiated and used. - if (_enableReferenceHandling && ReferenceHandlerParameter == null) + if (enableReferenceHandling && ReferenceHandlerParameter == null) { // var refHandler = new RefHandler(); var referenceHandlerName = ctx.NameBuilder.New(DefaultReferenceHandlerParameterName); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceGenericTypeMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceGenericTypeMapping.cs index 3b38606089..b36079ebaf 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceGenericTypeMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceGenericTypeMapping.cs @@ -13,22 +13,24 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// a generic target parameter or both. /// Similar to . /// -public class UserDefinedNewInstanceGenericTypeMapping : UserDefinedNewInstanceRuntimeTargetTypeMapping -{ - public UserDefinedNewInstanceGenericTypeMapping( - IMethodSymbol method, - GenericMappingTypeParameters typeParameters, - MappingMethodParameters parameters, - bool enableReferenceHandling, - NullFallbackValue nullArm, - ITypeSymbol objectType +public class UserDefinedNewInstanceGenericTypeMapping( + IMethodSymbol method, + GenericMappingTypeParameters typeParameters, + MappingMethodParameters parameters, + bool enableReferenceHandling, + NullFallbackValue nullArm, + ITypeSymbol objectType +) + : UserDefinedNewInstanceRuntimeTargetTypeMapping( + method, + parameters.Source, + parameters.ReferenceHandler, + enableReferenceHandling, + nullArm, + objectType ) - : base(method, parameters.Source, parameters.ReferenceHandler, enableReferenceHandling, nullArm, objectType) - { - TypeParameters = typeParameters; - } - - public GenericMappingTypeParameters TypeParameters { get; } +{ + public GenericMappingTypeParameters TypeParameters { get; } = typeParameters; public override MethodDeclarationSyntax BuildMethod(SourceEmitterContext ctx) => base.BuildMethod(ctx).WithTypeParameterList(TypeParameterList(TypeParameters.SourceType, TypeParameters.TargetType)); diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs index b2c66b9325..de3304106f 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceMethodMapping.cs @@ -9,23 +9,14 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// /// Represents a mapping method declared but not implemented by the user which results in a new target object instance. /// -public class UserDefinedNewInstanceMethodMapping : MethodMapping, IDelegateUserMapping +public class UserDefinedNewInstanceMethodMapping( + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter? referenceHandlerParameter, + bool enableReferenceHandling +) : MethodMapping(method, sourceParameter, referenceHandlerParameter, method.ReturnType.UpgradeNullable()), IDelegateUserMapping { - private readonly bool _enableReferenceHandling; - - public UserDefinedNewInstanceMethodMapping( - IMethodSymbol method, - MethodParameter sourceParameter, - MethodParameter? referenceHandlerParameter, - bool enableReferenceHandling - ) - : base(method, sourceParameter, referenceHandlerParameter, method.ReturnType.UpgradeNullable()) - { - _enableReferenceHandling = enableReferenceHandling; - Method = method; - } - - public IMethodSymbol Method { get; } + public IMethodSymbol Method { get; } = method; public INewInstanceMapping? DelegateMapping { get; private set; } @@ -41,7 +32,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c // if reference handling is enabled and no reference handler parameter is declared // the generated mapping method is called with a new reference handler instance // otherwise the generated method is embedded - if (_enableReferenceHandling && ReferenceHandlerParameter == null) + if (enableReferenceHandling && ReferenceHandlerParameter == null) { // new RefHandler(); var createRefHandler = ctx.SyntaxFactory.CreateInstance(TemplateReference.PreserveReferenceHandler); @@ -59,7 +50,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c /// A is callable by other mappings /// if either reference handling is not activated, or the user defined a reference handler parameter. /// - public override bool CallableByOtherMappings => !_enableReferenceHandling || ReferenceHandlerParameter != null; + public override bool CallableByOtherMappings => !enableReferenceHandling || ReferenceHandlerParameter != null; internal override void EnableReferenceHandling(INamedTypeSymbol iReferenceHandlerType) { diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeMapping.cs index 533213559c..e24ee7d798 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeMapping.cs @@ -13,31 +13,19 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// A mapping which has a as a second parameter describing the target type of the mapping. /// Generates a switch expression based on the mapping types. /// -public abstract class UserDefinedNewInstanceRuntimeTargetTypeMapping : MethodMapping, IUserMapping +public abstract class UserDefinedNewInstanceRuntimeTargetTypeMapping( + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter? referenceHandlerParameter, + bool enableReferenceHandling, + NullFallbackValue nullArm, + ITypeSymbol objectType +) : MethodMapping(method, sourceParameter, referenceHandlerParameter, method.ReturnType), IUserMapping { private const string IsAssignableFromMethodName = nameof(Type.IsAssignableFrom); private const string GetTypeMethodName = nameof(GetType); private readonly List _mappings = new(); - private readonly bool _enableReferenceHandling; - private readonly NullFallbackValue _nullArm; - private readonly ITypeSymbol _objectType; - - protected UserDefinedNewInstanceRuntimeTargetTypeMapping( - IMethodSymbol method, - MethodParameter sourceParameter, - MethodParameter? referenceHandlerParameter, - bool enableReferenceHandling, - NullFallbackValue nullArm, - ITypeSymbol objectType - ) - : base(method, sourceParameter, referenceHandlerParameter, method.ReturnType) - { - Method = method; - _enableReferenceHandling = enableReferenceHandling; - _nullArm = nullArm; - _objectType = objectType; - } // requires the user mapping bodies // as the delegate mapping of user mappings is only set after bodies are built @@ -46,7 +34,7 @@ ITypeSymbol objectType // only the delegate mapping is callable by other mappings. public override MappingBodyBuildingPriority BodyBuildingPriority => MappingBodyBuildingPriority.AfterUserMappings; - public IMethodSymbol Method { get; } + public IMethodSymbol Method { get; } = method; public override bool CallableByOtherMappings => false; @@ -56,7 +44,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c { // if reference handling is enabled and no reference handler parameter is declared // a new reference handler is instantiated and used. - if (_enableReferenceHandling && ReferenceHandlerParameter == null) + if (enableReferenceHandling && ReferenceHandlerParameter == null) { // var refHandler = new RefHandler(); var referenceHandlerName = ctx.NameBuilder.New(DefaultReferenceHandlerParameterName); @@ -83,7 +71,7 @@ public override IEnumerable BuildBody(TypeMappingBuildContext c var arms = _mappings.Select(x => BuildSwitchArm(typeArmContext, typeArmVariableName, x, targetType)); // null => default / throw - arms = arms.Append(SwitchArm(ConstantPattern(NullLiteral()), NullSubstitute(TargetType, ctx.Source, _nullArm))); + arms = arms.Append(SwitchArm(ConstantPattern(NullLiteral()), NullSubstitute(TargetType, ctx.Source, nullArm))); arms = arms.Append(fallbackArm); var switchExpression = ctx.SyntaxFactory.Switch(ctx.Source, arms); yield return ctx.SyntaxFactory.Return(switchExpression); @@ -131,7 +119,7 @@ private ExpressionSyntax BuildSwitchArmMapping(RuntimeTargetTypeMapping mapping, // (TTarget)(object)MapToTarget(source); return CastExpression( FullyQualifiedIdentifier(TargetType), - CastExpression(FullyQualifiedIdentifier(_objectType), mappingExpression) + CastExpression(FullyQualifiedIdentifier(objectType), mappingExpression) ); } } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeParameterMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeParameterMapping.cs index ce15bc8e97..0ca4a0eb9a 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeParameterMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserDefinedNewInstanceRuntimeTargetTypeParameterMapping.cs @@ -10,24 +10,24 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// A mapping which has a as a second parameter describing the target type of the mapping. /// Generates a switch expression based on the mapping types. /// -public class UserDefinedNewInstanceRuntimeTargetTypeParameterMapping : UserDefinedNewInstanceRuntimeTargetTypeMapping -{ - private readonly MethodParameter _targetTypeParameter; - - public UserDefinedNewInstanceRuntimeTargetTypeParameterMapping( - IMethodSymbol method, - RuntimeTargetTypeMappingMethodParameters parameters, - bool enableReferenceHandling, - NullFallbackValue nullArm, - ITypeSymbol objectType +public class UserDefinedNewInstanceRuntimeTargetTypeParameterMapping( + IMethodSymbol method, + RuntimeTargetTypeMappingMethodParameters parameters, + bool enableReferenceHandling, + NullFallbackValue nullArm, + ITypeSymbol objectType +) + : UserDefinedNewInstanceRuntimeTargetTypeMapping( + method, + parameters.Source, + parameters.ReferenceHandler, + enableReferenceHandling, + nullArm, + objectType ) - : base(method, parameters.Source, parameters.ReferenceHandler, enableReferenceHandling, nullArm, objectType) - { - _targetTypeParameter = parameters.TargetType; - } - +{ protected override ParameterListSyntax BuildParameterList() => - ParameterList(IsExtensionMethod, SourceParameter, _targetTypeParameter, ReferenceHandlerParameter); + ParameterList(IsExtensionMethod, SourceParameter, parameters.TargetType, ReferenceHandlerParameter); - protected override ExpressionSyntax BuildTargetType() => IdentifierName(_targetTypeParameter.Name); + protected override ExpressionSyntax BuildTargetType() => IdentifierName(parameters.TargetType.Name); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs index 186e867912..24fa30dbe4 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedExistingTargetMethodMapping.cs @@ -11,30 +11,15 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// /// Represents an existing target type mapper which is implemented by the user. /// -public class UserImplementedExistingTargetMethodMapping : ExistingTargetMapping, IUserMapping +public class UserImplementedExistingTargetMethodMapping( + string? receiver, + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter targetParameter, + MethodParameter? referenceHandlerParameter +) : ExistingTargetMapping(method.Parameters[0].Type.UpgradeNullable(), targetParameter.Type.UpgradeNullable()), IUserMapping { - private readonly MethodParameter _sourceParameter; - private readonly MethodParameter _targetParameter; - private readonly MethodParameter? _referenceHandlerParameter; - private readonly string? _receiver; - - public UserImplementedExistingTargetMethodMapping( - string? receiver, - IMethodSymbol method, - MethodParameter sourceParameter, - MethodParameter targetParameter, - MethodParameter? referenceHandlerParameter - ) - : base(method.Parameters[0].Type.UpgradeNullable(), targetParameter.Type.UpgradeNullable()) - { - Method = method; - _sourceParameter = sourceParameter; - _targetParameter = targetParameter; - _referenceHandlerParameter = referenceHandlerParameter; - _receiver = receiver; - } - - public IMethodSymbol Method { get; } + public IMethodSymbol Method { get; } = method; public override IEnumerable Build(TypeMappingBuildContext ctx, ExpressionSyntax target) { @@ -44,10 +29,10 @@ public override IEnumerable Build(TypeMappingBuildContext ctx, { yield return ctx.SyntaxFactory.ExpressionStatement( Invocation( - _receiver == null ? IdentifierName(Method.Name) : MemberAccess(_receiver, Method.Name), - _sourceParameter.WithArgument(ctx.Source), - _targetParameter.WithArgument(target), - _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) + receiver == null ? IdentifierName(Method.Name) : MemberAccess(receiver, Method.Name), + sourceParameter.WithArgument(ctx.Source), + targetParameter.WithArgument(target), + referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) ) ); yield break; @@ -55,15 +40,15 @@ public override IEnumerable Build(TypeMappingBuildContext ctx, var castedThis = CastExpression( FullyQualifiedIdentifier(Method.ReceiverType!), - _receiver != null ? IdentifierName(_receiver) : ThisExpression() + receiver != null ? IdentifierName(receiver) : ThisExpression() ); var method = MemberAccess(ParenthesizedExpression(castedThis), Method.Name); yield return ctx.SyntaxFactory.ExpressionStatement( Invocation( method, - _sourceParameter.WithArgument(ctx.Source), - _targetParameter.WithArgument(target), - _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) + sourceParameter.WithArgument(ctx.Source), + targetParameter.WithArgument(target), + referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) ) ); } diff --git a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs index 2c7117261d..764f31ce8e 100644 --- a/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs +++ b/src/Riok.Mapperly/Descriptors/Mappings/UserMappings/UserImplementedMethodMapping.cs @@ -10,27 +10,14 @@ namespace Riok.Mapperly.Descriptors.Mappings.UserMappings; /// /// Represents a mapping method on the mapper which is implemented by the user. /// -public class UserImplementedMethodMapping : NewInstanceMapping, IUserMapping +public class UserImplementedMethodMapping( + string? receiver, + IMethodSymbol method, + MethodParameter sourceParameter, + MethodParameter? referenceHandlerParameter +) : NewInstanceMapping(method.Parameters[0].Type.UpgradeNullable(), method.ReturnType.UpgradeNullable()), IUserMapping { - private readonly string? _receiver; - private readonly MethodParameter _sourceParameter; - private readonly MethodParameter? _referenceHandlerParameter; - - public UserImplementedMethodMapping( - string? receiver, - IMethodSymbol method, - MethodParameter sourceParameter, - MethodParameter? referenceHandlerParameter - ) - : base(method.Parameters[0].Type.UpgradeNullable(), method.ReturnType.UpgradeNullable()) - { - Method = method; - _receiver = receiver; - _sourceParameter = sourceParameter; - _referenceHandlerParameter = referenceHandlerParameter; - } - - public IMethodSymbol Method { get; } + public IMethodSymbol Method { get; } = method; public override ExpressionSyntax Build(TypeMappingBuildContext ctx) { @@ -38,20 +25,16 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx) // we explicitly cast to be able to use the default interface implementation or explicit implementations if (Method.ReceiverType?.TypeKind != TypeKind.Interface) return Invocation( - _receiver == null ? IdentifierName(Method.Name) : MemberAccess(_receiver, Method.Name), - _sourceParameter.WithArgument(ctx.Source), - _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) + receiver == null ? IdentifierName(Method.Name) : MemberAccess(receiver, Method.Name), + sourceParameter.WithArgument(ctx.Source), + referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) ); var castedReceiver = CastExpression( FullyQualifiedIdentifier(Method.ReceiverType!), - _receiver == null ? ThisExpression() : IdentifierName(_receiver) + receiver == null ? ThisExpression() : IdentifierName(receiver) ); var method = MemberAccess(ParenthesizedExpression(castedReceiver), Method.Name); - return Invocation( - method, - _sourceParameter.WithArgument(ctx.Source), - _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler) - ); + return Invocation(method, sourceParameter.WithArgument(ctx.Source), referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler)); } } diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceObjectFactory.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceObjectFactory.cs index 0a212ff984..ba4f715cfc 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceObjectFactory.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceObjectFactory.cs @@ -9,11 +9,8 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// with a named return type and one type parameter which is also the only parameter of the method. /// Example signature: TypeToCreate Create<S>(S source); /// -public class GenericSourceObjectFactory : ObjectFactory +public class GenericSourceObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) : ObjectFactory(symbolAccessor, method) { - public GenericSourceObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) - : base(symbolAccessor, method) { } - public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => SymbolEqualityComparer.Default.Equals(Method.ReturnType, targetTypeToCreate) && SymbolAccessor.DoesTypeSatisfyTypeParameterConstraints( diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceTargetObjectFactory.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceTargetObjectFactory.cs index 9edb93d48f..f85cd80a9b 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceTargetObjectFactory.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericSourceTargetObjectFactory.cs @@ -4,21 +4,14 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; -public class GenericSourceTargetObjectFactory : ObjectFactory +public class GenericSourceTargetObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method, int sourceTypeParameterIndex) + : ObjectFactory(symbolAccessor, method) { - private readonly int _sourceTypeParameterIndex; - private readonly int _targetTypeParameterIndex; - - public GenericSourceTargetObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method, int sourceTypeParameterIndex) - : base(symbolAccessor, method) - { - _sourceTypeParameterIndex = sourceTypeParameterIndex; - _targetTypeParameterIndex = (sourceTypeParameterIndex + 1) % 2; - } + private readonly int _targetTypeParameterIndex = (sourceTypeParameterIndex + 1) % 2; public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => SymbolAccessor.DoesTypeSatisfyTypeParameterConstraints( - Method.TypeParameters[_sourceTypeParameterIndex], + Method.TypeParameters[sourceTypeParameterIndex], sourceType, Method.Parameters[0].Type.NullableAnnotation ) @@ -31,7 +24,7 @@ public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTyp protected override ExpressionSyntax BuildCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate, ExpressionSyntax source) { var typeParams = new TypeSyntax[2]; - typeParams[_sourceTypeParameterIndex] = NonNullableIdentifier(sourceType); + typeParams[sourceTypeParameterIndex] = NonNullableIdentifier(sourceType); typeParams[_targetTypeParameterIndex] = NonNullableIdentifier(targetTypeToCreate); return GenericInvocation(Method.Name, typeParams, source); } diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactory.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactory.cs index 5ab2eba93b..3d9d462a13 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactory.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactory.cs @@ -9,11 +9,8 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// without any parameters but a single type parameter which is also the return type. /// Example signature: T Create<T>(); /// -public class GenericTargetObjectFactory : ObjectFactory +public class GenericTargetObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) : ObjectFactory(symbolAccessor, method) { - public GenericTargetObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) - : base(symbolAccessor, method) { } - public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => SymbolAccessor.DoesTypeSatisfyTypeParameterConstraints( Method.TypeParameters[0], diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactoryWithSource.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactoryWithSource.cs index 20d4c8ffbc..91f671b852 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactoryWithSource.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/GenericTargetObjectFactoryWithSource.cs @@ -9,11 +9,9 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// with a single parameter (which is the source object and is a named type) and a single type parameter which is also the return type. /// Example signature: T Create<T>(SourceType source); /// -public class GenericTargetObjectFactoryWithSource : GenericTargetObjectFactory +public class GenericTargetObjectFactoryWithSource(SymbolAccessor symbolAccessor, IMethodSymbol method) + : GenericTargetObjectFactory(symbolAccessor, method) { - public GenericTargetObjectFactoryWithSource(SymbolAccessor symbolAccessor, IMethodSymbol method) - : base(symbolAccessor, method) { } - public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => base.CanCreateType(sourceType, targetTypeToCreate) && SymbolEqualityComparer.Default.Equals(Method.Parameters[0].Type, sourceType); diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactory.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactory.cs index 26e22ed9b9..e530cd11d5 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactory.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactory.cs @@ -8,17 +8,11 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// /// An object factory represents a method to instantiate objects of a certain type. /// -public abstract class ObjectFactory +public abstract class ObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) { - protected ObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) - { - Method = method; - SymbolAccessor = symbolAccessor; - } - - protected SymbolAccessor SymbolAccessor { get; } + protected SymbolAccessor SymbolAccessor { get; } = symbolAccessor; - protected IMethodSymbol Method { get; } + protected IMethodSymbol Method { get; } = method; public ExpressionSyntax CreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate, ExpressionSyntax source) => HandleNull(BuildCreateType(sourceType, targetTypeToCreate, source), targetTypeToCreate); diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactoryCollection.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactoryCollection.cs index 654d7a8fdf..f3effdbf8c 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactoryCollection.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/ObjectFactoryCollection.cs @@ -3,22 +3,16 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; -public class ObjectFactoryCollection +public class ObjectFactoryCollection(IReadOnlyCollection objectFactories) { - private readonly IReadOnlyCollection _objectFactories; private readonly Dictionary _concreteObjectFactories = new(SymbolEqualityComparer.IncludeNullability); - public ObjectFactoryCollection(IReadOnlyCollection objectFactories) - { - _objectFactories = objectFactories; - } - public bool TryFindObjectFactory(ITypeSymbol sourceType, ITypeSymbol targetType, [NotNullWhen(true)] out ObjectFactory? objectFactory) { if (_concreteObjectFactories.TryGetValue(targetType, out objectFactory)) return true; - objectFactory = _objectFactories.FirstOrDefault(f => f.CanCreateType(sourceType, targetType)); + objectFactory = objectFactories.FirstOrDefault(f => f.CanCreateType(sourceType, targetType)); if (objectFactory == null) return false; diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactory.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactory.cs index a2e4b4da8e..6b6927271d 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactory.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactory.cs @@ -8,11 +8,8 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// A is an without any parameters and a named return type (not generic). /// Example signature: TypeToCreate Create(); /// -public class SimpleObjectFactory : ObjectFactory +public class SimpleObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) : ObjectFactory(symbolAccessor, method) { - public SimpleObjectFactory(SymbolAccessor symbolAccessor, IMethodSymbol method) - : base(symbolAccessor, method) { } - public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => SymbolEqualityComparer.Default.Equals(Method.ReturnType, targetTypeToCreate); diff --git a/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactoryWithSource.cs b/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactoryWithSource.cs index bc8232b192..f9635f33f7 100644 --- a/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactoryWithSource.cs +++ b/src/Riok.Mapperly/Descriptors/ObjectFactories/SimpleObjectFactoryWithSource.cs @@ -9,11 +9,9 @@ namespace Riok.Mapperly.Descriptors.ObjectFactories; /// with a single parameter (which is the source object and is a named type) and a named return type (not generic). /// Example signature: TypeToCreate Create(SourceType source); /// -public class SimpleObjectFactoryWithSource : SimpleObjectFactory +public class SimpleObjectFactoryWithSource(SymbolAccessor symbolAccessor, IMethodSymbol method) + : SimpleObjectFactory(symbolAccessor, method) { - public SimpleObjectFactoryWithSource(SymbolAccessor symbolAccessor, IMethodSymbol method) - : base(symbolAccessor, method) { } - public override bool CanCreateType(ITypeSymbol sourceType, ITypeSymbol targetTypeToCreate) => base.CanCreateType(sourceType, targetTypeToCreate) && SymbolEqualityComparer.Default.Equals(sourceType, Method.Parameters[0].Type); diff --git a/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs b/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs index 25e3128e75..8202176a32 100644 --- a/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs @@ -10,35 +10,22 @@ namespace Riok.Mapperly.Descriptors; /// /// A simple mapping context which does not allow to access and build other mappings. /// -public class SimpleMappingBuilderContext +public class SimpleMappingBuilderContext( + CompilationContext compilationContext, + MapperConfigurationReader configurationReader, + SymbolAccessor symbolAccessor, + AttributeDataAccessor attributeAccessor, + MapperDescriptor descriptor, + UnsafeAccessorContext unsafeAccessorContext, + DiagnosticCollection diagnostics, + MappingBuilder mappingBuilder, + ExistingTargetMappingBuilder existingTargetMappingBuilder +) { - private readonly MapperDescriptor _descriptor; - private readonly DiagnosticCollection _diagnostics; - private readonly CompilationContext _compilationContext; - private readonly MapperConfigurationReader _configurationReader; - - public SimpleMappingBuilderContext( - CompilationContext compilationContext, - MapperConfigurationReader configurationReader, - SymbolAccessor symbolAccessor, - AttributeDataAccessor attributeAccessor, - MapperDescriptor descriptor, - UnsafeAccessorContext unsafeAccessorContext, - DiagnosticCollection diagnostics, - MappingBuilder mappingBuilder, - ExistingTargetMappingBuilder existingTargetMappingBuilder - ) - { - SymbolAccessor = symbolAccessor; - _compilationContext = compilationContext; - _configurationReader = configurationReader; - _descriptor = descriptor; - _diagnostics = diagnostics; - MappingBuilder = mappingBuilder; - ExistingTargetMappingBuilder = existingTargetMappingBuilder; - AttributeAccessor = attributeAccessor; - UnsafeAccessorContext = unsafeAccessorContext; - } + private readonly MapperDescriptor _descriptor = descriptor; + private readonly DiagnosticCollection _diagnostics = diagnostics; + private readonly CompilationContext _compilationContext = compilationContext; + private readonly MapperConfigurationReader _configurationReader = configurationReader; protected SimpleMappingBuilderContext(SimpleMappingBuilderContext ctx) : this( @@ -61,15 +48,15 @@ protected SimpleMappingBuilderContext(SimpleMappingBuilderContext ctx) public bool Static => _descriptor.Static; - public SymbolAccessor SymbolAccessor { get; } + public SymbolAccessor SymbolAccessor { get; } = symbolAccessor; - public AttributeDataAccessor AttributeAccessor { get; } + public AttributeDataAccessor AttributeAccessor { get; } = attributeAccessor; - public UnsafeAccessorContext UnsafeAccessorContext { get; } + public UnsafeAccessorContext UnsafeAccessorContext { get; } = unsafeAccessorContext; - protected MappingBuilder MappingBuilder { get; } + protected MappingBuilder MappingBuilder { get; } = mappingBuilder; - protected ExistingTargetMappingBuilder ExistingTargetMappingBuilder { get; } + protected ExistingTargetMappingBuilder ExistingTargetMappingBuilder { get; } = existingTargetMappingBuilder; public virtual bool IsConversionEnabled(MappingConversionType conversionType) => MapperConfiguration.EnabledConversions.HasFlag(conversionType); diff --git a/src/Riok.Mapperly/Descriptors/SymbolAccessor.cs b/src/Riok.Mapperly/Descriptors/SymbolAccessor.cs index cf11b900f9..e968541ca0 100644 --- a/src/Riok.Mapperly/Descriptors/SymbolAccessor.cs +++ b/src/Riok.Mapperly/Descriptors/SymbolAccessor.cs @@ -8,10 +8,8 @@ namespace Riok.Mapperly.Descriptors; -public class SymbolAccessor +public class SymbolAccessor(CompilationContext compilationContext, INamedTypeSymbol mapperSymbol) { - private readonly CompilationContext _compilationContext; - private readonly INamedTypeSymbol _mapperSymbol; private readonly Dictionary> _attributes = new(SymbolEqualityComparer.Default); private readonly Dictionary> _allMembers = new(SymbolEqualityComparer.Default); private readonly Dictionary> _allAccessibleMembers = @@ -23,13 +21,7 @@ public class SymbolAccessor private MemberVisibility _memberVisibility = MemberVisibility.AllAccessible; - public SymbolAccessor(CompilationContext compilationContext, INamedTypeSymbol mapperSymbol) - { - _compilationContext = compilationContext; - _mapperSymbol = mapperSymbol; - } - - private Compilation Compilation => _compilationContext.Compilation; + private Compilation Compilation => compilationContext.Compilation; internal void SetMemberVisibility(MemberVisibility visibility) => _memberVisibility = visibility; @@ -37,7 +29,7 @@ public bool HasAccessibleParameterlessConstructor(ITypeSymbol symbol) => symbol is INamedTypeSymbol { IsAbstract: false } namedTypeSymbol && namedTypeSymbol.InstanceConstructors.Any(c => c.Parameters.IsDefaultOrEmpty && IsDirectlyAccessible(c)); - public bool IsDirectlyAccessible(ISymbol symbol) => Compilation.IsSymbolAccessibleWithin(symbol, _mapperSymbol); + public bool IsDirectlyAccessible(ISymbol symbol) => Compilation.IsSymbolAccessibleWithin(symbol, mapperSymbol); public bool IsAccessibleToMemberVisibility(ISymbol symbol) { @@ -97,7 +89,7 @@ internal IEnumerable GetAttributes(ISymbol symbol) yield break; } - var attributeSymbol = _compilationContext.Types.Get(); + var attributeSymbol = compilationContext.Types.Get(); foreach (var attr in attributes) { if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.ConstructedFrom ?? attr.AttributeClass, attributeSymbol)) diff --git a/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs b/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs index c46b13f0bd..660e74e0a1 100644 --- a/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs +++ b/src/Riok.Mapperly/Descriptors/TypeMappingKey.cs @@ -6,25 +6,25 @@ namespace Riok.Mapperly.Descriptors; [DebuggerDisplay("{Source.Name} => {Target.Name}")] -public readonly struct TypeMappingKey +public readonly struct TypeMappingKey( + ITypeSymbol source, + ITypeSymbol target, + TypeMappingConfiguration? config = null, + bool includeNullability = true +) { private static readonly IEqualityComparer _comparer = SymbolEqualityComparer.IncludeNullability; public TypeMappingKey(ITypeMapping mapping, TypeMappingConfiguration? config = null, bool includeNullability = true) : this(mapping.SourceType, mapping.TargetType, config, includeNullability) { } - public TypeMappingKey(ITypeSymbol source, ITypeSymbol target, TypeMappingConfiguration? config = null, bool includeNullability = true) - { - Configuration = config ?? TypeMappingConfiguration.Default; - Source = includeNullability ? source.UpgradeNullable() : source.NonNullable(); - Target = includeNullability ? target.UpgradeNullable() : target.NonNullable(); - } - - public ITypeSymbol Source { get; } + public ITypeSymbol Source { get; } = + includeNullability ? NullableSymbolExtensions.UpgradeNullable(source) : NullableSymbolExtensions.NonNullable(source); - public ITypeSymbol Target { get; } + public ITypeSymbol Target { get; } = + includeNullability ? NullableSymbolExtensions.UpgradeNullable(target) : NullableSymbolExtensions.NonNullable(target); - public TypeMappingConfiguration Configuration { get; } + public TypeMappingConfiguration Configuration { get; } = config ?? TypeMappingConfiguration.Default; public TypeMappingKey NonNullableSource() => new(Source.NonNullable(), Target, Configuration); diff --git a/src/Riok.Mapperly/Descriptors/UnsafeAccessorContext.cs b/src/Riok.Mapperly/Descriptors/UnsafeAccessorContext.cs index c368256cd2..3b87b3df12 100644 --- a/src/Riok.Mapperly/Descriptors/UnsafeAccessorContext.cs +++ b/src/Riok.Mapperly/Descriptors/UnsafeAccessorContext.cs @@ -5,18 +5,11 @@ namespace Riok.Mapperly.Descriptors; -public class UnsafeAccessorContext +public class UnsafeAccessorContext(UniqueNameBuilder nameBuilder, SymbolAccessor symbolAccessor) { - private readonly UniqueNameBuilder _nameBuilder; - private readonly SymbolAccessor _symbolAccessor; + private readonly UniqueNameBuilder _nameBuilder = nameBuilder.NewScope(); private readonly Dictionary _unsafeAccessors = new(); - public UnsafeAccessorContext(UniqueNameBuilder nameBuilder, SymbolAccessor symbolAccessor) - { - _nameBuilder = nameBuilder.NewScope(); - _symbolAccessor = symbolAccessor; - } - public IReadOnlyCollection UnsafeAccessors => _unsafeAccessors.Values; public IUnsafeAccessor GetOrBuildAccessor(UnsafeAccessorType type, ISymbol symbol) @@ -50,7 +43,7 @@ public IUnsafeAccessor GetOrBuildAccessor(UnsafeAccessorType type, ISymbol symbo private string GetValidMethodName(ITypeSymbol symbol, string name) { - var memberNames = _symbolAccessor.GetAllMembers(symbol).Select(x => x.Name); + var memberNames = symbolAccessor.GetAllMembers(symbol).Select(x => x.Name); return _nameBuilder.New(name, memberNames); } @@ -75,16 +68,10 @@ public enum UnsafeAccessorType GetField, } - private readonly struct UnsafeAccessorKey : IEquatable + private readonly struct UnsafeAccessorKey(ISymbol member, UnsafeAccessorType type) : IEquatable { - private readonly ISymbol _member; - private readonly UnsafeAccessorType _type; - - public UnsafeAccessorKey(ISymbol member, UnsafeAccessorType type) - { - _member = member; - _type = type; - } + private readonly ISymbol _member = member; + private readonly UnsafeAccessorType _type = type; public bool Equals(UnsafeAccessorKey other) => SymbolEqualityComparer.Default.Equals(_member, other._member) && _type == other._type; diff --git a/src/Riok.Mapperly/Descriptors/WellKnownTypes.cs b/src/Riok.Mapperly/Descriptors/WellKnownTypes.cs index a9396cdc46..859efef9a6 100644 --- a/src/Riok.Mapperly/Descriptors/WellKnownTypes.cs +++ b/src/Riok.Mapperly/Descriptors/WellKnownTypes.cs @@ -3,23 +3,17 @@ namespace Riok.Mapperly.Descriptors; -public class WellKnownTypes +public class WellKnownTypes(Compilation compilation) { - private readonly Compilation _compilation; private readonly Dictionary _cachedTypes = new(); - internal WellKnownTypes(Compilation compilation) - { - _compilation = compilation; - } - // use string type name as they are not available in netstandard2.0 public INamedTypeSymbol? DateOnly => TryGet("System.DateOnly"); public INamedTypeSymbol? TimeOnly => TryGet("System.TimeOnly"); public ITypeSymbol GetArrayType(ITypeSymbol type) => - _compilation.CreateArrayTypeSymbol(type, elementNullableAnnotation: type.NullableAnnotation).NonNullable(); + compilation.CreateArrayTypeSymbol(type, elementNullableAnnotation: type.NullableAnnotation).NonNullable(); public INamedTypeSymbol Get() => Get(typeof(T)); @@ -40,7 +34,7 @@ public INamedTypeSymbol Get(Type type) return typeSymbol; } - typeSymbol = _compilation.GetBestTypeByMetadataName(typeFullName); + typeSymbol = compilation.GetBestTypeByMetadataName(typeFullName); _cachedTypes.Add(typeFullName, typeSymbol); return typeSymbol; diff --git a/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs b/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs index e5f0586d38..e0ed1dedd8 100644 --- a/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs +++ b/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs @@ -3,15 +3,9 @@ namespace Riok.Mapperly.Diagnostics; -public class DiagnosticCollection : IReadOnlyCollection +public class DiagnosticCollection(Location defaultLocation) : IReadOnlyCollection { private readonly List _diagnostics = new(); - private readonly Location _defaultLocation; - - internal DiagnosticCollection(Location defaultLocation) - { - _defaultLocation = defaultLocation; - } public IEnumerator GetEnumerator() => _diagnostics.GetEnumerator(); @@ -33,6 +27,6 @@ internal void ReportDiagnostic(DiagnosticDescriptor descriptor, ISymbol? locatio var syntaxNode = location?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); var nodeLocation = syntaxNode?.GetLocation(); - _diagnostics.Add(Diagnostic.Create(descriptor, nodeLocation ?? _defaultLocation, messageArgs)); + _diagnostics.Add(Diagnostic.Create(descriptor, nodeLocation ?? defaultLocation, messageArgs)); } } diff --git a/src/Riok.Mapperly/Helpers/ImmutableEquatableArray.cs b/src/Riok.Mapperly/Helpers/ImmutableEquatableArray.cs index 7886736a0c..428abfcb23 100644 --- a/src/Riok.Mapperly/Helpers/ImmutableEquatableArray.cs +++ b/src/Riok.Mapperly/Helpers/ImmutableEquatableArray.cs @@ -8,15 +8,13 @@ namespace Riok.Mapperly.Helpers; /// /// Provides an immutable list implementation which implements sequence equality. /// -public sealed class ImmutableEquatableArray : IEquatable>, IReadOnlyList +public sealed class ImmutableEquatableArray(IEnumerable values) : IEquatable>, IReadOnlyList where T : IEquatable { - private readonly T[] _values; + private readonly T[] _values = Enumerable.ToArray(values); public T this[int index] => _values[index]; public int Count => _values.Length; - public ImmutableEquatableArray(IEnumerable values) => _values = values.ToArray(); - public bool Equals(ImmutableEquatableArray? other) => other != null && ((ReadOnlySpan)_values).SequenceEqual(other._values); public override bool Equals(object? obj) => obj is ImmutableEquatableArray other && Equals(other); diff --git a/src/Riok.Mapperly/Helpers/UniqueNameBuilder.cs b/src/Riok.Mapperly/Helpers/UniqueNameBuilder.cs index 3e9d3e1198..d72fe8a910 100644 --- a/src/Riok.Mapperly/Helpers/UniqueNameBuilder.cs +++ b/src/Riok.Mapperly/Helpers/UniqueNameBuilder.cs @@ -1,18 +1,13 @@ namespace Riok.Mapperly.Helpers; -public class UniqueNameBuilder +public class UniqueNameBuilder() { - private readonly HashSet _usedNames; + private readonly HashSet _usedNames = new(StringComparer.Ordinal); private readonly UniqueNameBuilder? _parentScope; - public UniqueNameBuilder() - { - _usedNames = new HashSet(StringComparer.Ordinal); - } - private UniqueNameBuilder(UniqueNameBuilder parentScope) + : this() { - _usedNames = new HashSet(StringComparer.Ordinal); _parentScope = parentScope; } diff --git a/src/Riok.Mapperly/Symbols/FieldMember.cs b/src/Riok.Mapperly/Symbols/FieldMember.cs index e2e8457f49..538995c880 100644 --- a/src/Riok.Mapperly/Symbols/FieldMember.cs +++ b/src/Riok.Mapperly/Symbols/FieldMember.cs @@ -5,14 +5,9 @@ namespace Riok.Mapperly.Symbols; -public class FieldMember : IMappableMember +public class FieldMember(IFieldSymbol fieldSymbol) : IMappableMember { - private readonly IFieldSymbol _fieldSymbol; - - public FieldMember(IFieldSymbol fieldSymbol) - { - _fieldSymbol = fieldSymbol; - } + private readonly IFieldSymbol _fieldSymbol = fieldSymbol; public string Name => _fieldSymbol.Name; public ITypeSymbol Type => _fieldSymbol.Type; diff --git a/src/Riok.Mapperly/Symbols/MemberPath.cs b/src/Riok.Mapperly/Symbols/MemberPath.cs index 303e4e2753..9e8e72c1d2 100644 --- a/src/Riok.Mapperly/Symbols/MemberPath.cs +++ b/src/Riok.Mapperly/Symbols/MemberPath.cs @@ -12,18 +12,12 @@ namespace Riok.Mapperly.Symbols; /// Eg. A.B.C /// [DebuggerDisplay("{FullName}")] -public class MemberPath +public class MemberPath(IReadOnlyList path) { private const string MemberAccessSeparator = "."; protected const string NullableValueProperty = "Value"; - public MemberPath(IReadOnlyList path) - { - Path = path; - FullName = string.Join(MemberAccessSeparator, Path.Select(x => x.Name)); - } - - public IReadOnlyList Path { get; } + public IReadOnlyList Path { get; } = path; /// /// Gets the path without the very last element (the path of the object containing the ). @@ -43,7 +37,7 @@ public MemberPath(IReadOnlyList path) /// /// Gets the full name of the path (eg. A.B.C). /// - public string FullName { get; } + public string FullName { get; } = string.Join(MemberAccessSeparator, path.Select(x => x.Name)); /// /// Builds a member path skipping trailing path items which are non nullable. diff --git a/src/Riok.Mapperly/Symbols/MethodAccessorMember.cs b/src/Riok.Mapperly/Symbols/MethodAccessorMember.cs index ded1a701c1..3638c55106 100644 --- a/src/Riok.Mapperly/Symbols/MethodAccessorMember.cs +++ b/src/Riok.Mapperly/Symbols/MethodAccessorMember.cs @@ -4,33 +4,23 @@ namespace Riok.Mapperly.Symbols; -public class MethodAccessorMember : IMappableMember +public class MethodAccessorMember(IMappableMember mappableMember, string methodName, bool methodRequiresParameter = false) : IMappableMember { - private readonly IMappableMember _mappableMember; - private readonly string _methodName; - /// /// This member requires invocation with a parameter. /// - private readonly bool _methodRequiresParameter; - - public MethodAccessorMember(IMappableMember mappableMember, string methodName, bool methodRequiresParameter = false) - { - _mappableMember = mappableMember; - _methodName = methodName; - _methodRequiresParameter = methodRequiresParameter; - } - - public string Name => _mappableMember.Name; - public ITypeSymbol Type => _mappableMember.Type; - public ISymbol MemberSymbol => _mappableMember.MemberSymbol; - public bool IsNullable => _mappableMember.IsNullable; - public bool IsIndexer => _mappableMember.IsIndexer; - public bool CanGet => _mappableMember.CanGet; - public bool CanSet => _mappableMember.CanSet; - public bool CanSetDirectly => _mappableMember.CanSetDirectly; - public bool IsInitOnly => _mappableMember.IsInitOnly; - public bool IsRequired => _mappableMember.IsRequired; + private readonly bool _methodRequiresParameter = methodRequiresParameter; + + public string Name => mappableMember.Name; + public ITypeSymbol Type => mappableMember.Type; + public ISymbol MemberSymbol => mappableMember.MemberSymbol; + public bool IsNullable => mappableMember.IsNullable; + public bool IsIndexer => mappableMember.IsIndexer; + public bool CanGet => mappableMember.CanGet; + public bool CanSet => mappableMember.CanSet; + public bool CanSetDirectly => mappableMember.CanSetDirectly; + public bool IsInitOnly => mappableMember.IsInitOnly; + public bool IsRequired => mappableMember.IsRequired; public ExpressionSyntax BuildAccess(ExpressionSyntax source, bool nullConditional = false) { @@ -38,16 +28,16 @@ public ExpressionSyntax BuildAccess(ExpressionSyntax source, bool nullConditiona { // the receiver of the resulting ExpressionSyntax will add an invocation call with a parameter // src?.SetValue or src.SetValue - return nullConditional ? ConditionalAccess(source, _methodName) : MemberAccess(source, _methodName); + return nullConditional ? ConditionalAccess(source, methodName) : MemberAccess(source, methodName); } // src?.GetValue() or src.GetValue() - return nullConditional ? Invocation(ConditionalAccess(source, _methodName)) : Invocation(MemberAccess(source, _methodName)); + return nullConditional ? Invocation(ConditionalAccess(source, methodName)) : Invocation(MemberAccess(source, methodName)); } public override bool Equals(object? obj) => obj is MethodAccessorMember other - && SymbolEqualityComparer.IncludeNullability.Equals(_mappableMember.MemberSymbol, other.MemberSymbol); + && SymbolEqualityComparer.IncludeNullability.Equals(mappableMember.MemberSymbol, other.MemberSymbol); - public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(_mappableMember.MemberSymbol); + public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(mappableMember.MemberSymbol); } diff --git a/src/Riok.Mapperly/Symbols/PropertyMember.cs b/src/Riok.Mapperly/Symbols/PropertyMember.cs index 9ec35c6233..6a85b97de1 100644 --- a/src/Riok.Mapperly/Symbols/PropertyMember.cs +++ b/src/Riok.Mapperly/Symbols/PropertyMember.cs @@ -6,16 +6,9 @@ namespace Riok.Mapperly.Symbols; -internal class PropertyMember : IMappableMember +internal class PropertyMember(IPropertySymbol propertySymbol, SymbolAccessor symbolAccessor) : IMappableMember { - private readonly IPropertySymbol _propertySymbol; - private readonly SymbolAccessor _symbolAccessor; - - internal PropertyMember(IPropertySymbol propertySymbol, SymbolAccessor symbolAccessor) - { - _propertySymbol = propertySymbol; - _symbolAccessor = symbolAccessor; - } + private readonly IPropertySymbol _propertySymbol = propertySymbol; public string Name => _propertySymbol.Name; public ITypeSymbol Type => _propertySymbol.Type; @@ -24,14 +17,14 @@ internal PropertyMember(IPropertySymbol propertySymbol, SymbolAccessor symbolAcc public bool IsIndexer => _propertySymbol.IsIndexer; public bool CanGet => !_propertySymbol.IsWriteOnly - && (_propertySymbol.GetMethod == null || _symbolAccessor.IsAccessibleToMemberVisibility(_propertySymbol.GetMethod)); + && (_propertySymbol.GetMethod == null || symbolAccessor.IsAccessibleToMemberVisibility(_propertySymbol.GetMethod)); public bool CanSet => !_propertySymbol.IsReadOnly - && (_propertySymbol.SetMethod == null || _symbolAccessor.IsAccessibleToMemberVisibility(_propertySymbol.SetMethod)); + && (_propertySymbol.SetMethod == null || symbolAccessor.IsAccessibleToMemberVisibility(_propertySymbol.SetMethod)); public bool CanSetDirectly => !_propertySymbol.IsReadOnly - && (_propertySymbol.SetMethod == null || _symbolAccessor.IsDirectlyAccessible(_propertySymbol.SetMethod)); + && (_propertySymbol.SetMethod == null || symbolAccessor.IsDirectlyAccessible(_propertySymbol.SetMethod)); public bool IsInitOnly => _propertySymbol.SetMethod?.IsInitOnly == true;