Fix compiler warnings about nullables

Remove obsolete support of .Net framework 2.0
This commit is contained in:
Peter Kirmeier 2023-04-16 20:45:21 +02:00
parent c9ce4d1d21
commit 1d29fea766

View file

@ -4,8 +4,10 @@
namespace SystemTrayMenu.Helpers.Updater namespace SystemTrayMenu.Helpers.Updater
{ {
// The MIT License (MIT)
// Copyright (c) 2018 Alex Parker // Copyright (c) 2018 Alex Parker
// Copyright (c) 2018-2019 Peter Kirmeier // Copyright (c) 2018-2023 Peter Kirmeier
// Permission is hereby granted, free of charge, to any person obtaining a copy of // 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 // this software and associated documentation files (the "Software"), to deal in
@ -50,23 +52,20 @@ namespace SystemTrayMenu.Helpers.Updater
public static class JSONParser public static class JSONParser
{ {
[ThreadStatic] [ThreadStatic]
private static Stack<List<string>> splitArrayPool; private static Stack<List<string>>? splitArrayPool;
[ThreadStatic] [ThreadStatic]
private static StringBuilder stringBuilder; private static StringBuilder? stringBuilder;
[ThreadStatic] [ThreadStatic]
private static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache; private static Dictionary<Type, Dictionary<string, FieldInfo>>? fieldInfoCache;
[ThreadStatic] [ThreadStatic]
private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache; private static Dictionary<Type, Dictionary<string, PropertyInfo>>? propertyInfoCache;
public static T FromJson<T>(this string json) public static T? FromJson<T>(this string json)
{ {
// Initialize, if needed, the ThreadStatic variables // Initialize, if needed, the ThreadStatic variables
propertyInfoCache ??= new Dictionary<Type, Dictionary<string, PropertyInfo>>(); propertyInfoCache ??= new Dictionary<Type, Dictionary<string, PropertyInfo>>();
fieldInfoCache ??= new Dictionary<Type, Dictionary<string, FieldInfo>>(); fieldInfoCache ??= new Dictionary<Type, Dictionary<string, FieldInfo>>();
stringBuilder ??= new StringBuilder(); stringBuilder ??= new StringBuilder();
splitArrayPool ??= new Stack<List<string>>(); splitArrayPool ??= new Stack<List<string>>();
// Remove all whitespace not within strings to make parsing simpler // Remove all whitespace not within strings to make parsing simpler
@ -89,11 +88,17 @@ namespace SystemTrayMenu.Helpers.Updater
} }
// Parse the thing! // Parse the thing!
return (T)ParseValue(typeof(T), stringBuilder.ToString()); return (T?)ParseValue(typeof(T), stringBuilder.ToString());
} }
internal static object ParseValue(Type type, string json) internal static object? ParseValue(Type type, string json)
{ {
// Initialize, if needed, the ThreadStatic variables
propertyInfoCache ??= new Dictionary<Type, Dictionary<string, PropertyInfo>>();
fieldInfoCache ??= new Dictionary<Type, Dictionary<string, FieldInfo>>();
stringBuilder ??= new StringBuilder();
splitArrayPool ??= new Stack<List<string>>();
if (type == typeof(string)) if (type == typeof(string))
{ {
if (json.Length <= 2) if (json.Length <= 2)
@ -167,7 +172,7 @@ namespace SystemTrayMenu.Helpers.Updater
if (type.IsArray) if (type.IsArray)
{ {
Type arrayType = type.GetElementType(); Type arrayType = type.GetElementType() !;
if (json[0] != '[' || json[^1] != ']') if (json[0] != '[' || json[^1] != ']')
{ {
return null; return null;
@ -193,7 +198,12 @@ namespace SystemTrayMenu.Helpers.Updater
} }
List<string> elems = Split(json); List<string> elems = Split(json);
var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count }); var list = (IList?)type.GetConstructor(new Type[] { typeof(int) })?.Invoke(new object[] { elems.Count });
if (list == null)
{
return null;
}
for (int i = 0; i < elems.Count; i++) for (int i = 0; i < elems.Count; i++)
{ {
list.Add(ParseValue(listType, elems[i])); list.Add(ParseValue(listType, elems[i]));
@ -231,7 +241,12 @@ namespace SystemTrayMenu.Helpers.Updater
return null; return null;
} }
var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 }); var dictionary = (IDictionary?)type.GetConstructor(new Type[] { typeof(int) })?.Invoke(new object[] { elems.Count / 2 });
if (dictionary == null)
{
return null;
}
for (int i = 0; i < elems.Count; i += 2) for (int i = 0; i < elems.Count; i += 2)
{ {
if (elems[i].Length <= 2) if (elems[i].Length <= 2)
@ -240,7 +255,7 @@ namespace SystemTrayMenu.Helpers.Updater
} }
string keyValue = elems[i][1..^1]; string keyValue = elems[i][1..^1];
object val = ParseValue(valueType, elems[i + 1]); object? val = ParseValue(valueType, elems[i + 1]);
dictionary.Add(keyValue, val); dictionary.Add(keyValue, val);
} }
@ -262,7 +277,7 @@ namespace SystemTrayMenu.Helpers.Updater
private static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json) private static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
{ {
stringBuilder.Append(json[startIdx]); stringBuilder!.Append(json[startIdx]);
for (int i = startIdx + 1; i < json.Length; i++) for (int i = startIdx + 1; i < json.Length; i++)
{ {
if (json[i] == '\\') if (json[i] == '\\')
@ -292,7 +307,7 @@ namespace SystemTrayMenu.Helpers.Updater
// Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings // Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
private static List<string> Split(string json) private static List<string> Split(string json)
{ {
List<string> splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List<string>(); List<string> splitArray = splitArrayPool!.Count > 0 ? splitArrayPool.Pop() : new List<string>();
splitArray.Clear(); splitArray.Clear();
if (json.Length == 2) if (json.Length == 2)
{ {
@ -300,7 +315,7 @@ namespace SystemTrayMenu.Helpers.Updater
} }
int parseDepth = 0; int parseDepth = 0;
stringBuilder.Length = 0; stringBuilder!.Length = 0;
for (int i = 1; i < json.Length - 1; i++) for (int i = 1; i < json.Length - 1; i++)
{ {
switch (json[i]) switch (json[i])
@ -336,7 +351,7 @@ namespace SystemTrayMenu.Helpers.Updater
return splitArray; return splitArray;
} }
private static object ParseAnonymousValue(string json) private static object? ParseAnonymousValue(string json)
{ {
if (json.Length == 0) if (json.Length == 0)
{ {
@ -351,7 +366,7 @@ namespace SystemTrayMenu.Helpers.Updater
return null; return null;
} }
var dict = new Dictionary<string, object>(elems.Count / 2); var dict = new Dictionary<string, object?>(elems.Count / 2);
for (int i = 0; i < elems.Count; i += 2) for (int i = 0; i < elems.Count; i += 2)
{ {
dict.Add(elems[i][1..^1], ParseAnonymousValue(elems[i + 1])); dict.Add(elems[i][1..^1], ParseAnonymousValue(elems[i + 1]));
@ -363,7 +378,7 @@ namespace SystemTrayMenu.Helpers.Updater
if (json[0] == '[' && json[^1] == ']') if (json[0] == '[' && json[^1] == ']')
{ {
List<string> items = Split(json); List<string> items = Split(json);
var finalList = new List<object>(items.Count); var finalList = new List<object?>(items.Count);
for (int i = 0; i < items.Count; i++) for (int i = 0; i < items.Count; i++)
{ {
finalList.Add(ParseAnonymousValue(items[i])); finalList.Add(ParseAnonymousValue(items[i]));
@ -411,21 +426,23 @@ namespace SystemTrayMenu.Helpers.Updater
Dictionary<string, T> nameToMember = new(StringComparer.OrdinalIgnoreCase); Dictionary<string, T> nameToMember = new(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < members.Length; i++) for (int i = 0; i < members.Length; i++)
{ {
/*T member = members[i]; T member = members[i];
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true)) if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
{
continue; continue;
}
string name = member.Name; string name = member.Name;
if (member.IsDefined(typeof(DataMemberAttribute), true)) if (member.IsDefined(typeof(DataMemberAttribute), true))
{ {
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true); DataMemberAttribute? dataMemberAttribute = (DataMemberAttribute?)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
if (!string.IsNullOrEmpty(dataMemberAttribute.Name)) if (!string.IsNullOrEmpty(dataMemberAttribute?.Name))
{
name = dataMemberAttribute.Name; name = dataMemberAttribute.Name;
} }
}
nameToMember.Add(name, member);*/ nameToMember.Add(name, member);
// The above code is not working with .Net framework 2.0, so we ignore these attributes for compatibility reasons:
nameToMember.Add(members[i].Name, members[i]);
} }
return nameToMember; return nameToMember;
@ -442,13 +459,13 @@ namespace SystemTrayMenu.Helpers.Updater
return instance; return instance;
} }
if (!fieldInfoCache.TryGetValue(type, out Dictionary<string, FieldInfo> nameToField)) if (!fieldInfoCache!.TryGetValue(type, out Dictionary<string, FieldInfo>? nameToField))
{ {
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)); nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
fieldInfoCache.Add(type, nameToField); fieldInfoCache.Add(type, nameToField);
} }
if (!propertyInfoCache.TryGetValue(type, out Dictionary<string, PropertyInfo> nameToProperty)) if (!propertyInfoCache!.TryGetValue(type, out Dictionary<string, PropertyInfo>? nameToProperty))
{ {
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)); nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
propertyInfoCache.Add(type, nameToProperty); propertyInfoCache.Add(type, nameToProperty);
@ -464,11 +481,11 @@ namespace SystemTrayMenu.Helpers.Updater
string key = elems[i][1..^1]; string key = elems[i][1..^1];
string value = elems[i + 1]; string value = elems[i + 1];
if (nameToField.TryGetValue(key, out FieldInfo fieldInfo)) if (nameToField.TryGetValue(key, out FieldInfo? fieldInfo))
{ {
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value)); fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
} }
else if (nameToProperty.TryGetValue(key, out PropertyInfo propertyInfo)) else if (nameToProperty.TryGetValue(key, out PropertyInfo? propertyInfo))
{ {
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null); propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
} }