public RuleResult CheckType (TypeDefinition type) { // rule applies only to types, interfaces and structures (value types) if (type.IsEnum || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule onyly applies to type that implements IDisposable if (!type.Implements ("System.IDisposable")) return RuleResult.DoesNotApply; // no problem is a finalizer is found if (type.HasMethod (MethodSignatures.Finalize)) return RuleResult.Success; // otherwise check for native types foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; if (!field.FieldType.GetElementType ().IsNative ()) continue; Runner.Report (field, Severity.High, Confidence.High); } // special case: a struct cannot define a finalizer so it's a // bad candidate to hold references to unmanaged resources if (type.IsValueType && (Runner.CurrentRuleResult == RuleResult.Failure)) Runner.Report (type, Severity.High, Confidence.High, Struct); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; MethodDefinition equality = type.GetMethod (MethodSignatures.op_Equality); if ((equality == null) || type.HasMethod (MethodSignatures.Equals)) return RuleResult.Success; Runner.Report (equality, Severity.High, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType(TypeDefinition type) { // rule applies only to ValueType, except enums and generated code if (!type.IsValueType || type.IsEnum || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // note: no inheritance check required since we're dealing with structs bool equals = type.HasMethod (MethodSignatures.Equals); bool gethashcode = type.HasMethod (MethodSignatures.GetHashCode); bool operators = type.HasMethod (MethodSignatures.op_Equality) && type.HasMethod (MethodSignatures.op_Inequality); // note: we want to avoid reporting 4 defects each (well most) of the time // the rule is triggered (it's too verbose to be useful) if (equals && gethashcode && operators) return RuleResult.Success; // drop severity one level if only operators are missing (since overloading them // is not available in every language) Severity severity = (equals || gethashcode) ? Severity.Medium : Severity.Low; string msg = String.Format (CultureInfo.InvariantCulture, MissingImplementationMessage, !equals && !gethashcode ? "Equals(object)' and 'GetHashCode()" : equals ? "GetHashCode()" : "Equals(object)", operators ? String.Empty : MissingOperatorsMessage); Runner.Report (type, severity, Confidence.High, msg); return RuleResult.Failure; }
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; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to interfaces and enums if (type.IsInterface || type.IsEnum || type.IsDelegate ()) return RuleResult.DoesNotApply; bool equals = type.HasMethod (MethodSignatures.Equals); bool getHashCode = type.HasMethod (MethodSignatures.GetHashCode); // if we have Equals but no GetHashCode method if (equals && !getHashCode) { string text = String.Format (Message, MethodSignatures.Equals, MethodSignatures.GetHashCode); Runner.Report (type, Severity.Critical, Confidence.High, text); } // if we have GetHashCode but no Equals method if (!equals && getHashCode) { string text = String.Format (Message, MethodSignatures.GetHashCode, MethodSignatures.Equals); Runner.Report (type, Severity.Medium, Confidence.High, text); } // we either have both Equals and GetHashCode or none (both fine) return Runner.CurrentRuleResult; }
public RuleResult CheckType(TypeDefinition type) { // rule applies only to types and interfaces if (type.IsEnum || type.IsDelegate() || type.IsGeneratedCode() || type.IsValueType || type.IsInterface) return RuleResult.DoesNotApply; // rule only applies to type that implements IDisposable if (!type.Implements("System", "IDisposable")) return RuleResult.DoesNotApply; // rule only applies to type that doesn't derive from class that implements IDisposable if (type.BaseType.Implements("System", "IDisposable")) return RuleResult.DoesNotApply; // rule only applies if type has a Dispose(bool) method if (!type.HasMethod(Dispose)) return RuleResult.DoesNotApply; // no problem if a finalizer is found if (type.HasMethod(MethodSignatures.Finalize)) return RuleResult.Success; Runner.Report(type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; if (type.HasMethod (MethodSignatures.op_Addition) && type.HasMethod (MethodSignatures.op_Subtraction)) { if (!type.HasMethod (MethodSignatures.op_Equality)) { Runner.Report (type, Severity.Low, Confidence.High, "This type implements the addition (+) and subtraction (-) operators. It should also implement the equality (==) operator."); } } if (type.IsValueType) { if (type.HasMethod (MethodSignatures.Equals) && !type.HasMethod (MethodSignatures.op_Equality)) { Runner.Report (type, Severity.Medium, Confidence.High, "This type overrides Object.Equals. It should also implement the equality (==) operator."); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, interfaces and to generated code if (type.IsEnum || type.IsInterface || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule only applies if the type implements IComparable or IComparable<T> // Note: we do not use Implements rock because we do not want a recursive answer bool icomparable = false; foreach (TypeReference iface in type.Interfaces) { if (iface.Namespace != "System") continue; // catch both System.IComparable and System.IComparable`1<X> if (iface.Name.StartsWith ("IComparable", StringComparison.Ordinal)) { icomparable = true; break; } } if (!icomparable) return RuleResult.DoesNotApply; // type should override Equals(object) if (!type.HasMethod (MethodSignatures.Equals)) Runner.Report (type, Severity.High, Confidence.High, "Missing Equals(object) override."); // type should implement overloads for ==, !=, < and > operators // note: report all missing operators as single defect bool equality = type.HasMethod (MethodSignatures.op_Equality); bool inequality = type.HasMethod (MethodSignatures.op_Inequality); bool less_than = type.HasMethod (MethodSignatures.op_LessThan); bool greater_than = type.HasMethod (MethodSignatures.op_GreaterThan); if (!equality || !inequality || !less_than || !greater_than) { StringBuilder sb = new StringBuilder ("Missing operators:"); if (!equality) sb.Append (" op_Equality (==)"); if (!inequality) sb.Append (" op_Inequality (!=)"); if (!less_than) sb.Append (" op_LessThan (<)"); if (!greater_than) sb.Append (" op_GreaterThan (>)"); // not all languages support operator overloading so we lower the severity a bit Runner.Report (type, Severity.Medium, Confidence.High, sb.ToString ()); } return Runner.CurrentRuleResult; }