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) { // rule apply only to types protected by either a Demand or a LinkDemand (i.e. SecurityDeclaration) // that have fields and are visible outside the assembly if (!type.HasSecurityDeclarations || !type.HasFields || !type.IsVisible ()) return RuleResult.DoesNotApply; bool demand = false; foreach (SecurityDeclaration declsec in type.SecurityDeclarations) { switch (declsec.Action) { case Mono.Cecil.SecurityAction.Demand: case Mono.Cecil.SecurityAction.LinkDemand: demand = true; break; } } if (!demand) return RuleResult.DoesNotApply; // *** ok, the rule applies! *** // type shouldn't have any visible fields foreach (FieldDefinition field in type.Fields) { if (field.IsVisible ()) { Runner.Report (field, Severity.Critical, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // if the type is not visible or has no fields then the rule does not apply if (!type.HasFields || type.IsEnum || !type.IsVisible ()) return RuleResult.DoesNotApply; foreach (FieldDefinition field in type.Fields) { // look for 'const' fields if (!field.IsLiteral) continue; // that are visible outside the current assembly if (!field.IsVisible ()) continue; // we let null constant for all reference types (since they can't be changed to anything else) // except for strings (which can be modified later) string type_name = field.FieldType.FullName; if (!field.FieldType.IsValueType && (type_name != "System.String")) continue; string msg = string.Format ("'{0}' of type {1}.", field.Name, type_name); Runner.Report (field, Severity.High, Confidence.High, msg); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (!type.IsClass || !type.HasGenericParameters || !type.IsVisible ()) return RuleResult.DoesNotApply; if (type.GenericParameters.Count > 2) Runner.Report (type, Severity.Medium, Confidence.Total); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to nested types, since the declaring type will already be reported if (type.IsNested) return RuleResult.DoesNotApply; // rule applies to only to types visible outside the assembly if (!type.IsVisible ()) return RuleResult.DoesNotApply; // rule applies! // check if the type resides inside a namespace if (!String.IsNullOrEmpty (type.Namespace)) return RuleResult.Success; Runner.Report (type, Severity.Low, Confidence.Total); return RuleResult.Failure; }
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) { if (!type.IsClass || !type.HasGenericParameters || !type.IsVisible ()) return RuleResult.DoesNotApply; if (type.HasFields) { foreach (var field in type.Fields) { if (field.IsStatic && field.IsVisible ()) Runner.Report (field, Severity.Medium, Confidence.Total); } } if (type.HasMethods) { foreach (var method in type.Methods) { if (method.IsStatic && method.IsVisible ()) Runner.Report (method, Severity.Medium, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only to classes that defines events if (type.IsEnum || type.IsInterface || type.IsValueType || !type.HasEvents) return RuleResult.DoesNotApply; // type can be non-visible (private or internal) but still reachable // with an interface or with an attribute (internals) bool type_visible = type.IsVisible (); foreach (EventDefinition evnt in type.Events) { // we assume that Add|Remove have the same visibility if (evnt.AddMethod.IsVisible ()) continue; // report if Add|Remove is synchronized if (evnt.AddMethod.IsSynchronized) { Confidence confidence = type_visible ? Confidence.Normal : Confidence.Low; Runner.Report (evnt, Severity.Medium, confidence); } } return Runner.CurrentRuleResult; }
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; }
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) { if (type.BaseType == null) return RuleResult.DoesNotApply; // rule apply only to type that inherits from the base exceptions switch (type.BaseType.FullName) { case "System.Exception": case "System.SystemException": case "System.ApplicationException": break; default: return RuleResult.DoesNotApply; } if (type.IsAbstract || type.IsVisible ()) return RuleResult.Success; Runner.Report (type, Severity.High, Confidence.Total); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { //type does not apply if not an interface or is an empty interface if (!type.IsInterface || !type.HasMethods) return RuleResult.DoesNotApply; //TODO: take into account [InternalsVisibleTo] on iface's assembly AssemblyDefinition current_assembly = type.Module.Assembly; if (type.IsVisible ()) { // We should not, by default, promote the implementation of interfaces in assemblies that // do not, already, refer to the current one because: // (a) we could be suggesting circular references (solvable, or not, by refactoring) // (b) it has a very HIGH performance cost, with verry LITTLE value (in # of defects) string current_assembly_name = current_assembly.Name.Name; foreach (AssemblyDefinition assembly in Runner.Assemblies) { // by default only process assemblies (from the set) that refers to the current one // or the current one itself if (!ReferencesOnly || (current_assembly_name == assembly.Name.Name) || assembly.References (current_assembly_name)) { CheckAssemblyTypes (assembly, type); } } } else { // if the interface is not visible then we only check this assembly CheckAssemblyTypes (current_assembly, type); } 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; }
private static TypeDefinition GetBaseImplementor (TypeDefinition type, IEnumerable<MethodSignature> signatures) { TypeDefinition implementor = type; while (null != type && type.IsVisible ()) { //search for matching interface TypeDefinition ifaceDef = GetInterfaceImplementor (type, signatures); if (null != ifaceDef) implementor = ifaceDef; else if (DoesAllSignaturesMatchType (type, signatures)) implementor = type; type = type.BaseType != null ? type.BaseType.Resolve () : null; } return implementor; }
public RuleResult CheckType (TypeDefinition type) { if (type.HasGenericParameters || !type.IsVisible () || !type.IsTypeComVisible ()) return RuleResult.DoesNotApply; bool foundRegister = false; // type level variables bool foundUnregister = false; foreach (MethodDefinition method in type.Methods) { if (!method.HasCustomAttributes) continue; bool foundRegisterUnregisterMethod = false; // method level variable foreach (CustomAttribute attribute in method.CustomAttributes) { var name = attribute.AttributeType.FullName; if (!foundRegister && name == comRegister) { foundRegister = true; foundRegisterUnregisterMethod = true; } if (!foundUnregister && name == comUnregister) { foundUnregister = true; foundRegisterUnregisterMethod = true; } } if (foundRegisterUnregisterMethod && method.IsVisible ()) { Runner.Report (method, Severity.High, Confidence.High, "Method is marked with the ComRegisterFunctionAttribute or with the ComUnregisterFunctionAttribute and is externally visible"); } } if (foundRegister ^ foundUnregister) { // only one of them is true if (foundRegister) Runner.Report (type, Severity.High, Confidence.High, "Type contains has a method with ComRegisterFunctionAttribute but it doesn't contain a method with ComUnregisterFunctionAttribute"); if (foundUnregister) Runner.Report (type, Severity.High, Confidence.High, "Type contains has a method with ComUnregisterFunctionAttribute but it doesn't contain a method with ComRegisterFunctionAttribute"); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { CheckIdentifier (type, type.Name, type.IsVisible () ? Severity.Medium : Severity.Low); if (type.HasFields) { // fields should not be visible (in most case) so we always report low foreach (FieldDefinition field in type.Fields) CheckIdentifier (field, field.Name, Severity.Low); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { TypeReference btype = type.BaseType; if (btype == null) return RuleResult.DoesNotApply; // rule apply only to type that inherits from the base exceptions if (btype.Namespace != "System") return RuleResult.DoesNotApply; string name = btype.Name; if ((name != "Exception") && (name != "SystemException") && (name != "ApplicationException")) return RuleResult.DoesNotApply; if (type.IsAbstract || type.IsVisible ()) return RuleResult.Success; Runner.Report (type, Severity.High, Confidence.Total); return RuleResult.Failure; }
public RuleResult CheckType(TypeDefinition type) { // rule apply only to types that // - are not sealed; // - have a LinkDemand (so some security declarations); and // - are visible outside the current assembly if (type.IsSealed || !type.HasSecurityDeclarations || !type.IsVisible ()) return RuleResult.DoesNotApply; PermissionSet link = null; PermissionSet inherit = null; // rule apply to types with a LinkDemand foreach (SecurityDeclaration declsec in type.SecurityDeclarations) { switch (declsec.Action) { case Mono.Cecil.SecurityAction.LinkDemand: case Mono.Cecil.SecurityAction.NonCasLinkDemand: link = declsec.ToPermissionSet (); break; case Mono.Cecil.SecurityAction.InheritDemand: case Mono.Cecil.SecurityAction.NonCasInheritance: inherit = declsec.ToPermissionSet (); break; } } // no LinkDemand == no problem if (link == null) return RuleResult.DoesNotApply; // rule apply if there are virtual methods defined bool virt = false; foreach (MethodDefinition method in type.Methods) { // ensure that the method is declared in this type (i.e. not in a parent) if (method.IsVirtual && ((method.DeclaringType as TypeDefinition) == type)) virt = true; } // no virtual method == no problem if (!virt) return RuleResult.DoesNotApply; // *** ok, the rule applies! *** // Ensure the LinkDemand is a subset of the InheritanceDemand if (inherit == null) { // LinkDemand without InheritanceDemand Runner.Report (type, Severity.High, Confidence.High, "LinkDemand is present but no InheritanceDemand is specified."); } else if (!link.IsSubsetOf (inherit)) { Runner.Report (type, Severity.High, Confidence.High, "LinkDemand is not a subset of InheritanceDemand."); } return Runner.CurrentRuleResult; }
void CheckInterfaces(TypeDefinition type) { foreach (TypeReference intf in type.Interfaces) { if (IsObsolete (intf)) { string msg = String.Format (CultureInfo.InvariantCulture, "Implement obsolete interface '{0}'.", intf); Runner.Report (type, type.IsVisible () ? Severity.Medium : Severity.Low, Confidence.Total, msg); } } }
void CheckBaseType(TypeDefinition type) { if (!IsObsolete (type.BaseType)) return; string msg = String.Format (CultureInfo.InvariantCulture, "Inherit from obsolete type '{0}'.", type.BaseType); Runner.Report (type, type.IsVisible () ? Severity.High : Severity.Medium, Confidence.Total, msg); }
public RuleResult CheckType (TypeDefinition type) { if (!type.HasProperties || !type.IsVisible ()) return RuleResult.DoesNotApply; bool is_interface = type.IsInterface; foreach (PropertyDefinition pd in type.Properties) { MethodDefinition setter = pd.SetMethod; if ((setter == null) || (!is_interface && !setter.IsVisible ())) continue; TypeReference ptype = pd.PropertyType; if (IsICollection (ptype) && !IsSpecialCase (ptype)) Runner.Report (setter, Severity.Medium, Confidence.High); } 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) { // apply only to nested types if (!type.IsNested) return RuleResult.DoesNotApply; // it's ok if the type is not visible if (!type.IsVisible ()) return RuleResult.Success; // otherwise we warn about the nested type Runner.Report (type, Severity.Medium, Confidence.Total); return RuleResult.Failure; }
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; }