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;
		}