private void CheckIfBaseDisposeIsCalled(MethodDefinition method, MemberReference baseMethod) { bool found = false; if (method.HasBody) { OpCodeBitmask bitmask = OpCodeEngine.GetBitmask(method); if (bitmask.Get(Code.Ldarg_0) && (OpCodeBitmask.Calls.Intersect(bitmask))) { //Check for a call to base.Dispose(); foreach (Instruction ins in method.Body.Instructions) { if (ins.OpCode.Code != Code.Ldarg_0) //ldarg_0 (this) { continue; } Instruction call = ins.Next; //call baseMethod if (call == null) { continue; } if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt) { continue; } MethodReference calledMethod = (MethodReference)call.Operand; if (calledMethod.GetFullName() != baseMethod.GetFullName()) { continue; } found = true; } } } if (!found) { string s = String.Format(CultureInfo.InvariantCulture, "{0} should call base.Dispose().", method.GetFullName()); Runner.Report(method, Severity.Medium, Confidence.High, s); } }
private void CheckForViolation(MethodDefinition method, Instruction instruction) { if ((instruction.OpCode.Code == Code.Newobj || instruction.OpCode.Code == Code.Newarr)) { MemberReference member = (instruction.Operand as MemberReference); if ((member != null) && !IsNewException(member)) { string s = String.Format(CultureInfo.InvariantCulture, "Unused object of type '{0}' created.", member.GetFullName()); Runner.Report(method, instruction, Severity.High, Confidence.Normal, s); } } if (instruction.OpCode.Code == Code.Call || instruction.OpCode.Code == Code.Callvirt) { MethodReference callee = instruction.Operand as MethodReference; if (callee != null && !callee.ReturnType.IsValueType) { // check for some common exceptions (to reduce false positive) if (!IsCallException(callee)) { string s = String.Format(CultureInfo.InvariantCulture, "Do not ignore method results from call to '{0}'.", callee.GetFullName()); Runner.Report(method, instruction, Severity.Medium, Confidence.Normal, s); } } } }
protected override void Report(MethodDefinition method, Instruction instruction, MethodReference prefered) { string msg = String.Format(CultureInfo.InvariantCulture, "Consider using the perfered '{0}' override.", prefered.GetFullName()); Runner.Report(method, instruction, Severity.Medium, Confidence.High, msg); }
public RuleResult CheckMethod(MethodDefinition method) { // rule doesn't apply if method has no IL if (!method.HasBody) { return(RuleResult.DoesNotApply); } // check if any instruction refers to methods or types that MoMA could track if (!mask.Intersect(OpCodeEngine.GetBitmask(method))) { return(RuleResult.DoesNotApply); } // rule applies foreach (Instruction ins in method.Body.Instructions) { // look for any instruction that could use something incomplete if (!mask.Get(ins.OpCode.Code)) { continue; } // filter calls to assemblies that MoMA likely does not include (e.g. your own code) MethodReference mr = (ins.Operand as MethodReference); if ((mr == null) || !Filter(mr.DeclaringType.Scope as AssemblyNameReference)) { continue; } // MethodReference.ToString is costly so we do it once for the three checks string callee = mr.GetFullName(); // calling not implemented method is very likely not to work == High if ((NotImplemented != null) && NotImplementedInternal.Contains(callee)) { string message = String.Format(CultureInfo.InvariantCulture, NotImplementedMessage, callee); // confidence is Normal since we can't be sure if MoMA data is up to date Runner.Report(method, ins, Severity.High, Confidence.Normal, message); } // calling missing methods can't work == Critical if ((Missing != null) && Missing.Contains(callee)) { string message = String.Format(CultureInfo.InvariantCulture, MissingMessage, callee); Runner.Report(method, ins, Severity.Critical, Confidence.Normal, message); } // calling todo methods migh work with some limitations == Medium if (ToDo != null) { string value; if (ToDo.TryGetValue(callee, out value)) { string message = String.Format(CultureInfo.InvariantCulture, TodoMessage, callee, value); Runner.Report(method, ins, Severity.Medium, Confidence.Normal, message); } } } return(Runner.CurrentRuleResult); }