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

MapProperty.Use: Default + non-default user mappings generate wrong (chained) mapping code #1254

Closed
InspiringCode opened this issue Apr 29, 2024 · 4 comments · Fixed by #1256
Labels
bug Something isn't working

Comments

@InspiringCode
Copy link

Consider the following classes:

public class Model
{
    public Length Length { get; set; }

    public Length Thickness { get; set; }
}

public class ModelDto
{
    public double LengthInMeter { get; set; }

    public double ThicknessInMillimeter { get; set; }
}

And the following mapper:

[Mapper]
public partial class DemoMapper
{
    [MapProperty("Length", "LengthInMeter", Use = nameof(ToMeters))]
    [MapProperty("Thickness", "ThicknessInMillimeter")]
    public partial ModelDto ToDto(Model source);

    // Here we just copied the attributes from 'ToDto' but accidentally
    // forget to change the mapping method from 'ToMeters' to its
    // inverse ('FromMeters'), which could easily happen in practice...
    [MapProperty("LengthInMeter", "Length", Use = nameof(ToMeters))]
    [MapProperty("ThicknessInMillimeter", "Thickness")]
    public partial Model ToModelWrong(ModelDto source);

    [MapProperty("LengthInMeter", "Length", Use = nameof(FromMeters))]
    [MapProperty("ThicknessInMillimeter", "Thickness")]
    public partial Model ToModelCorrect(ModelDto source);


    // 95% of all Length properties are in millimeters, so we use this as default
    public double ToMillimeters(Length length) => length.Millimeters;
    public Length FromMillimeters(double valueInMm) => Length.FromMillimeters(valueInMm);

    [UserMapping(Default = false)]
    public double ToMeters(Length length) => length.Meters;
    [UserMapping(Default = false)]
    public Length FromMeters(double length) => Length.FromMeters(length);
}

In ToModelWrong we want to convert a double to Length, but we explicitly specify a mapping method that converts from Length to double (ToMeters). Since we also have a default mapping method that converts double to Length (FromMillimeters), Mapperly generates the following mapping (double -> Length, Length -> double, double -> Length):

target.Length = FromMillimeters(ToMeters(FromMillimeters(source.LengthInMeter)));

But this is obviously very wrong and unexpected. In this case I would expect an error from Mapperly because I explicitly specified a mapping method that has an incompatible signature.

@InspiringCode InspiringCode added the bug Something isn't working label Apr 29, 2024
@latonz
Copy link
Contributor

latonz commented Apr 29, 2024

Mapperly tries to map these types to compatible types. As this behaviour is already released in a stable version and may also be useful in some scenarios we cannot remove it completely anymore. I still understand your point. I think we should introduce a compile time warning whenever a MapPropertyAttribute.Use mapping has incompatible types.

@latonz latonz changed the title Default + non-default user mappings generate wrong (chained) mapping code MapProperty.Use: Default + non-default user mappings generate wrong (chained) mapping code Apr 29, 2024
@InspiringCode
Copy link
Author

@latonz Sounds reasonable. Users can then change the Analyzer Rule ID severity to Error or none, depending on their preference.

Copy link

github-actions bot commented May 3, 2024

🎉 This issue has been resolved in version 3.6.0-next.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This issue has been resolved in version 3.6.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants