From 37046a462a167181f2d8e34e45e38a14aeeced91 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 13 Dec 2019 15:28:59 -0600 Subject: [PATCH] Added support for Nullable in the generated config --- IPA.Loader/Config/Stores/GeneratedStore.cs | 34 ++++++++++++++++----- Refs/Unity.TextMeshPro.dll | Bin 97280 -> 97280 bytes Refs/UnityEngine.CoreModule.Net4.dll | Bin 614400 -> 614400 bytes 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/IPA.Loader/Config/Stores/GeneratedStore.cs b/IPA.Loader/Config/Stores/GeneratedStore.cs index cbc87a24..29f615b0 100644 --- a/IPA.Loader/Config/Stores/GeneratedStore.cs +++ b/IPA.Loader/Config/Stores/GeneratedStore.cs @@ -237,7 +237,7 @@ namespace IPA.Config.Stores public bool AllowNull; public bool IsVirtual; public bool IsField; - public bool IsNullable; + public bool IsNullable; // signifies whether this is a Nullable // invalid for objects with IsNullabe false public Type NullableWrappedType => Nullable.GetUnderlyingType(Type); @@ -245,6 +245,8 @@ namespace IPA.Config.Stores public PropertyInfo Nullable_HasValue => Type.GetProperty(nameof(Nullable.HasValue)); // invalid for objects with IsNullabe false public PropertyInfo Nullable_Value => Type.GetProperty(nameof(Nullable.Value)); + // invalid for objects with IsNullabe false + public ConstructorInfo Nullable_Construct => Type.GetConstructor(new[] { NullableWrappedType }); } private static Func MakeCreator(Type type) @@ -853,11 +855,12 @@ namespace IPA.Config.Stores if (member.AllowNull) { var passedNull = il.DefineLabel(); + il.Emit(OpCodes.Dup); + if (member.IsNullable) + il.Emit(OpCodes.Call, member.Nullable_HasValue.GetGetMethod()); il.Emit(OpCodes.Brtrue, passedNull); - // TODO: add special check for nullables - il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Br, endSerialize); @@ -865,6 +868,9 @@ namespace IPA.Config.Stores il.MarkLabel(passedNull); } + if (member.IsNullable) + il.Emit(OpCodes.Call, member.Nullable_Value.GetGetMethod()); + var targetType = GetExpectedValueTypeForType(member.Type); if (targetType == typeof(Text)) { // only happens when arg is a string or char @@ -954,6 +960,12 @@ namespace IPA.Config.Stores il.Emit(OpCodes.Callvirt, IGeneratedStore_Deserialize); } + private static void EmitDeserializeNullable(ILGenerator il, SerializedMemberInfo member, Type expected, Func GetLocal) + { + EmitDeserializeValue(il, member.NullableWrappedType, expected, GetLocal); + il.Emit(OpCodes.Newobj, member.Nullable_Construct); + } + // top of stack is the Value to deserialize; the type will be as returned from GetExpectedValueTypeForType // after, top of stack will be thing to write to field private static void EmitDeserializeValue(ILGenerator il, Type targetType, Type expected, Func GetLocal) @@ -1006,7 +1018,7 @@ namespace IPA.Config.Stores var implLabel = il.DefineLabel(); var passedTypeCheck = il.DefineLabel(); - var expectType = GetExpectedValueTypeForType(member.Type); + var expectType = GetExpectedValueTypeForType(member.IsNullable ? member.NullableWrappedType : member.Type); void EmitStore(Action value) { @@ -1028,8 +1040,6 @@ namespace IPA.Config.Stores il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brtrue_S, implLabel); // null check - // TODO: support Nullable - if (!member.AllowNull) { il.Emit(OpCodes.Pop); @@ -1037,6 +1047,15 @@ namespace IPA.Config.Stores expected: il => EmitTypeof(il, expectType)); il.Emit(OpCodes.Br, nextLabel); } + else if (member.IsNullable) + { + il.Emit(OpCodes.Pop); + var valTLocal = GetLocal(member.Type, 0); + il.Emit(OpCodes.Ldloca, valTLocal); + il.Emit(OpCodes.Initobj, member.Type); + EmitStore(il => il.Emit(OpCodes.Ldloc, valTLocal)); + il.Emit(OpCodes.Br, nextLabel); + } else { il.Emit(OpCodes.Pop); @@ -1095,7 +1114,8 @@ namespace IPA.Config.Stores il.MarkLabel(passedTypeCheck); var local = GetLocal(member.Type, 0); - EmitDeserializeValue(il, member.Type, expectType, GetLocal); + if (member.IsNullable) EmitDeserializeNullable(il, member, expectType, GetLocal); + else EmitDeserializeValue(il, member.Type, expectType, GetLocal); il.Emit(OpCodes.Stloc, local); EmitStore(il => il.Emit(OpCodes.Ldloc, local)); } diff --git a/Refs/Unity.TextMeshPro.dll b/Refs/Unity.TextMeshPro.dll index 8214d4da160e050cac922cb15a780d5a89ff8a2a..c531b4668ab313375217de57004c2314c8a02feb 100644 GIT binary patch delta 42 zcmV+_0M-A1_yvIY1(1jXPnz<9i?xdZEmIJ#=u{loHVa9ne9WIM&Z5Y-$WsA0D5r@N ATL1t6 delta 42 zcmV+_0M-A1_yvIY1(1jX7#-+=i?xdZEmIKOgF21Mm0(1>pBJ{KoV262$WsA0D4FdO AEC2ui diff --git a/Refs/UnityEngine.CoreModule.Net4.dll b/Refs/UnityEngine.CoreModule.Net4.dll index f6df15fd5aa051a02f399dd4f10b8d6fa23602ae..6362cdf10545736130379d13fecd4971e3ce0546 100644 GIT binary patch delta 45 ucmZoTpxOXLEsQNpEzB(}TUa~7nUfik+q=VAftU@5*@2j2dv`czDF*;`4G*IL delta 45 ucmZoTpxOXLEsQNpEzB(}TUa~7nRywQ+q=VAftU@5*@2j2dv`czDF*;#2M+B3