Skip to content

Commit

Permalink
Add support for serializing Dictionary<TKey,TValue[]> and List<T[]>
Browse files Browse the repository at this point in the history
  • Loading branch information
prochnowc committed Oct 5, 2023
1 parent 75f4010 commit 1b8d324
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 8 deletions.
28 changes: 20 additions & 8 deletions YamlDotNet.Analyzers.StaticGenerator/ClassSyntaxReceiver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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]);
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions YamlDotNet.Analyzers.StaticGenerator/SymbolCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -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<T>(this IEnumerable<T> enumerable, T symbol)
where T : ISymbol
{
return enumerable.Any(t => t.Name == symbol.Name);
}
}
}
3 changes: 3 additions & 0 deletions YamlDotNet.Analyzers.StaticGenerator/SymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ static string GetGenericTypes(IReadOnlyList<ITypeSymbol> 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}");
}
Expand Down
17 changes: 17 additions & 0 deletions YamlDotNet.Core7AoTCompileTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@
MyDictionary:
x: y
a: b
MyDictionaryOfArrays:
a:
- a
- b
b:
- c
- d
MyList:
- a
- b
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -191,6 +207,7 @@ public class PrimitiveTypes
public Inner[]? InnerArray { get; set; }
public MyArray? MyArray { get; set; }
public Dictionary<string, string>? MyDictionary { get; set; }
public Dictionary<string, string[]>? MyDictionaryOfArrays { get; set; }
public List<string>? MyList { get; set; }
public Inherited Inherited { get; set; }
public ExternalModel External { get; set; }
Expand Down

0 comments on commit 1b8d324

Please sign in to comment.