public RuleResult CheckMethod (MethodDefinition method)
		{
			// catch abstract, pinvoke and icalls - where rule does not apply
			if (!method.HasBody)
				return RuleResult.DoesNotApply;

			// skip methods without parameters
			if (!method.HasParameters)
				return RuleResult.DoesNotApply;

			// rule doesn't apply to virtual, overrides or generated code
			// doesn't apply to code referenced by delegates (note: more complex check moved last)
			if (method.IsVirtual || method.HasOverrides || method.IsGeneratedCode ())
				return RuleResult.DoesNotApply;
		
			// Also EventArgs parameters are often required in method signatures,
			// but often not required. Reduce "false positives"(*) for GUI apps
			// (*) it's more a "don't report things outside developer's control"
			if (method.IsEventCallback () || IsReferencedByDelegate (method))
				return RuleResult.DoesNotApply;

			// methods with [Conditional] can be empty (not using any parameter) IL-wise but not source-wise, ignore them
			if (method.HasCustomAttributes) {
				if (method.CustomAttributes.ContainsType ("System.Diagnostics.ConditionalAttribute"))
					return RuleResult.DoesNotApply;
			}

			// rule applies

			// we limit ourselves to the first 64 parameters (so we can use a bitmask)
			IList<ParameterDefinition> pdc = method.Parameters;
			int pcount = pdc.Count;
			if (pcount > 64)
				pcount = 64;
			ulong mask = 0;

			// scan IL to see which parameter is being used
			foreach (Instruction ins in method.Body.Instructions) {
				ParameterDefinition parameter = ins.GetParameter (method);
				if (parameter == null)
					continue;
				mask |= ((ulong)1 << (parameter.GetSequence () - 1));
			}

			// quick out based on value - i.e. every parameter is being used
			int shift = 64 - pcount;
			if ((mask << shift) == (UInt64.MaxValue << shift))
				return RuleResult.Success;

			for (int i = 0; i < pcount; i++) {
				if ((mask & ((ulong) 1 << i)) == 0) {
					ParameterDefinition parameter = pdc [i];
					string text = String.Format ("Parameter '{0}' of type '{1}' is never used in the method.",
						parameter.Name, parameter.ParameterType);
					Runner.Report (parameter, Severity.Medium, Confidence.Normal, text);
				}
			}

			return Runner.CurrentRuleResult;
		}
		public RuleResult CheckMethod (MethodDefinition method)
		{
			if (!method.HasBody || !method.HasParameters || method.IsCompilerControlled)
				return RuleResult.DoesNotApply;
			if (method.IsProperty () || method.IsGeneratedCode () || method.IsEventCallback ())
				return RuleResult.DoesNotApply;

			// we cannot change parameter types if:
			// - we're overriding a base virtual method; or
			// - they were specified by an interface
			if (IsSignatureDictated (method))
				return RuleResult.DoesNotApply;

			int pcount = method.Parameters.Count;
			if (pcount > types_least.Length) {
				// that should be quite rare (does not happen for mono 2.0 class libs)
				types_least = new TypeReference [pcount];
				depths_least = new int [pcount];
			}

			CheckParameters (method);

			CheckParametersSpecializationDelta (method);

			Array.Clear (types_least, 0, types_least.Length);
			Array.Clear (depths_least, 0, depths_least.Length);

			return Runner.CurrentRuleResult;
		}
		public RuleResult CheckMethod (MethodDefinition method)
		{
			// we only check non static, non virtual methods and not constructors
			if (method.IsStatic || method.IsVirtual || method.IsConstructor)
				return RuleResult.DoesNotApply;

			// we only check methods with a body
			if (!method.HasBody)
				return RuleResult.DoesNotApply;

			// we also don't check event callbacks, as they usually bring a lot of false positive,
			// and that developers are tied to their signature
			if (method.IsEventCallback ())
				return RuleResult.DoesNotApply;

			// that aren't compiler generated (e.g. anonymous methods) or generated by a tool (e.g. web services)
			if (method.IsGeneratedCode ())
				return RuleResult.DoesNotApply;

			// methods with [Conditional] can be empty (not using 'this') IL-wise but not source-wise, ignore them
			if (method.HasCustomAttributes) {
				if (method.HasAttribute ("System.Diagnostics", "ConditionalAttribute"))
					return RuleResult.DoesNotApply;
			}

			// rule applies

			// if we find a use of the "this" reference, it's ok

			// in most (all?) case "this" is used with the ldarg_0 instruction
			if (OpCodeEngine.GetBitmask (method).Get (Code.Ldarg_0))
				return RuleResult.Success;

			// but it's also valid to have an ldarg with a 0 value operand
			foreach (Instruction instr in method.Body.Instructions) {
				if (instr.OpCode.Code == Code.Ldarg) {
					ParameterDefinition pd = (instr.Operand as ParameterDefinition);
					if (pd.Index == -1)
						return RuleResult.Success;
				}
			}

			Runner.Report (method, Severity.Low, Confidence.Total);
			return RuleResult.Failure;
		}