public RuleResult CheckType (TypeDefinition type) { //does rule apply? if (type.IsEnum || type.IsInterface || type.IsAbstract || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; if (!type.HasFields || (type.Fields.Count < MinimumFieldCount)) return RuleResult.DoesNotApply; if (!type.HasMethods || (type.Methods.Count < MinimumMethodCount)) return RuleResult.DoesNotApply; //yay! rule do apply! double coh = GetCohesivenessForType (type); if (coh >= SuccessLowerLimit) return RuleResult.Success; if (0 == coh) return RuleResult.DoesNotApply; //how's severity? Severity sev = GetCohesivenessSeverity(coh); string msg = String.Format (CultureInfo.CurrentCulture, "Type cohesiveness : {0}%", (int) (coh * 100)); Runner.Report (type, sev, Confidence.Normal, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; if (!invoke.ReturnType.IsNamed ("System", "Void")) return RuleResult.Success; if (!invoke.HasParameters) return RuleResult.Success; IList<ParameterDefinition> pdc = invoke.Parameters; if (pdc.Count != 2) return RuleResult.Success; if (!pdc [0].ParameterType.IsNamed ("System", "Object")) return RuleResult.Success; if (!pdc [1].ParameterType.Inherits ("System", "EventArgs")) return RuleResult.Success; Runner.Report (type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
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) { // 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) { // rule doesn't apply on enums, interfaces, delegates or to compiler/tools-generated code // e.g. CSC compiles anonymous methods as an inner type that expose public fields if (type.IsEnum || type.IsInterface || !type.HasFields || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule doesn't apply to type non (externally) visible if (!type.IsVisible ()) return RuleResult.DoesNotApply; foreach (FieldDefinition fd in type.Fields) { if (!fd.IsVisible () || fd.IsSpecialName || fd.HasConstant || fd.IsInitOnly) continue; string name = fd.Name; if (fd.FieldType.IsArray) { string s = String.Format (CultureInfo.InvariantCulture, "Consider changing the field '{0}' to a private or internal field and add a 'Set{1}{2}' method.", name, Char.ToUpper (name [0], CultureInfo.InvariantCulture).ToString (CultureInfo.InvariantCulture), name.Substring (1)); Runner.Report (fd, Severity.Medium, Confidence.Total, s); } else { string s = String.Format (CultureInfo.InvariantCulture, "Field '{0}' should be private or internal and its value accessed through a property.", name); Runner.Report (fd, Severity.Medium, Confidence.Total, s); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { //Skip the <Module> type declaration. if (type.IsGeneratedCode ()) return RuleResult.DoesNotApply; Runner.Report (type, Severity.High, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // that will cover interfaces, delegates too if (!type.HasFields) return RuleResult.DoesNotApply; // rule doesn't apply to enums, interfaces, structs, delegates or generated code if (type.IsEnum || type.IsValueType || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition explicitDisposeMethod = null; MethodDefinition implicitDisposeMethod = null; bool abstractWarning = false; if (type.Implements ("System", "IDisposable")) { implicitDisposeMethod = type.GetMethod (MethodSignatures.Dispose); explicitDisposeMethod = type.GetMethod (MethodSignatures.DisposeExplicit); if (IsAbstract (implicitDisposeMethod) || IsAbstract (explicitDisposeMethod)) { abstractWarning = true; } else { return RuleResult.Success; } } FieldCandidates.Clear (); foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; TypeDefinition fieldType = field.FieldType.GetElementType ().Resolve (); if (fieldType == null) continue; if (FieldTypeIsCandidate (fieldType)) FieldCandidates.Add (field); } // if there are fields types that implements IDisposable if (type.HasMethods && (FieldCandidates.Count > 0)) { // check if we're assigning new object to them foreach (MethodDefinition method in type.Methods) { CheckMethod (method, abstractWarning); } } // Warn about possible confusion if the Dispose methods are abstract if (IsAbstract (implicitDisposeMethod)) Runner.Report (implicitDisposeMethod, Severity.Medium, Confidence.High, AbstractDisposeMessage); return Runner.CurrentRuleResult; }
virtual public RuleResult CheckType (TypeDefinition type) { if (type.IsAbstract || type.IsGeneratedCode () || !type.Implements (InterfaceNamespace, InterfaceName)) return RuleResult.DoesNotApply; signatures = GetMethods (); propertyNames = GetProperties (); methodsLeft = signatures.Length; propertiesLeft = propertyNames.Length; TypeDefinition baseType = type; while (methodsLeft > 0 || propertiesLeft > 0) { ProcessType (baseType); if (baseType.BaseType == null) break; TypeDefinition td = baseType.BaseType.Resolve (); if (td == null) break; baseType = td; } if (propertiesLeft > 0) { foreach (string propertyName in propertyNames) { if (propertyName == null) continue; Runner.Report (type, Severity.Medium, Confidence.High, "Type does not have strongly typed version of property " + propertyName); } } if (methodsLeft > 0) { foreach (MethodSignature signature in signatures) { if (signature == null) continue; Runner.Report (type, Severity.Medium, Confidence.High, "Type does not have strongly typed version of method " + signature.Name); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsAbstract || type.IsSealed || type.IsVisible () || type.IsGeneratedCode ()) return RuleResult.Success; ModuleDefinition module = type.Module; string type_name = type.FullName; foreach (TypeDefinition type_definition in module.GetAllTypes ()) { // skip ourself if (type_definition.FullName == type_name) continue; if (type_definition.Inherits (type_name)) return RuleResult.Success; } Confidence c = module.Assembly.HasAttribute ("System.Runtime.CompilerServices.InternalsVisibleToAttribute") ? Confidence.High : Confidence.Total; Runner.Report (type, Severity.Medium, c); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, interfaces and generated code if (type.IsEnum || type.IsInterface || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule applies only to visible types if (!type.IsVisible ()) return RuleResult.DoesNotApply; // rule only applies if the type implements IEnumerable if (!type.Implements ("System.Collections", "IEnumerable")) return RuleResult.DoesNotApply; // rule does not apply to the types implementing IDictionary if (type.Implements ("System.Collections", "IDictionary")) return RuleResult.DoesNotApply; // the type should implement IEnumerable<T> too if (!type.Implements ("System.Collections.Generic", "IEnumerable`1")) Runner.Report (type, Severity.Medium, Confidence.High); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule apply to internal (non-visible) types // note: IsAbstract also excludes static types (2.0) if (type.IsVisible () || type.IsAbstract || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // people use this pattern to have a static class in C# 1. if (type.IsSealed && HasSinglePrivateConstructor (type)) return RuleResult.DoesNotApply; // used for documentation purpose by monodoc if (type.Name == "NamespaceDoc") return RuleResult.DoesNotApply; // rule applies // if the type holds the Main entry point then it is considered useful AssemblyDefinition assembly = type.Module.Assembly; MethodDefinition entry_point = assembly.EntryPoint; if ((entry_point != null) && (entry_point.DeclaringType == type)) return RuleResult.Success; // create a cache of all type instantiation inside this CacheInstantiationFromAssembly (assembly); HashSet<TypeReference> typeset = null; if (cache.ContainsKey (assembly)) typeset = cache [assembly]; // if we can't find the non-public type being used in the assembly then the rule fails if (typeset == null || !typeset.Contains (type)) { // base confidence on whether the internals are visible or not Confidence c = assembly.HasAttribute ("System.Runtime.CompilerServices.InternalsVisibleToAttribute") ? Confidence.Low : Confidence.Normal; Runner.Report (type, Severity.High, c); return RuleResult.Failure; } return RuleResult.Success; }
public RuleResult CheckType(TypeDefinition type) { // don't analyze cases where no methods (or body) are available if (type.IsEnum || type.IsInterface || !type.HasMethods) return RuleResult.DoesNotApply; // ignore code generated by compiler/tools, since they can generate some amount of duplicated code if (type.IsGeneratedCode ()) return RuleResult.DoesNotApply; locator.Clear (); foreach (MethodDefinition current in type.Methods) { locator.CompareMethodAgainstTypeMethods (current, type); locator.CheckedMethods.AddIfNew (current.Name); } return Runner.CurrentRuleResult; }
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) { if (type.IsEnum || !type.HasFields || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; //collect *has* fields foreach (FieldDefinition fd in type.Fields) { if (!fd.FieldType.IsValueType || fd.IsSpecialName || fd.HasConstant || fd.IsInitOnly) continue; string prefix = null, suffix = null; if (IsHasField(fd, ref prefix, ref suffix) && HasValueTypeField(type, string.Concat(prefix,suffix)) ) { //TODO: check if they are both used in the same method? does the complexity worth it? string s = (Runner.VerbosityLevel > 0) ? String.Format ("Field '{0}' should probably be a nullable if '{1}' purpose is to inform if '{0}' has been set.", fd.Name, suffix) : string.Empty; Runner.Report (fd, Severity.Low, Confidence.Low, s); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // type must be visible and not generated by the compiler (or a tool) if (!type.IsVisible () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // the rule does not apply if the code is an interface to COM objects if (UsedForComInterop (type)) return RuleResult.DoesNotApply; // check the type name if (!CheckName (type.Name, false)) { Runner.Report (type, Severity.Medium, Confidence.High); } // CheckMethod covers methods, properties and events (indirectly) // but we still need to cover fields if (type.HasFields) { bool is_enum = type.IsEnum; foreach (FieldDefinition field in type.Fields) { if (!field.IsVisible ()) continue; // ignore "value__" inside every enumeration if (is_enum && !field.IsStatic) continue; if (!CheckName (field.Name, false)) { Runner.Report (field, Severity.Medium, Confidence.High); } } } return Runner.CurrentRuleResult; }
public RuleResult CheckType(TypeDefinition type) { // rule does not apply to generated code (outside developer's control) if (type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // ok, rule applies string tname = type.Name; // first check if the current suffix is correct // e.g. MyAttribute where the type does not inherit from Attribute foreach (string suffix in reservedSuffixes.Keys) { if (HasSuffix (tname, suffix)) { Func<TypeDefinition, string> f; if (reservedSuffixes.TryGetValue (suffix, out f)) { string msg = f (type); // if this is a valid suffix then there's not need to check for invalid later if (String.IsNullOrEmpty (msg)) return RuleResult.Success; Runner.Report (type, Severity.Medium, Confidence.High, msg); } } } // then check if the type should have a (or one of) specific suffixes // e.g. MyStuff where the type implements ICollection proposedSuffixes.Clear (); bool currentTypeSuffix; if (!HasRequiredSuffix (type, proposedSuffixes, out currentTypeSuffix)) { Confidence confidence = Confidence.High; // if base type itself does not have any of the proposed suffixes, lower the confidence if (!currentTypeSuffix) { TypeDefinition baseType = type.BaseType.Resolve (); if (null != baseType && !HasRequiredSuffix (baseType, proposedSuffixes, out currentTypeSuffix)) confidence = Confidence.Low; } // there must be some suffixes defined, but type name doesn't end with any of them Runner.Report (type, Severity.Medium, confidence, ComposeMessage (proposedSuffixes)); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { string ns = type.Namespace; if (type.IsGeneratedCode () || string.IsNullOrEmpty (ns)) return RuleResult.DoesNotApply; int ifaceOffset = type.IsInterface ? 1 : 0; int lastDot = ns.LastIndexOf ('.'); string name = type.Name; //type name is smaller or equal to namespace it cannot be a defect if (name.Length - ifaceOffset <= (ns.Length - lastDot)) return RuleResult.Success; string lastComponent = ns.Substring (lastDot + 1); if (type.IsInterface) name = name.Substring (1); if (!name.StartsWith (lastComponent, StringComparison.Ordinal)) return RuleResult.Success; //if first char of suggestion does not start with a uppercase, can ignore it //ie. Foo.Bar.Barometer if (!char.IsUpper (name [lastComponent.Length])) return RuleResult.Success; string suggestion = name.Substring (lastComponent.Length); //if base type name is or ends with suggestion, likely not clearer if we rename it. //would bring ambiguity or make suggestion looks like base of basetype if (null != type.BaseType) { string base_name = type.BaseType.Name; if (base_name.EndsWith (suggestion, StringComparison.Ordinal)) return RuleResult.Success; //equally, if base type starts with the prefix, it is likely a wanted pattern if (DoesNameStartWithPascalWord (base_name, lastComponent)) return RuleResult.Success; } if (type.IsInterface) suggestion = string.Concat ("I", suggestion); //we have a really interesting candidate now, let's check that removing prefix //would not cause undesirable ambiguity with a type from a parent namespace while (0 != ns.Length) { foreach (TypeDefinition typ in NamespaceEngine.TypesInside (ns)) { if (null == typ) break; if (suggestion == typ.Name) //ambiguity return RuleResult.Success; } ns = ns.Substring (0, Math.Max (0, ns.LastIndexOf ('.'))); } //main goal is to keep the API as simple as possible so this is more severe for visible types Severity severity = type.IsVisible () ? Severity.Medium : Severity.Low; string msg = String.Format (CultureInfo.InvariantCulture, "Consider renaming type to '{0}'.", suggestion); Runner.Report (type, severity, Confidence.Normal, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || !type.HasFields || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; int fcount = GetNonConstantFieldsCount (type); if (fcount > MaxFields) { string msg = String.Format (CultureInfo.InvariantCulture, "This type contains a lot of fields ({0} versus maximum of {1}).", fcount, MaxFields); Runner.Report (type, Severity.High, Confidence.High, msg); } // skip check if there are only constants or generated fields if (fcount > 0) CheckForFieldCommonPrefixes (type); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only if the type isn't: an enum, an interface, a struct, a delegate or compiler generated if (type.IsEnum || type.IsInterface || type.IsValueType || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // it also does not apply if the type is static (2.0+ only) if (type.IsStatic ()) return RuleResult.DoesNotApply; if (!IsAllStatic (type)) return RuleResult.Success; // rule applies! foreach (MethodDefinition ctor in type.Methods) { if (ctor.IsConstructor && !ctor.IsStatic && ctor.IsVisible ()) { Runner.Report (ctor, Severity.Low, Confidence.High); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType(TypeDefinition type) { if (type.IsGeneratedCode ()) return RuleResult.DoesNotApply; string name = type.Name; if (type.IsInterface) { // interfaces should look like 'ISomething' if (!IsCorrectInterfaceName (name)) { string s = String.Format (CultureInfo.InvariantCulture, "The '{0}' interface name doesn't have the required 'I' prefix. Acoording to existing naming conventions, all interface names should begin with the 'I' letter followed by another capital letter.", name); Runner.Report (type, Severity.Critical, Confidence.High, s); } } else { // class should _not_ look like 'CSomething" or like an interface 'IOops' if (!IsCorrectTypeName (name)) { string s = String.Format (CultureInfo.InvariantCulture, "The '{0}' type name starts with '{1}' prefix but, according to existing naming conventions, type names should not have any specific prefix.", name, name [0]); Runner.Report (type, Severity.Medium, Confidence.High, s); } } if (type.HasGenericParameters) { // check generic parameters. They are commonly a single letter T, V, K (ok) // but if they are longer (than one char) they should start with a 'T' // e.g. EventHandler<TEventArgs> foreach (GenericParameter parameter in type.GenericParameters) { string param_name = parameter.Name; if (IsCorrectGenericParameterName (param_name)) { string s = String.Format (CultureInfo.InvariantCulture, "The generic parameter '{0}' should be prefixed with 'T' or be a single, uppercased letter.", param_name); Runner.Report (type, Severity.High, Confidence.High, s); } } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; int n = 0; Severity severity = Severity.Medium; bool use_structure = false; // check parameters for 'ref', 'out', 'params' if (invoke.HasParameters) { IList<ParameterDefinition> pdc = invoke.Parameters; n = pdc.Count; // too many parameters to directly use Action/Func // so we lower severity and suggest grouping them if (n > ((type.Module.Runtime >= TargetRuntime.Net_4_0) ? 16 : 4)) { severity = Severity.Low; n = 1; use_structure = true; } // special cases not directly usable with Action/Func foreach (ParameterDefinition pd in pdc) { if (pd.IsOut || pd.ParameterType.IsByReference || pd.IsParams ()) return RuleResult.Success; } } string msg = invoke.ReturnType.IsNamed ("System", "Void") ? ActionMessage [n] : FuncMessage [n]; if (use_structure) msg += " and use a structure to hold all your parameters into <T>."; Runner.Report (type, severity, Confidence.High, msg); return Runner.CurrentRuleResult; }
public RuleResult CheckType(TypeDefinition type) { // We only like types with fields AND methods. if (!type.HasFields || !type.HasMethods || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; fields.Clear (); foreach (FieldDefinition field in type.Fields) fields.Add (field.Name); // Iterate through all the methods. Check parameter names then method bodies. foreach (MethodDefinition method in type.Methods) { if (method.HasParameters) { foreach (ParameterDefinition param in method.Parameters) { if (fields.Contains (param.Name)) Runner.Report (param, Severity.Medium, Confidence.Total); } } // Method bodies w/o variables don't interest me. if (!method.HasBody) continue; MethodBody body = method.Body; if (body.HasVariables) { // Iterate through all variables in the method body. foreach (VariableDefinition var in body.Variables) { // if the name is compiler generated or if we do not have debugging symbols... if (var.IsGeneratedName ()) continue; if (fields.Contains (var.Name)) Runner.Report (method, Severity.Medium, Confidence.Normal, var.Name); } } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, interfaces and delegates // or types and structures without fields // nor does it apply to generated code (quite common for anonymous types) if (type.IsEnum || type.IsInterface || !type.HasFields || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // copy all fields into an hashset fields.Clear (); foreach (FieldDefinition field in type.Fields) { if (!field.IsPrivate || field.IsLiteral) continue; fields.Add (field); } // scan all methods, including constructors, to find if the field is used foreach (MethodDefinition method in type.Methods) { if (!method.HasBody) continue; // don't check the method if it does not access any field if (!OpCodeEngine.GetBitmask (method).Intersect (LoadStoreFields)) continue; foreach (Instruction ins in method.Body.Instructions) { FieldDefinition fd = ins.GetField (); if (fd == null) continue; fields.Remove (fd); } } // check remaining (private) fields in the set foreach (FieldDefinition field in fields) { Runner.Report (field, Severity.Medium, Confidence.Normal); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; CheckAbstractClassWithoutResponsability (type); if (avoidUnusedParameters != null) { foreach (MethodDefinition method in type.Methods) { avoidUnusedParameters.CheckMethod (method); } } CheckUnnecesaryDelegation (type); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to enums, interfaces, structs, delegates or generated code if (type.IsEnum || type.IsInterface || type.IsValueType || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition explicitDisposeMethod = null; MethodDefinition implicitDisposeMethod = null; bool abstractWarning = false; if (type.Implements ("System.IDisposable")) { implicitDisposeMethod = type.GetMethod (MethodSignatures.Dispose); explicitDisposeMethod = type.GetMethod (MethodSignatures.DisposeExplicit); if (IsAbstract (implicitDisposeMethod) || IsAbstract (explicitDisposeMethod)) { abstractWarning = true; } else { return RuleResult.Success; } } foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; TypeDefinition fieldType = field.FieldType.GetElementType ().Resolve (); if (fieldType == null) continue; // enums and primitives don't implement IDisposable if (fieldType.IsEnum || fieldType.IsPrimitive) continue; if (fieldType.Implements ("System.IDisposable")) { Runner.Report (field, Severity.High, Confidence.High, abstractWarning ? AbstractTypeMessage : TypeMessage); } } // Warn about possible confusion if the Dispose methods are abstract if (IsAbstract (implicitDisposeMethod)) Runner.Report (implicitDisposeMethod, Severity.Medium, Confidence.High, AbstractDisposeMessage); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only if the type isn't: an enum, an interface, a struct, a delegate or compiler generated if (type.IsEnum || type.IsInterface || type.IsValueType || !type.HasFields && GetMethodCount (type) == 0 || type.IsDelegate () || type.IsGeneratedCode () || type.BaseType != null && type.BaseType.FullName != "System.Object") return RuleResult.DoesNotApply; // success if the type is already static if (type.IsStatic ()) return RuleResult.Success; if (IsAllStatic (type)) { // no technical reason not to use a static type exists Runner.Report (type, Severity.Medium, Confidence.High); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // we only check value types not generated by tools (including the compiler) // we also exclude enums since they cannot be larger than 64 bits (8 bytes) if (!type.IsValueType || type.IsEnum || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule applies long size = SizeOfStruct (type); if (size <= max_size) return RuleResult.Success; // here we compute severity based on the actual struct size Severity severity = Severity.Low; if (size > critical_severity_limit) severity = Severity.Critical; else if (size > high_severity_limit) severity = Severity.High; else if (size > medium_severity_limit) severity = Severity.Medium; string text = String.Format (CultureInfo.CurrentCulture, "Structure size is {0} bytes.", size); Runner.Report (type, severity, Confidence.High, text); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to generated code (outside developer's control) if (type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // types should all be PascalCased string name = type.Name; if (!IsPascalCase (name)) { ReportCasingError (type, string.Format ( "Type names should all be pascal-cased. Rename '{0}' type to '{1}'.", name, PascalCase (name))); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, interfaces and delegates // or types and structures without fields // nor does it apply to generated code (quite common for anonymous types) if (type.IsEnum || type.IsInterface || !type.HasFields || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // copy all fields into an hashset fields.Clear (); foreach (FieldDefinition field in type.Fields) { if (!field.IsPrivate || field.IsLiteral || field.IsGeneratedCode ()) continue; fields.Add (field); } // scan all methods, including constructors, to find if the field is used if (fields.Count > 0) { CheckFieldsUsageInType (type); } // scan nested types becuase they also have access to private fields of their parent if (type.HasNestedTypes && fields.Count > 0) { foreach (TypeDefinition nested in type.NestedTypes) { CheckFieldsUsageInType (nested); } } // check remaining (private) fields in the set foreach (FieldDefinition field in fields) { Runner.Report (field, Severity.Medium, Confidence.Normal); } return Runner.CurrentRuleResult; }