Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for From and To method conversions (#1117) #1616

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

TonEnfer
Copy link

@TonEnfer TonEnfer commented Nov 30, 2024

Add support for From and To method conversions (#1117)

Description

  • Added support for conversion by calling the ToTTarget method on the source object
  • Added support for conversion by calling the static Create, CreateFrom, FromTSource methods on the integer type, as well as by calling the static ToTTarget method on the source type

Despite the discussion in the issue, the ToString mapping builder remains untouched as it contains a lot of logic.
Instead, the new mapping builder eliminates the mapping to string.

The previously existing mapping builders for DateTime mapping have been removed, as their role is now performed by the new mapping builder for static methods.
However, MappingConversionType has only been extended, the previously existing MappingConversionType.DateTimeToDateOnly and MappingConversionType.DateTimeToTimeOnly are left for backward compatibility, their processing has been moved to the new mapping builder

Fixes #1117

Checklist

  • The existing code style is followed
  • The commit message follows our guidelines
  • Performed a self-review of my code
  • Hard-to-understand areas of my code are commented
  • The documentation is updated (as applicable)
  • Unit tests are added/updated
  • Integration tests are added/updated (as applicable, especially if feature/bug depends on roslyn or framework version in use)

@TonEnfer TonEnfer marked this pull request as ready for review November 30, 2024 06:51
@TonEnfer TonEnfer force-pushed the #1117_Support_From_and_To_static_factory_methods branch from 22527b1 to 2d82323 Compare December 1, 2024 05:06
@latonz latonz added the enhancement New feature or request label Dec 2, 2024
Copy link
Contributor

@latonz latonz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR! I’m excited to see this feature added to Mapperly. I’ve shared my feedback 😊

Comment on lines +12 to +28
//checks for backward compatibility

if (IsDateTimeToDateOnlyConversion(ctx))
{
if (!ctx.IsConversionEnabled(MappingConversionType.DateTimeToDateOnly))
return null;
}
else if (IsDateTimeToTimeOnlyConversion(ctx))
{
if (!ctx.IsConversionEnabled(MappingConversionType.DateTimeToTimeOnly))
return null;
}
else
{
if (!ctx.IsConversionEnabled(MappingConversionType.StaticConvertMethods))
return null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it could make sense to extract this into a method IsConversionEnabled(ctx)

&& ctx.Types.DateOnly != null
&& ctx.Target is INamedTypeSymbol namedSymbol
&& SymbolEqualityComparer.Default.Equals(namedSymbol, ctx.Types.DateOnly)
|| true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this || true really required? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. I have no idea where this came from 🤦

var methodCandidates = ctx
.SymbolAccessor.GetAllMethods(ctx.Source, methodName)
.Where(x => x is { IsStatic: false, ReturnsVoid: false, IsAsync: false, Parameters.Length: 0 })
.ToArray();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we opt for ToList in similar scenarios (AFAIK it performs a little better than ToArray if the source count is unknown). Is there a reason you used ToArray? The same question applies at several places in this PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason I chose ToArray is because the list is not mutable and should not be mutable further down the code.
I'll change it to ToList since it works better.

Comment on lines +185 to +188
if (!ctx.Source.IsArrayType(out var arrayType))
yield return $"{from}{ctx.Source.Name}";
else
yield return $"{from}{arrayType.ElementType.Name}Array";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be logical to also try $"{create}{from}{ctx.Source.Name}"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right, I will add this

Comment on lines +55 to +57
else
{
if (ctx.Source is INamedTypeSymbol { TypeArguments.Length: 1 } namedTypeSymbol)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a simple else if clause, couldn't it?


private static bool FilterParameterType(IParameterSymbol parameter, ITypeSymbol targetType)
{
if (SymbolEqualityComparer.Default.Equals(parameter.Type, targetType))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this include nullability?

Comment on lines +161 to +167
if (parameter.Type.IsArrayType(out var arrayTypeSymbol))
{
return SymbolEqualityComparer.Default.Equals(
arrayTypeSymbol.ElementType,
targetIsArray ? targetArrayTypeSymbol!.ElementType : targetType
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This early return could happen before the enumerable check of the target, couldn't it?

Comment on lines +161 to +167
if (parameter.Type.IsArrayType(out var arrayTypeSymbol))
{
return SymbolEqualityComparer.Default.Equals(
arrayTypeSymbol.ElementType,
targetIsArray ? targetArrayTypeSymbol!.ElementType : targetType
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this section really required? If the target type is an array and the source type matches it, it should already be handled... If it is some other collection type it is handled later on anyway...

Comment on lines +172 to +174
return targetIsEnumerable
? parameter.Type.AllInterfaces.Intersect(targetType.AllInterfaces, SymbolEqualityComparer.Default).Any()
: SymbolEqualityComparer.Default.Equals(((INamedTypeSymbol)parameter.Type)?.TypeArguments[0], targetType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't SymbolAccessor.CanAssign be used here?


if (!nonNullableTarget.IsArrayType(out var arrayType))
{
return $"To{nonNullableTarget.Name}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBD (same for the static one): Would it make sense to also support language keyword names (e.g. ToInt instead of only ToInt32 etc.)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that would make sense, but I don't know how I would get language keyword names. Could you give me a hint?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is an easy way to do this, you may need to handle it with a dictionary or a switch...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support From and To static factory methods
2 participants