Parallel exception aggregate fix
This commit is contained in:
parent
73e3735dcd
commit
6b4e52febb
|
@ -57,60 +57,75 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework
|
||||||
/// <returns>Returns whether the module was modified.</returns>
|
/// <returns>Returns whether the module was modified.</returns>
|
||||||
public bool RewriteModule()
|
public bool RewriteModule()
|
||||||
{
|
{
|
||||||
bool anyRewritten = false;
|
Tuple<bool,Exception> aggregateResult = this.Module.GetTypes()
|
||||||
|
.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism)
|
||||||
foreach (TypeDefinition type in this.Module.GetTypes())
|
.Select(type =>
|
||||||
{
|
|
||||||
if (type.BaseType == null)
|
|
||||||
continue; // special type like <Module>
|
|
||||||
|
|
||||||
anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes);
|
|
||||||
anyRewritten |= this.RewriteGenericParameters(type.GenericParameters);
|
|
||||||
|
|
||||||
foreach (InterfaceImplementation @interface in type.Interfaces)
|
|
||||||
anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType);
|
|
||||||
|
|
||||||
if (type.BaseType.FullName != "System.Object")
|
|
||||||
anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType);
|
|
||||||
|
|
||||||
foreach (MethodDefinition method in type.Methods)
|
|
||||||
{
|
{
|
||||||
anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType);
|
try
|
||||||
anyRewritten |= this.RewriteGenericParameters(method.GenericParameters);
|
|
||||||
anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes);
|
|
||||||
|
|
||||||
foreach (ParameterDefinition parameter in method.Parameters)
|
|
||||||
anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType);
|
|
||||||
|
|
||||||
foreach (var methodOverride in method.Overrides)
|
|
||||||
anyRewritten |= this.RewriteMethodReference(methodOverride);
|
|
||||||
|
|
||||||
if (method.HasBody)
|
|
||||||
{
|
{
|
||||||
foreach (VariableDefinition variable in method.Body.Variables)
|
bool anyRewritten = false;
|
||||||
anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType);
|
if (type.BaseType == null)
|
||||||
|
return new Tuple<bool, Exception>(anyRewritten, null); // special type like <Module>
|
||||||
|
|
||||||
// check CIL instructions
|
anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes);
|
||||||
ILProcessor cil = method.Body.GetILProcessor();
|
anyRewritten |= this.RewriteGenericParameters(type.GenericParameters);
|
||||||
Collection<Instruction> instructions = cil.Body.Instructions;
|
|
||||||
for (int i = 0; i < instructions.Count; i++)
|
foreach (InterfaceImplementation @interface in type.Interfaces)
|
||||||
|
anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType);
|
||||||
|
|
||||||
|
if (type.BaseType.FullName != "System.Object")
|
||||||
|
anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType);
|
||||||
|
|
||||||
|
foreach (MethodDefinition method in type.Methods)
|
||||||
{
|
{
|
||||||
var instruction = instructions[i];
|
anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType);
|
||||||
if (instruction.OpCode.Code == Code.Nop)
|
anyRewritten |= this.RewriteGenericParameters(method.GenericParameters);
|
||||||
continue;
|
anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes);
|
||||||
|
|
||||||
anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction =>
|
foreach (ParameterDefinition parameter in method.Parameters)
|
||||||
|
anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType);
|
||||||
|
|
||||||
|
foreach (var methodOverride in method.Overrides)
|
||||||
|
anyRewritten |= this.RewriteMethodReference(methodOverride);
|
||||||
|
|
||||||
|
if (method.HasBody)
|
||||||
{
|
{
|
||||||
anyRewritten = true;
|
foreach (VariableDefinition variable in method.Body.Variables)
|
||||||
cil.Replace(instruction, newInstruction);
|
anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType);
|
||||||
instruction = newInstruction;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return anyRewritten;
|
// check CIL instructions
|
||||||
|
ILProcessor cil = method.Body.GetILProcessor();
|
||||||
|
Collection<Instruction> instructions = cil.Body.Instructions;
|
||||||
|
for (int i = 0; i < instructions.Count; i++)
|
||||||
|
{
|
||||||
|
var instruction = instructions[i];
|
||||||
|
if (instruction.OpCode.Code == Code.Nop)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction =>
|
||||||
|
{
|
||||||
|
anyRewritten = true;
|
||||||
|
cil.Replace(instruction, newInstruction);
|
||||||
|
instruction = newInstruction;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Tuple<bool, Exception>(anyRewritten, null);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new Tuple<bool, Exception>(false, e.InnerException ?? e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.TakeWhile(tuple => tuple.Item2 == null) // Stop on any exception occurs
|
||||||
|
.Aggregate((tupleA, tupleB) => new Tuple<bool, Exception>(tupleA.Item1 | tupleB.Item1, tupleA.Item2 ?? tupleB.Item2)); // Aggregate result and exception
|
||||||
|
if (aggregateResult.Item2 != null)
|
||||||
|
{
|
||||||
|
throw aggregateResult.Item2; // rethrow inner Exception
|
||||||
|
}
|
||||||
|
return aggregateResult.Item1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue