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;
		}
Пример #6
0
		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;
        }
Пример #14
0
		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;
		}
Пример #19
0
		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;
		}
Пример #21
0
        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;
		}
Пример #29
0
		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;
		}