Skip to content

Commit

Permalink
chore: Enable Nullable on YamlSerialization project (#10421)
Browse files Browse the repository at this point in the history
chore-enable nullable for YamlSerialization project
  • Loading branch information
filzrev authored Nov 27, 2024
1 parent 8704b50 commit ee3aa53
Show file tree
Hide file tree
Showing 20 changed files with 144 additions and 133 deletions.
4 changes: 4 additions & 0 deletions src/Docfx.YamlSerialization/Docfx.YamlSerialization.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="YamlDotNet" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/Docfx.YamlSerialization/ExtensibleMemberAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public sealed class ExtensibleMemberAttribute : Attribute
public string Prefix { get; }

public ExtensibleMemberAttribute()
: this(null)
: this(string.Empty)
{
}

public ExtensibleMemberAttribute(string prefix)
{
Prefix = prefix ?? string.Empty;
Prefix = prefix;
}
}
2 changes: 1 addition & 1 deletion src/Docfx.YamlSerialization/Helpers/ReflectionUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Docfx.YamlSerialization.Helpers;

internal static class ReflectionUtility
{
public static Type GetImplementedGenericInterface(Type type, Type genericInterfaceType)
public static Type? GetImplementedGenericInterface(Type type, Type genericInterfaceType)
{
foreach (var interfaceType in GetImplementedInterfaces(type))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ namespace Docfx.YamlSerialization.NodeDeserializers;
public class EmitArrayNodeDeserializer : INodeDeserializer
{
private static readonly MethodInfo DeserializeHelperMethod =
typeof(EmitArrayNodeDeserializer).GetMethod(nameof(DeserializeHelper));
private static readonly ConcurrentDictionary<Type, Func<IParser, Type, Func<IParser, Type, object>, object>> _funcCache =
typeof(EmitArrayNodeDeserializer).GetMethod(nameof(DeserializeHelper))!;
private static readonly ConcurrentDictionary<Type, Func<IParser, Type, Func<IParser, Type, object?>, object?>> _funcCache =
new();

bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value)
{
if (!expectedType.IsArray)
{
Expand All @@ -31,22 +31,22 @@ bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IPars
}

[EditorBrowsable(EditorBrowsableState.Never)]
public static TItem[] DeserializeHelper<TItem>(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer)
public static TItem[] DeserializeHelper<TItem>(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer)
{
var items = new List<TItem>();
EmitGenericCollectionNodeDeserializer.DeserializeHelper(reader, expectedType, nestedObjectDeserializer, items);
return items.ToArray();
}

private static Func<IParser, Type, Func<IParser, Type, object>, object> AddItem(Type expectedType)
private static Func<IParser, Type, Func<IParser, Type, object?>, object?> AddItem(Type expectedType)
{
var dm = new DynamicMethod(string.Empty, typeof(object), [typeof(IParser), typeof(Type), typeof(Func<IParser, Type, object>)]);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Call, DeserializeHelperMethod.MakeGenericMethod(expectedType.GetElementType()));
il.Emit(OpCodes.Call, DeserializeHelperMethod.MakeGenericMethod(expectedType.GetElementType()!));
il.Emit(OpCodes.Ret);
return (Func<IParser, Type, Func<IParser, Type, object>, object>)dm.CreateDelegate(typeof(Func<IParser, Type, Func<IParser, Type, object>, object>));
return (Func<IParser, Type, Func<IParser, Type, object?>, object?>)dm.CreateDelegate(typeof(Func<IParser, Type, Func<IParser, Type, object?>, object?>));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ namespace Docfx.YamlSerialization.NodeDeserializers;
public class EmitGenericCollectionNodeDeserializer : INodeDeserializer
{
private static readonly MethodInfo DeserializeHelperMethod =
typeof(EmitGenericCollectionNodeDeserializer).GetMethod(nameof(DeserializeHelper));
typeof(EmitGenericCollectionNodeDeserializer).GetMethod(nameof(DeserializeHelper))!;
private readonly IObjectFactory _objectFactory;
private readonly Dictionary<Type, Type> _gpCache =
private readonly Dictionary<Type, Type?> _gpCache =
new();
private readonly Dictionary<Type, Action<IParser, Type, Func<IParser, Type, object>, object>> _actionCache =
private readonly Dictionary<Type, Action<IParser, Type, Func<IParser, Type, object?>, object?>> _actionCache =
new();

public EmitGenericCollectionNodeDeserializer(IObjectFactory objectFactory)
{
_objectFactory = objectFactory;
}

bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value)
{
if (!_gpCache.TryGetValue(expectedType, out Type gp))
if (!_gpCache.TryGetValue(expectedType, out var gp))
{
var collectionType = ReflectionUtility.GetImplementedGenericInterface(expectedType, typeof(ICollection<>));
if (collectionType != null)
Expand Down Expand Up @@ -66,7 +66,7 @@ bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IPars
il.Emit(OpCodes.Castclass, typeof(ICollection<>).MakeGenericType(gp));
il.Emit(OpCodes.Call, DeserializeHelperMethod.MakeGenericMethod(gp));
il.Emit(OpCodes.Ret);
action = (Action<IParser, Type, Func<IParser, Type, object>, object>)dm.CreateDelegate(typeof(Action<IParser, Type, Func<IParser, Type, object>, object>));
action = (Action<IParser, Type, Func<IParser, Type, object?>, object?>)dm.CreateDelegate(typeof(Action<IParser, Type, Func<IParser, Type, object?>, object?>));
_actionCache[gp] = action;
}

Expand All @@ -75,13 +75,11 @@ bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IPars
}

[EditorBrowsable(EditorBrowsableState.Never)]
public static void DeserializeHelper<TItem>(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, ICollection<TItem> result)
public static void DeserializeHelper<TItem>(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, ICollection<TItem> result)
{
reader.Consume<SequenceStart>();
while (!reader.Accept<SequenceEnd>(out _))
{
var current = reader.Current;

var value = nestedObjectDeserializer(reader, typeof(TItem));
if (value is not IValuePromise promise)
{
Expand All @@ -90,11 +88,12 @@ public static void DeserializeHelper<TItem>(IParser reader, Type expectedType, F
else if (result is IList<TItem> list)
{
var index = list.Count;
result.Add(default);
result.Add(default!);
promise.ValueAvailable += v => list[index] = TypeConverter.ChangeType<TItem>(v, NullNamingConvention.Instance);
}
else
{
var current = reader.Current!;
throw new ForwardAnchorNotSupportedException(
current.Start,
current.End,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ namespace Docfx.YamlSerialization.NodeDeserializers;
public class EmitGenericDictionaryNodeDeserializer : INodeDeserializer
{
private static readonly MethodInfo DeserializeHelperMethod =
typeof(EmitGenericDictionaryNodeDeserializer).GetMethod(nameof(DeserializeHelper));
typeof(EmitGenericDictionaryNodeDeserializer).GetMethod(nameof(DeserializeHelper))!;
private readonly IObjectFactory _objectFactory;
private readonly Dictionary<Type, Type[]> _gpCache =
private readonly Dictionary<Type, Type[]?> _gpCache =
new();
private readonly Dictionary<Tuple<Type, Type>, Action<IParser, Type, Func<IParser, Type, object>, object>> _actionCache =
private readonly Dictionary<Tuple<Type, Type>, Action<IParser, Type, Func<IParser, Type, object?>, object?>> _actionCache =
new();

public EmitGenericDictionaryNodeDeserializer(IObjectFactory objectFactory)
{
_objectFactory = objectFactory;
}

bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value)
{
if (!_gpCache.TryGetValue(expectedType, out Type[] gp))
if (!_gpCache.TryGetValue(expectedType, out var gp))
{
var dictionaryType = ReflectionUtility.GetImplementedGenericInterface(expectedType, typeof(IDictionary<,>));
if (dictionaryType != null)
Expand Down Expand Up @@ -67,7 +67,7 @@ bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IPars
il.Emit(OpCodes.Castclass, typeof(IDictionary<,>).MakeGenericType(gp));
il.Emit(OpCodes.Call, DeserializeHelperMethod.MakeGenericMethod(gp));
il.Emit(OpCodes.Ret);
action = (Action<IParser, Type, Func<IParser, Type, object>, object>)dm.CreateDelegate(typeof(Action<IParser, Type, Func<IParser, Type, object>, object>));
action = (Action<IParser, Type, Func<IParser, Type, object?>, object?>)dm.CreateDelegate(typeof(Action<IParser, Type, Func<IParser, Type, object?>, object?>));
_actionCache[cacheKey] = action;
}
action(reader, expectedType, nestedObjectDeserializer, value);
Expand All @@ -78,7 +78,7 @@ bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IPars
}

[EditorBrowsable(EditorBrowsableState.Never)]
public static void DeserializeHelper<TKey, TValue>(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, IDictionary<TKey, TValue> result)
public static void DeserializeHelper<TKey, TValue>(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, IDictionary<TKey, TValue> result)
{
while (!reader.Accept<MappingEnd>(out _))
{
Expand All @@ -92,20 +92,20 @@ public static void DeserializeHelper<TKey, TValue>(IParser reader, Type expected
if (valuePromise == null)
{
// Happy path: both key and value are known
result[(TKey)key] = (TValue)value;
result[(TKey)key!] = (TValue)value!;
}
else
{
// Key is known, value is pending
valuePromise.ValueAvailable += v => result[(TKey)key] = (TValue)v;
valuePromise.ValueAvailable += v => result[(TKey)key!] = (TValue)v!;
}
}
else
{
if (valuePromise == null)
{
// Key is pending, value is known
keyPromise.ValueAvailable += v => result[(TKey)v] = (TValue)value;
keyPromise.ValueAvailable += v => result[(TKey)v!] = (TValue)value!;
}
else
{
Expand All @@ -116,7 +116,7 @@ public static void DeserializeHelper<TKey, TValue>(IParser reader, Type expected
{
if (hasFirstPart)
{
result[(TKey)v] = (TValue)value;
result[(TKey)v!] = (TValue)value!;
}
else
{
Expand All @@ -129,7 +129,7 @@ public static void DeserializeHelper<TKey, TValue>(IParser reader, Type expected
{
if (hasFirstPart)
{
result[(TKey)key] = (TValue)v;
result[(TKey)key] = (TValue)v!;
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public ExtensibleObjectNodeDeserializer(IObjectFactory objectFactory, ITypeInspe
_ignoreUnmatched = ignoreUnmatched;
}

bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
bool INodeDeserializer.Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value)
{
if (!reader.TryConsume<MappingStart>(out _))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Docfx.YamlSerialization.NodeTypeResolvers;

internal sealed class ScalarYamlNodeTypeResolver : INodeTypeResolver
{
bool INodeTypeResolver.Resolve(NodeEvent nodeEvent, ref Type currentType)
bool INodeTypeResolver.Resolve(NodeEvent? nodeEvent, ref Type currentType)
{
if (currentType == typeof(string) || currentType == typeof(object))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ namespace Docfx.YamlSerialization.ObjectDescriptors;

public class BetterObjectDescriptor : IObjectDescriptor
{
public BetterObjectDescriptor(object value, Type type, Type staticType)
public BetterObjectDescriptor(object? value, Type type, Type staticType)
: this(value, type, staticType, ScalarStyle.Any)
{
}

public BetterObjectDescriptor(object value, Type type, Type staticType, ScalarStyle scalarStyle)
public BetterObjectDescriptor(object? value, Type type, Type staticType, ScalarStyle scalarStyle)
{
Value = value;
Type = type;
StaticType = staticType;
ScalarStyle = scalarStyle == ScalarStyle.Any && NeedQuote(value) ? ScalarStyle.DoubleQuoted : scalarStyle;

static bool NeedQuote(object val)
static bool NeedQuote(object? val)
{
if (val is not string s)
if (val is not string s || s == null)
return false;

return Regexes.BooleanLike().IsMatch(s)
Expand All @@ -42,5 +42,5 @@ static bool NeedQuote(object val)

public Type Type { get; }

public object Value { get; }
public object? Value { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public class DefaultEmitObjectFactory : ObjectFactoryBase

public override object Create(Type type)
{
if (!_cache.TryGetValue(type, out Func<object> func))
if (!_cache.TryGetValue(type, out var func))
{
var realType = type;
if (type is {IsInterface: true, IsGenericType: true})
if (type is { IsInterface: true, IsGenericType: true })
{
var def = type.GetGenericTypeDefinition();
var args = type.GetGenericArguments();
Expand Down Expand Up @@ -46,7 +46,12 @@ public override object Create(Type type)
{
func = CreateValueTypeFactory(type);
}
_cache[type] = func;
else
{
throw new InvalidOperationException($"Failed to gets type instance create func for type: {type.FullName}.");
}

_cache[type] = func!;
}
return func();
}
Expand All @@ -56,7 +61,7 @@ private static Func<object> CreateReferenceTypeFactory(ConstructorInfo ctor)
var dm = new DynamicMethod(string.Empty, typeof(object), EmptyTypes);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Newobj, ctor);
if (ctor.DeclaringType.IsValueType)
if (ctor.DeclaringType!.IsValueType)
{
il.Emit(OpCodes.Box, ctor.DeclaringType);
}
Expand Down
Loading

0 comments on commit ee3aa53

Please sign in to comment.