cezarypiatek / MappingGenerator

:arrows_counterclockwise: "AutoMapper" like, Roslyn based, code fix provider that allows to generate mapping code in design time.
https://marketplace.visualstudio.com/items?itemName=54748ff9-45fc-43c2-8ec5-cf7912bc3b84.mappinggenerator
MIT License
1.03k stars 119 forks source link

ValueCollection appears to cause crash on Quick Action #161

Closed antmeehan closed 3 years ago

antmeehan commented 3 years ago

Mapping Generator Version v1.21.15

Mapping Generator distribution VSExtension

IDE type and version Microsoft Visual Studio Professional 2019 Version 16.8.4 VisualStudio.16.Release/16.8.4+30907.101

Describe the incorrect behavior When invoking the Quick Action menu on a CS0029 C# Cannot implicitly convert type squiggle which is a Dictionary<T,K>.ValueCollection the MappingGenerator extension crashes with the following stack trace:

System.IndexOutOfRangeException : Index was outside the bounds of the array. at MappingGenerator.Mappings.MappingHelper.GetElementType(ITypeSymbol collectionType) at async MappingGenerator.Mappings.MappingEngine.MapCollectionsAsync() at async MappingGenerator.Mappings.MappingEngine.TryToCreateMappingExpression() at async MappingGenerator.Mappings.MappingEngine.MapExpression() at async MappingGenerator.Mappings.MappingEngine.MapExpression() at async MappingGenerator.Features.CodeFixes.ExplicitConversionCodeFixProvider.GenerateExplicitConversion() at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetChangedSolutionAsync() at async Microsoft.CodeAnalysis.CodeActions.CodeAction.ComputeOperationsAsync() at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetPreviewOperationsAsync() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.GetPreviewResultAsync() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.<>c__DisplayClass11_0.b__0() at async Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformFunctionAsync[T]()

Here is some example code to reproduce:

public class Source { }
public class Destination { }

public IEnumerable<Destination> Example(Dictionary<string, Source> source)
{
    return source.Values;
}

Describe the expected behavior Would expect either no suggestion from MappingGenerator, or even better it can create mapping from the ValueCollection.

Screenshots image

image

cezarypiatek commented 3 years ago

Hi @antmeehan

This should be fixed in v1.22. Would you mind testing the fix and letting me know it that works for you as expected?

Please also consider supporting MappingGenerator project. Thanks!

antmeehan commented 3 years ago

Thanks @cezarypiatek for the fast response! I'm very impressed with your DevOps process too.

The fix stops the crash now, but the mapping doesn't occur as I would expect. Eg.

public class Source
{
    public string A { get; set; }
}

public class Destination
{
    public string A { get; set; }
}

public IEnumerable<Destination> Example(Dictionary<string, Source> source)
{
    return source.Values;
}

gets changed to:

public IEnumerable<Destination> Example(Dictionary<string, Source> source)
{
    return source.Values.Select(sourceValue => new Destination());
}

But I would expect:

public IEnumerable<Destination> Example(Dictionary<string, Source> source)
{
    return source.Values.Select(sourceValue => new Destination()
    {
        A = sourceValue.A
    });
}
cezarypiatek commented 3 years ago

HI @antmeehan

Apologies, my mistake. Please check v1.22.1 (should be released shortly)