private void RemoveObsoleteCodeForArgumentExpression(MethodDefinition method, Collection<Instruction> instructions, TypeDefinition displayClassType)
        {
            // Display class is used when there are still calls to load a field from the display class
            if (instructions.UsesType(displayClassType, OpCodes.Ldfld, OpCodes.Ldftn))
            {
                return;
            }

            FodyEnvironment.LogDebug($"Method '{method.GetFullName()}' no longer uses display class '{displayClassType.GetFullName()}', removing the display class from the method");

            // Remove display class from container
            if (method.DeclaringType.NestedTypes.Contains(displayClassType))
            {
                method.DeclaringType.NestedTypes.Remove(displayClassType);
            }

            // Remove display class - variables
            for (var i = 0; i < method.Body.Variables.Count; i++)
            {
                var variable = method.Body.Variables[i];
                if (string.Equals(variable.VariableType.Name, displayClassType.Name))
                {
                    method.Body.Variables.RemoveAt(i--);
                }
            }

            // Remove display class creation, can be either:
            //
            // Msbuild
            //   L_0000: newobj instance void Catel.Fody.TestAssembly.ArgumentChecksAsExpressionsClass/<>c__DisplayClass1a::.ctor()
            //   L_0005: stloc.0 
            //
            // Roslyn
            //   L_0000: newobj instance void Catel.Fody.TestAssembly.ArgumentChecksAsExpressionsClass/<>c__DisplayClass1a::.ctor()
            //   L_0005: dup

            for (var i = 0; i < instructions.Count; i++)
            {
                var innerInstruction = instructions[i];
                if (innerInstruction.OpCode == OpCodes.Newobj)
                {
                    var remove = false;

                    var methodReference = innerInstruction.Operand as MethodReference;
                    if (methodReference != null)
                    {
                        if (string.Equals(methodReference.DeclaringType.Name, displayClassType.Name))
                        {
                            remove = true;
                        }
                    }

                    var methodDefinition = innerInstruction.Operand as MethodDefinition;
                    if (methodDefinition != null)
                    {
                        if (string.Equals(methodDefinition.DeclaringType.Name, displayClassType.Name))
                        {
                            remove = true;
                        }
                    }

                    if (remove)
                    {
                        // Delete 2 instructions, same location since remove will move everything 1 place up
                        instructions.RemoveAt(i);

                        // Special case in .net core
                        if (instructions[i].OpCode == OpCodes.Dup)
                        {
                            instructions.RemoveAt(i);
                        }

                        instructions.RemoveAt(i);
                    }
                }
            }

            //// Remove all assignments to the display class
            ////   ldarg.0 
            ////   stfld class MyClass/<>c__DisplayClass0_0`1<!!T>::myArgument

            //for (var i = 0; i < instructions.Count; i++)
            //{
            //    var innerInstruction = instructions[i];
            //}

            // Remove display class allocation and assigments
            //   L_0014: ldloc.0 (can also be dup)
            //   L_0015: ldarg.3 
            //   L_0016: stfld object Catel.Fody.TestAssembly.ArgumentChecksAsExpressionsClass/<>c__DisplayClass28::myObject3

            for (var i = 0; i < instructions.Count; i++)
            {
                var innerInstruction = instructions[i];
                if (innerInstruction.UsesType(displayClassType, OpCodes.Stfld))
                {
                    // Remove the stfld + 2 previous operations
                    instructions.RemoveAt(i);
                    instructions.RemoveAt(i - 1);
                    instructions.RemoveAt(i - 2);

                    i -= 3;
                }
            }

            // Remove duplicate nop instructions at the start of a method
            if (instructions.Count > 0)
            {
                var startInstruction = instructions[0];
                if (startInstruction.IsOpCode(OpCodes.Nop))
                {
                    instructions.RemoveAt(0);
                }
            }
        }
		private void CheckTypeVisibility (TypeDefinition type)
		{
			// *NativeMethods types should never be visible outside the assembly
			if (type.IsVisible ()) {
				string msg = String.Format (CultureInfo.InvariantCulture, 
					"'{0}' should not be visible outside the assembly.", type.GetFullName ());
				Runner.Report (type, Severity.High, Confidence.Total, msg);
			}

			if (CanInstantiateType (type)) {
				string msg = String.Format (CultureInfo.InvariantCulture, 
					"'{0}' should not be static or sealed with no visible constructor.", type.GetFullName ());
				Runner.Report (type, Severity.High, Confidence.Total, msg);
			}
		}
		public RuleResult CheckType (TypeDefinition type)
		{
			// rule does not apply to enums, delegates and to generated code
			if (type.IsEnum || type.IsDelegate () || type.IsGeneratedCode ())
				return RuleResult.DoesNotApply;

			// rule applies only if the type overrides Equals(object)
			if (!type.HasMethod (MethodSignatures.Equals))
				return RuleResult.DoesNotApply;

			// if so then the type should also implement Equals(type) since this avoid a cast 
			// operation (for reference types) and also boxing (for value types).

			// we suggest to implement IEquatable<T> if
			// * the assembly targets the 2.0 (or later) runtime
			// * and it does not already implement it
			if (type.Module.Runtime >= TargetRuntime.Net_2_0) {
				if (!type.Implements ("System", "IEquatable`1")) {
					Runner.Report (type, Severity.Medium, Confidence.Total, "Implement System.IEquatable<T>");
				}
				return Runner.CurrentRuleResult;
			}

			parameters [0] = type.GetFullName ();
			if (type.GetMethod (MethodAttributes.Public, "Equals", "System.Boolean", parameters) != null)
				return RuleResult.Success;

			// we consider this a step more severe for value types since it will need 
			// boxing/unboxing with Equals(object)
			Severity severity = type.IsValueType ? Severity.Medium : Severity.Low;
			string msg = String.Format (CultureInfo.InvariantCulture, "Implement 'bool Equals({0})'", type.Name);
			Runner.Report (type, severity, Confidence.High, msg);
			return RuleResult.Failure;
		}