Nullable disabled target: An item with the same key has already been added.
See original GitHub issueFirst of all, thank you for an awesome mapper! Keep up the good work 😀
Describe the bug
warning CS8785: Generator 'MapperGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'ArgumentException' with message 'An item with the same key has already been added.
I’ll try to explain, but its maybe easier to fire up the debugger yourselves with this repo, as the bug is a bit complex.
The code flow ends up trying to add (string, string)
twice to the mappers dictionary.
First it adds the mapping (string, string)
correctly.
Then, trying to add mapping between the List<string>
, since the target dto is flagged #nullable disable
, it correctly calls FindOrBuildMapping(string, string?)
This method again runs the FindMapping(string, string?)
, and correctly returns that there are no existing mappings for (string, string?)
.
Then the BuildDelegateMapping(null, string, string?)
method runs, and results in the NullableMappingBuilder
returns here: https://github.com/riok/mapperly/blob/fdde1270d5a0d7d0a4c4794509b15a5a956266f8/src/Riok.Mapperly/Descriptors/MappingBuilder/NullableMappingBuilder.cs#L15-L18
This changes the mapping to (string, string)
. There is not any new check if this mapping already exists, and the _mappings.Add()
throws the exception.
To Reproduce Build this repo: https://github.com/stigrune/BugReport.Mapperly Look at build output.
Code snippets Added personal comments to the code from DescriptorBuilder.cs
public TypeMapping? FindOrBuildMapping(
ITypeSymbol sourceType,
ITypeSymbol targetType)
{
// (string, string?) here, and it does not exists.
if (FindMapping(sourceType, targetType) is { } foundMapping)
return foundMapping;
// Inside the BuildDelegateMapping, NullableMappingBuilder ends up changing the target from string? to string.
if (BuildDelegateMapping(null, sourceType, targetType) is not { } mapping)
return null;
// mapping is (string, string) here, and this already exists.
AddMapping(mapping);
return mapping;
}
Environment (please complete the following information):
- Mapperly Version: 2.3.1
- .NET Version: 6.0.302
- Target Framework: net6.0
- OS: Windows
A quick obvious fix is to recheck if the mapping exists just before trying to add it to the dictionary. This might be the best way to fix it if other MappingBuilders also modify the source or targets?
Reply with a description of the desired fix, and I’ll happily try to help out and submit a PR 😀 Edit: Fixed typo and mix-up between what is source and target types.
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:10 (5 by maintainers)
Top GitHub Comments
In the meantime I could fix the bug 😊 Let me know if the fix in the released version 2.3.2 of Mapperly does not work for you. Enjoy your vacation! 🏝️
Thank you for the extensive bug report! I think the root cause here is that the
NullableMappingBuilder
createsTypeMapping
’s of which the types are different from the actual types it was asked to map. I think the way to go would be to implement a newDelegateMapping
/DelegateMethodMapping
which wraps the non nullable mapping into the correct nullable types. I’ll fix this when I find the time. Would also be very happy to accept a PR