summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-08-25 22:05:27 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-08-25 22:05:27 -0400
commitb9a9fe36bbaa1357b98a117400a62fecc0fc56cb (patch)
tree111b3a4b0a6fd2285edf78716594308340322c21
parent915e6d22f199354ef69a20e47f13731379b46306 (diff)
downloadSMAPI-b9a9fe36bbaa1357b98a117400a62fecc0fc56cb.tar.gz
SMAPI-b9a9fe36bbaa1357b98a117400a62fecc0fc56cb.tar.bz2
SMAPI-b9a9fe36bbaa1357b98a117400a62fecc0fc56cb.zip
fix missing-parameter rewriter not loading default values onto stack
-rw-r--r--src/SMAPI/Framework/ModLoading/Rewriters/MethodWithMissingOptionalParameterRewriter.cs40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/MethodWithMissingOptionalParameterRewriter.cs b/src/SMAPI/Framework/ModLoading/Rewriters/MethodWithMissingOptionalParameterRewriter.cs
index 9db3c3fd..75182890 100644
--- a/src/SMAPI/Framework/ModLoading/Rewriters/MethodWithMissingOptionalParameterRewriter.cs
+++ b/src/SMAPI/Framework/ModLoading/Rewriters/MethodWithMissingOptionalParameterRewriter.cs
@@ -68,14 +68,28 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
if (method == null)
return false;
- // add extra parameters
- foreach (ParameterDefinition parameter in method.Parameters.Skip(methodRef.Parameters.Count))
+ // get instructions to inject
+ var injectables = method.Parameters.Skip(methodRef.Parameters.Count)
+ .Select(p => new { Parameter = p, LoadValueInstruction = this.GetLoadValueInstruction(p.Constant) })
+ .ToArray();
+ if (injectables.Any(p => p.LoadValueInstruction == null))
+ return false; // SMAPI needs to load the value onto the stack before the method call, but the optional parameter type wasn't recognized
+
+ // inject new parameters
+ foreach (var entry in injectables)
{
- methodRef.Parameters.Add(new ParameterDefinition(
+ // load value onto stack
+ cil.InsertBefore(instruction, entry.LoadValueInstruction);
+
+ // add parameter
+ ParameterDefinition parameter = entry.Parameter;
+ var newParameter = new ParameterDefinition(
name: parameter.Name,
attributes: parameter.Attributes,
parameterType: module.ImportReference(parameter.ParameterType)
- ));
+ );
+ newParameter.Constant = parameter.Constant;
+ methodRef.Parameters.Add(newParameter);
}
this.Phrases.Add($"{methodRef.DeclaringType.Name}.{methodRef.Name} (added missing optional parameters)");
@@ -109,5 +123,23 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
return true;
}
+
+ /// <summary>Get the CIL instruction to load a value onto the stack.</summary>
+ /// <param name="rawValue">The constant value to inject.</param>
+ /// <returns>Returns the instruction, or <c>null</c> if the value type isn't supported.</returns>
+ private Instruction GetLoadValueInstruction(object rawValue)
+ {
+ return rawValue switch
+ {
+ null => Instruction.Create(OpCodes.Ldnull),
+ bool value => Instruction.Create(value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0),
+ int value => Instruction.Create(OpCodes.Ldc_I4, value), // int32
+ long value => Instruction.Create(OpCodes.Ldc_I8, value), // int64
+ float value => Instruction.Create(OpCodes.Ldc_R4, value), // float32
+ double value => Instruction.Create(OpCodes.Ldc_R8, value), // float64
+ string value => Instruction.Create(OpCodes.Ldstr, value),
+ _ => null
+ };
+ }
}
}