private Tuple<TypeDefinition, int> RemoveArgumentWeavingCall(MethodDefinition method, Collection<Instruction> instructions, Instruction instruction)
{
TypeReference displayClassType = null;
var index = instructions.IndexOf(instruction);
for (var i = index; i >= 0; i--)
{
// Remove everything until the first ldloc.0 call
var innerInstruction = instructions[i];
instructions.RemoveAt(i);
if (innerInstruction.IsOpCode(OpCodes.Ldtoken))
{
if (displayClassType == null)
{
// First call to ldtoken with FieldDefinition contains the display class type
var fieldDefinition = GetFieldDefinition(innerInstruction);
if (fieldDefinition != null)
{
displayClassType = fieldDefinition.DeclaringType;
}
}
}
// Regular code
if (innerInstruction.IsOpCode(OpCodes.Ldloc_0, OpCodes.Ldloc))
{
break;
}
// Async/await code
if (innerInstruction.IsOpCode(OpCodes.Ldarg, OpCodes.Ldarg_0))
{
break;
}
// Since .NET core, we want to skip assignments:
//
// ldarg.0
// stfld class MyClass/<>c__DisplayClass0_0`1<!!T>::myArgument
//
// If the display class is no longer used, another method must remove the code
if (innerInstruction.IsOpCode(OpCodes.Stfld, OpCodes.Ldarg, OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3))
{
break;
}
// .net core code
if (innerInstruction.IsOpCode(OpCodes.Dup))
{
break;
}
index = i;
}
return new Tuple<TypeDefinition, int>(displayClassType.Resolve(), index - 1);
}