diff --git a/YamlDotNet.Analyzers.StaticGenerator/ClassSyntaxReceiver.cs b/YamlDotNet.Analyzers.StaticGenerator/ClassSyntaxReceiver.cs index 8a527c58..a9cedb9d 100644 --- a/YamlDotNet.Analyzers.StaticGenerator/ClassSyntaxReceiver.cs +++ b/YamlDotNet.Analyzers.StaticGenerator/ClassSyntaxReceiver.cs @@ -94,30 +94,40 @@ private void AddSerializableClass(INamedTypeSymbol? classSymbol) if (member is IPropertySymbol propertySymbol) { - classObject.PropertySymbols.Add(propertySymbol); - CheckForSupportedGeneric(propertySymbol.Type); + if (!classObject.PropertySymbols.ContainsName(propertySymbol)) + { + classObject.PropertySymbols.Add(propertySymbol); + CheckForSupportedGeneric(propertySymbol.Type); + } } else if (member is IFieldSymbol fieldSymbol) { - classObject.FieldSymbols.Add(fieldSymbol); - CheckForSupportedGeneric(fieldSymbol.Type); + if (!classObject.FieldSymbols.ContainsName(fieldSymbol)) + { + classObject.FieldSymbols.Add(fieldSymbol); + CheckForSupportedGeneric(fieldSymbol.Type); + } } else if (member is IMethodSymbol methodSymbol) { var methodAttributes = methodSymbol.GetAttributes(); - if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnDeserializedAttribute")) + if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnDeserializedAttribute") + && !classObject.OnDeserializedMethods.ContainsName(methodSymbol)) { classObject.OnDeserializedMethods.Add(methodSymbol); } - if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnDeserializingAttribute")) + if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnDeserializingAttribute") + && !classObject.OnDeserializingMethods.ContainsName(methodSymbol)) { classObject.OnDeserializingMethods.Add(methodSymbol); } - if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnSerializedAttribute")) + if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnSerializedAttribute") + && !classObject.OnSerializedMethods.ContainsName(methodSymbol)) { classObject.OnSerializedMethods.Add(methodSymbol); } - if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnSerializingAttribute")) + if (methodAttributes.Any(x => x.AttributeClass!.ToDisplayString() == "YamlDotNet.Serialization.Callbacks.OnSerializingAttribute") + && !classObject.OnSerializingMethods.ContainsName(methodSymbol)) { classObject.OnSerializingMethods.Add(methodSymbol); } @@ -146,10 +156,12 @@ private void CheckForSupportedGeneric(ITypeSymbol type) else if (typeName.StartsWith("System.Collections.Generic.Dictionary")) { Classes.Add(sanitizedTypeName, new ClassObject(sanitizedTypeName, (INamedTypeSymbol)type, true)); + CheckForSupportedGeneric(((INamedTypeSymbol)type).TypeArguments[1]); } else if (typeName.StartsWith("System.Collections.Generic.List")) { Classes.Add(sanitizedTypeName, new ClassObject(sanitizedTypeName, (INamedTypeSymbol)type, isList: true)); + CheckForSupportedGeneric(((INamedTypeSymbol)type).TypeArguments[0]); } } } diff --git a/YamlDotNet.Analyzers.StaticGenerator/SymbolCollectionExtensions.cs b/YamlDotNet.Analyzers.StaticGenerator/SymbolCollectionExtensions.cs new file mode 100644 index 00000000..390fb944 --- /dev/null +++ b/YamlDotNet.Analyzers.StaticGenerator/SymbolCollectionExtensions.cs @@ -0,0 +1,36 @@ +// This file is part of YamlDotNet - A .NET library for YAML. +// Copyright (c) Antoine Aubry and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace YamlDotNet.Analyzers.StaticGenerator +{ + static class SymbolCollectionExtensions + { + public static bool ContainsName(this IEnumerable enumerable, T symbol) + where T : ISymbol + { + return enumerable.Any(t => t.Name == symbol.Name); + } + } +} diff --git a/YamlDotNet.Analyzers.StaticGenerator/SymbolExtensions.cs b/YamlDotNet.Analyzers.StaticGenerator/SymbolExtensions.cs index 91e8c470..ce2ba3d3 100644 --- a/YamlDotNet.Analyzers.StaticGenerator/SymbolExtensions.cs +++ b/YamlDotNet.Analyzers.StaticGenerator/SymbolExtensions.cs @@ -121,6 +121,9 @@ static string GetGenericTypes(IReadOnlyList typeArguments) case ITypeParameterSymbol typeParameterSymbol: output.Add(typeParameterSymbol.Name + typeParameterSymbol.GetNullable()); break; + case IArrayTypeSymbol arrayTypeSymbol: + output.Add(GetFullName(arrayTypeSymbol.ElementType) + "[]"); + break; default: throw new NotSupportedException($"Cannot generate type name from type argument {argument.GetType().FullName}"); } diff --git a/YamlDotNet.Core7AoTCompileTest/Program.cs b/YamlDotNet.Core7AoTCompileTest/Program.cs index 9e8a4123..254c4368 100644 --- a/YamlDotNet.Core7AoTCompileTest/Program.cs +++ b/YamlDotNet.Core7AoTCompileTest/Program.cs @@ -61,6 +61,13 @@ MyDictionary: x: y a: b +MyDictionaryOfArrays: + a: + - a + - b + b: + - c + - d MyList: - a - b @@ -117,6 +124,15 @@ } } +Console.WriteLine("MyDictionaryOfArrays == null: <{0}>", x.MyDictionaryOfArrays == null); +if (x.MyDictionaryOfArrays != null) +{ + foreach (var kvp in x.MyDictionaryOfArrays) + { + Console.WriteLine("MyDictionaryOfArrays[{0}] = <{1}>", kvp.Key, string.Join(',', kvp.Value)); + } +} + Console.WriteLine("MyList == null: <{0}>", x.MyList == null); if (x.MyList != null) { @@ -191,6 +207,7 @@ public class PrimitiveTypes public Inner[]? InnerArray { get; set; } public MyArray? MyArray { get; set; } public Dictionary? MyDictionary { get; set; } + public Dictionary? MyDictionaryOfArrays { get; set; } public List? MyList { get; set; } public Inherited Inherited { get; set; } public ExternalModel External { get; set; }