[Mono-dev] [PATCH] Update Gendarme framework

Aaron Tomb atomb at soe.ucsc.edu
Fri Dec 16 14:14:27 EST 2005


Hi,

I've updated the Gendarme rule execution framework as I described in my
earlier mail. Notably:

  * All of the Check* methods from the IRule interface now accept one
    extra parameter, a Runner, which can be a useful source of
    configuration information, such as command-line flags.

  * All of the Check* methods now return an IList, instead of bool. This
    list is intended to contain Message objects, giving details of the
    rule violation (particularly, the relevant locations within
    methods). In cases where you would previously return 'true', you
    should now return null. In cases where you would return 'false', but
    have no extra information, return an empty list (i.e., new
    ArrayList()). In cases where you want to provide extra information,
    create Message objects, and populate the list before returning it.

  * The ConsoleRunner now accepts the --debug flag, which sets the
    property Debug. All rules can now conditionally produce debugging
    information.

  * All of the code using these interfaces has been updated.

Beware that, currently, NullDerefRule generates a lot of output on
almost any assembly. Therefore, you may want to use the --set option to
specify exactly which set of rules you want to run.

I've attached a diff generated with 'svn diff' in the cecil/gendarme
directory.

Aaron
-------------- next part --------------
Index: console/ConsoleRunner.cs
===================================================================
--- console/ConsoleRunner.cs	(revision 54494)
+++ console/ConsoleRunner.cs	(working copy)
@@ -86,6 +86,9 @@
 			case "--set":
 				set = GetNext (args, ++i, defaultRuleSet);
 				break;
+			case "--debug":
+				debug = true;
+				break;
 			case "--help":
 				return false;
 			default:
@@ -154,6 +157,7 @@
 		Console.WriteLine ("Where");
 		Console.WriteLine ("  --config configfile\tSpecify the configuration file. Default is 'rules.xml'.");
 		Console.WriteLine ("  --set ruleset\t\tSpecify the set of rules to verify. Default is '*'.");
+		Console.WriteLine ("  --debug\t\tEnable debugging output.");
 		Console.WriteLine ("  assembly\t\tSpecify the assembly to verify.");
 		Console.WriteLine ();
 	}
@@ -202,6 +206,13 @@
 			Console.WriteLine ();
 			Console.WriteLine ("Problem: {0}", String.Format (ri.Problem, v.Violator));
 			Console.WriteLine ();
+			if(v.Messages != null && v.Messages.Count > 0) {
+				Console.WriteLine ("Details:");
+				foreach(object message in v.Messages) {
+					Console.WriteLine("  {0}", message);
+				}
+				Console.WriteLine ();
+			}
 			Console.WriteLine ("Solution: {0}", String.Format (ri.Solution, v.Violator));
 			Console.WriteLine ();
 			string url = ri.Uri;
Index: rules/Gendarme.Rules.Security/Test/TypeExposeFieldsTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/TypeExposeFieldsTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/TypeExposeFieldsTest.cs	(working copy)
@@ -123,42 +123,42 @@
 		public void NonPublic ()
 		{
 			ITypeDefinition type = GetTest ("NonPublicClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void NoSecurity ()
 		{
 			ITypeDefinition type = GetTest ("NoSecurityClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void NoDemand ()
 		{
 			ITypeDefinition type = GetTest ("NoDemandClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void NoPublicField ()
 		{
 			ITypeDefinition type = GetTest ("NoPublicFieldClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void LinkDemandWithField ()
 		{
 			ITypeDefinition type = GetTest ("LinkDemandWithFieldClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void DemandWithField ()
 		{
 			ITypeDefinition type = GetTest ("DemandWithFieldClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/Test/SealedTypeWithInheritanceDemandTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/SealedTypeWithInheritanceDemandTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/SealedTypeWithInheritanceDemandTest.cs	(working copy)
@@ -94,28 +94,28 @@
 		public void NonSealed ()
 		{
 			ITypeDefinition type = GetTest ("NonSealedClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void SealedWithoutSecurity ()
 		{
 			ITypeDefinition type = GetTest ("SealedClassWithoutSecurity");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void SealedWithoutInheritanceDemand ()
 		{
 			ITypeDefinition type = GetTest ("SealedClassWithoutInheritanceDemand");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void SealedWithInheritanceDemand ()
 		{
 			ITypeDefinition type = GetTest ("SealedClassWithInheritanceDemand");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/Test/NonVirtualMethodWithInheritanceDemandTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/NonVirtualMethodWithInheritanceDemandTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/NonVirtualMethodWithInheritanceDemandTest.cs	(working copy)
@@ -119,7 +119,7 @@
 		{
 			ITypeDefinition type = GetTest ("AbstractMethodsClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -128,7 +128,7 @@
 		{
 			ITypeDefinition type = GetTest ("VirtualMethodsClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -137,7 +137,7 @@
 		{
 			ITypeDefinition type = GetTest ("NoVirtualMethodsClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -146,7 +146,7 @@
 		{
 			ITypeDefinition type = GetTest ("NotInheritanceDemandClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 	}
Index: rules/Gendarme.Rules.Security/Test/TypeIsNotSubsetOfMethodSecurityTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/TypeIsNotSubsetOfMethodSecurityTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/TypeIsNotSubsetOfMethodSecurityTest.cs	(working copy)
@@ -149,49 +149,49 @@
 		public void NoSecurity ()
 		{
 			ITypeDefinition type = GetTest ("NoSecurityClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void LinkDemand ()
 		{
 			ITypeDefinition type = GetTest ("LinkDemandClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void InheritanceDemand ()
 		{
 			ITypeDefinition type = GetTest ("InheritanceDemandClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void AssertNotSubset ()
 		{
 			ITypeDefinition type = GetTest ("AssertNotSubsetClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void DemandSubset ()
 		{
 			ITypeDefinition type = GetTest ("DemandSubsetClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void DenyNotSubset ()
 		{
 			ITypeDefinition type = GetTest ("DenyNotSubsetClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void PermitOnlySubset ()
 		{
 			ITypeDefinition type = GetTest ("PermitOnlySubsetClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/Test/MethodCallWithSubsetLinkDemandTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/MethodCallWithSubsetLinkDemandTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/MethodCallWithSubsetLinkDemandTest.cs	(working copy)
@@ -128,7 +128,7 @@
 		{
 			ITypeDefinition type = GetTest ("SubsetInheritClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -137,7 +137,7 @@
 		{
 			ITypeDefinition type = GetTest ("NotASubsetInheritClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -146,7 +146,7 @@
 		{
 			ITypeDefinition type = GetTest ("SubsetCallClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -155,7 +155,7 @@
 		{
 			ITypeDefinition type = GetTest ("NotASubsetCallClass");
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 	}
Index: rules/Gendarme.Rules.Security/Test/TypeLinkDemandTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/TypeLinkDemandTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/TypeLinkDemandTest.cs	(working copy)
@@ -147,56 +147,56 @@
 		public void NonPublic ()
 		{
 			ITypeDefinition type = GetTest ("NonPublicClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void Sealed ()
 		{
 			ITypeDefinition type = GetTest ("SealedClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void LinkDemand ()
 		{
 			ITypeDefinition type = GetTest ("LinkDemandClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void LinkDemandVirtualMethod ()
 		{
 			ITypeDefinition type = GetTest ("LinkDemandVirtualMethodClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void InheritanceDemand ()
 		{
 			ITypeDefinition type = GetTest ("InheritanceDemandClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void NoIntersection ()
 		{
 			ITypeDefinition type = GetTest ("NoIntersectionClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void NoIntersectionVirtualMethod ()
 		{
 			ITypeDefinition type = GetTest ("NoIntersectionVirtualMethodClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void Intersection ()
 		{
 			ITypeDefinition type = GetTest ("IntersectionClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/Test/SecureGetObjectDataOverridesTest.cs
===================================================================
--- rules/Gendarme.Rules.Security/Test/SecureGetObjectDataOverridesTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/Test/SecureGetObjectDataOverridesTest.cs	(working copy)
@@ -155,7 +155,7 @@
 			ITypeDefinition type = GetTest ("SerializableClass");
 			// there's no GetObjectData method here so the test should never fail
 			foreach (IMethodDefinition method in type.Methods) {
-				Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+				Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 			}
 		}
 
@@ -164,7 +164,7 @@
 		{
 			ITypeDefinition type = GetTest ("ISerializableClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 
 		[Test]
@@ -172,7 +172,7 @@
 		{
 			ITypeDefinition type = GetTest ("InheritISerializableClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 
 		[Test]
@@ -180,7 +180,7 @@
 		{
 			ITypeDefinition type = GetTest ("LinkDemandClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 
 		[Test]
@@ -188,7 +188,7 @@
 		{
 			ITypeDefinition type = GetTest ("InheritanceDemandClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 
 		[Test]
@@ -196,7 +196,7 @@
 		{
 			ITypeDefinition type = GetTest ("DemandClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsTrue (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 
 		[Test]
@@ -204,7 +204,7 @@
 		{
 			ITypeDefinition type = GetTest ("DemandWrongPermissionClass");
 			IMethodDefinition method = GetObjectData (type);
-			Assert.IsFalse (rule.CheckMethod (assembly, module, type, method));
+			Assert.IsNotNull (rule.CheckMethod (assembly, module, type, method, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/MethodCallWithSubsetLinkDemandRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/MethodCallWithSubsetLinkDemandRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/MethodCallWithSubsetLinkDemandRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using System.Security;
 using System.Security.Permissions;
 
@@ -61,17 +62,17 @@
 			return calleeLinkDemand.IsSubsetOf (GetLinkDemand (caller));
 		}
 
-		public bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method)
+		public IList CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method, Runner runner)
 		{
 			// #1 - rule apply to methods are publicly accessible
 			//	note that the type doesn't have to be public (indirect access)
 			if ((method.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
-				return true;
+				return null;
 
 			// #2 - rule apply only if the method has a body (e.g. p/invokes, icalls don't)
 			//	otherwise we don't know what it's calling
 			if (method.Body == null)
-				return true;
+				return null;
 
 			// *** ok, the rule applies! ***
 
@@ -82,15 +83,16 @@
 				case "callvirt":
 					IMethodDefinition callee = AssemblyManager.GetMethod (ins.Operand);
 					if (callee == null) {
-						return true; // ignore (missing reference)
+						return null; // ignore (missing reference)
 					}
 					// 4 - and if it has security, ensure we don't reduce it's strength
-					if ((callee.SecurityDeclarations.Count > 0) && !Check (method, callee))
-						return false;
+					if ((callee.SecurityDeclarations.Count > 0) && !Check (method, callee)) {
+						return new ArrayList();
+					}
 					break;
 				}
 			}
-			return true;
+			return null;
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/TypeLinkDemandRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/TypeLinkDemandRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/TypeLinkDemandRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using System.Security;
 
 using Mono.Cecil;
@@ -36,7 +37,7 @@
 
 	public class TypeLinkDemandRule: ITypeRule {
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			// #1 - rule apply to types (and nested types) that are publicly visible
 			switch (type.Attributes & TypeAttributes.VisibilityMask) {
@@ -44,12 +45,12 @@
 			case TypeAttributes.NestedPublic:
 				break;
 			default:
-				return true;
+				return null;
 			}
 
 			// #2 - rule apply to types that aren't sealed
 			if (type.IsSealed)
-				return true;
+				return null;
 
 			PermissionSet link = null;
 			PermissionSet inherit = null;
@@ -68,7 +69,7 @@
 			}
 
 			if (link == null)
-				return true; // no LinkDemand == no problem
+				return null; // no LinkDemand == no problem
 
 			// #4 - rule apply if there are virtual methods defined
 			bool virt = false;
@@ -79,14 +80,17 @@
 			}
 
 			if (!virt)
-				return true; // no virtual method == no problem
+				return null; // no virtual method == no problem
 
 			// *** ok, the rule applies! ***
 
 			// #5 - and ensure the LinkDemand is a subset of the InheritanceDemand
 			if (inherit == null)
-				return false; // LinkDemand without InheritanceDemand
-			return link.IsSubsetOf (inherit);
+				return new ArrayList(); // LinkDemand without InheritanceDemand
+			if (link.IsSubsetOf (inherit))
+                                return null;
+                        else
+                                return new ArrayList();
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/SecureGetObjectDataOverridesRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/SecureGetObjectDataOverridesRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/SecureGetObjectDataOverridesRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using System.Security;
 using System.Security.Permissions;
 using System.Text;
@@ -51,19 +52,19 @@
 			}
 		}
 
-		public bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method)
+		public IList CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method, Runner runner)
 		{
 			// check that the method is called "GetObjectData"
 			if (method.Name != "GetObjectData")
-				return true;
+				return null;
 
 			// check parameters
 			if (method.Parameters.Count != 2)
-				return true;
+				return null;
 			if (method.Parameters[0].ParameterType.ToString () != "System.Runtime.Serialization.SerializationInfo")
-				return true;
+				return null;
 			if (method.Parameters[1].ParameterType.ToString () != "System.Runtime.Serialization.StreamingContext")
-				return true;
+				return null;
 
 			// check for ISerializable
 			bool iserialize = true; // FIXME
@@ -78,7 +79,7 @@
 
 			// is there any security applied ?
 			if (method.SecurityDeclarations.Count < 1)
-				return false;
+				return new ArrayList();
 
 			// the SerializationFormatter must be a subset of the one (of the) demand(s)
 			foreach (ISecurityDeclaration declsec in method.SecurityDeclarations) {
@@ -88,12 +89,12 @@
 				case Mono.Cecil.SecurityAction.LinkDemand:
 				case Mono.Cecil.SecurityAction.NonCasLinkDemand:
 					if (RuleSet.IsSubsetOf (declsec.PermissionSet))
-						return true;
+						return null;
 					break;
 				}
 			}
 
-			return false;
+			return new ArrayList();
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/TypeExposeFieldsRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/TypeExposeFieldsRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/TypeExposeFieldsRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using System.Text;
 
 using Mono.Cecil;
@@ -36,7 +37,7 @@
 
 	public class TypeExposeFieldsRule : ITypeRule {
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			// #1 - rule apply to types (and nested types) that are publicly visible
 			switch (type.Attributes & TypeAttributes.VisibilityMask) {
@@ -44,12 +45,12 @@
 			case TypeAttributes.NestedPublic:
 				break;
 			default:
-				return true;
+				return null;
 			}
 
 			// #2 - rule apply to type is protected by a Demand or a LinkDemand
 			if (type.SecurityDeclarations.Count == 0)
-				return true;
+				return null;
 
 			bool demand = false;
 			foreach (ISecurityDeclaration declsec in type.SecurityDeclarations) {
@@ -62,16 +63,16 @@
 			}
 
 			if (!demand)
-				return true;
+				return null;
 
 			// *** ok, the rule applies! ***
 
 			// #3 - so it shouldn't have any public fields
 			foreach (IFieldDefinition field in type.Fields) {
 				if ((field.Attributes & FieldAttributes.Public) == FieldAttributes.Public)
-					return false;
+					return new ArrayList();
 			}
-			return true;
+			return null;
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/SealedTypeWithInheritanceDemandRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/SealedTypeWithInheritanceDemandRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/SealedTypeWithInheritanceDemandRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 
 using Mono.Cecil;
 using Gendarme.Framework;
@@ -35,22 +36,22 @@
 
 	public class SealedTypeWithInheritanceDemandRule : ITypeRule {
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			// 1 - this applies only to sealed types
 			if (!type.IsSealed)
-				return true;
+				return null;
 
 			// 2 - the type must have an InheritanceDemand
 			if (type.SecurityDeclarations.Count == 0)
-				return true;
+				return null;
 
 			foreach (ISecurityDeclaration declsec in type.SecurityDeclarations) {
 				if (declsec.Action == SecurityAction.InheritDemand)
-					return false;
+					return new ArrayList();
 			}
 			// the action wasn't an inheritance demand check
-			return true;
+			return null;
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/NonVirtualMethodWithInheritanceDemandRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/NonVirtualMethodWithInheritanceDemandRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/NonVirtualMethodWithInheritanceDemandRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 
 using Mono.Cecil;
 using Gendarme.Framework;
@@ -35,11 +36,11 @@
 
 	public class NonVirtualMethodWithInheritanceDemandRule : IMethodRule {
 
-		public bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method)
+		public IList CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method, Runner runner)
 		{
 			// #1 - this rule apply only to methods with an inheritance demand
 			if (method.SecurityDeclarations.Count == 0)
-				return true;
+				return null;
 
 			bool inherit = false;
 			foreach (ISecurityDeclaration declsec in method.SecurityDeclarations) {
@@ -51,12 +52,15 @@
 				}
 			}
 			if (!inherit)
-				return true;
+				return null;
 
 			// *** ok, the rule applies! ***
 
 			// #2 - InheritanceDemand doesn't make sense on methods that cannot be overriden
-			return method.IsVirtual;
+			if(method.IsVirtual)
+				return null;
+			else
+				return new ArrayList();
 		}
 	}
 }
Index: rules/Gendarme.Rules.Security/TypeIsNotSubsetOfMethodSecurityRule.cs
===================================================================
--- rules/Gendarme.Rules.Security/TypeIsNotSubsetOfMethodSecurityRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Security/TypeIsNotSubsetOfMethodSecurityRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using System.Security;
 using System.Text;
 
@@ -37,11 +38,11 @@
 
 	public class TypeIsNotSubsetOfMethodSecurityRule : ITypeRule {
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			// #1 - this rules apply if type as security permissions
 			if (type.SecurityDeclarations.Count == 0)
-				return true;
+				return null;
 
 			PermissionSet assert = null;
 			PermissionSet deny = null;
@@ -73,7 +74,7 @@
 			// #2 - this rules doesn't apply to LinkDemand (both are executed) 
 			// and to InheritanceDemand (both are executed at different time).
 			if (!apply)
-				return true;
+				return null;
 
 			// *** ok, the rule applies! ***
 
@@ -89,32 +90,32 @@
 						if (assert == null)
 							continue;
 						if (!assert.IsSubsetOf (declsec.PermissionSet))
-							return false;
+							return new ArrayList();
 						break;
 					case Mono.Cecil.SecurityAction.Deny:
 						if (deny == null)
 							continue;
 						if (!deny.IsSubsetOf (declsec.PermissionSet))
-							return false;
+							return new ArrayList();
 						break;
 					case Mono.Cecil.SecurityAction.PermitOnly:
 						if (permitonly == null)
 							continue;
 						if (!permitonly.IsSubsetOf (declsec.PermissionSet))
-							return false;
+							return new ArrayList();
 						break;
 					case Mono.Cecil.SecurityAction.Demand:
 					case Mono.Cecil.SecurityAction.NonCasDemand:
 						if (demand == null)
 							continue;
 						if (!demand.IsSubsetOf (declsec.PermissionSet))
-							return false;
+							return new ArrayList();
 						break;
 					}
 				}
 			}
 			// other types security applies
-			return true;
+			return null;
 		}
 	}
 }
Index: rules/Gendarme.Rules.Concurrency/DoubleCheckLockingRule.cs
===================================================================
--- rules/Gendarme.Rules.Concurrency/DoubleCheckLockingRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Concurrency/DoubleCheckLockingRule.cs	(working copy)
@@ -1,5 +1,5 @@
 /*
- * DCLChecker.cs: looks for instances of double-check locking.
+ * DoubleCheckLockingRule.cs: looks for instances of double-check locking.
  *
  * Authors:
  *   Aaron Tomb <atomb at soe.ucsc.edu>
@@ -17,15 +17,19 @@
 using Mono.Cecil.Cil;
 using Gendarme.Framework;
 
+namespace Gendarme.Rules.Concurrency {
+
 public class DoubleCheckLockingRule : IMethodRule {
 
-    public bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module,
-            ITypeDefinition type, IMethodDefinition method)
+    public IList CheckMethod (IAssemblyDefinition assembly,
+            IModuleDefinition module,
+            ITypeDefinition type, IMethodDefinition method,
+            Runner runner)
     {
         Hashtable comparisons = new Hashtable();
 
         if(method.Body == null)
-            return true;
+            return null;
 
         IInstructionCollection insns = method.Body.Instructions;
 
@@ -40,22 +44,25 @@
                     foreach(IInstruction insn in comparisons.Keys) {
                         IInstruction[] twoBeforeI =
                             (IInstruction[])comparisons[insn];
-                        if(EffectivelyEqual(insn, insns[i]) &&
-                           EffectivelyEqual(twoBeforeI[0], twoBefore[0]) &&
-                           EffectivelyEqual(twoBeforeI[1], twoBefore[1]) &&
-                           mcount > 0 &&
-                           insn.Offset < (int)monitorOffsetList[mcount - 1]) {
-                            return false;
-                            /* TODO: restore messages */
-                            /*
-                            string etype = method.DeclaringType.FullName;
-                            Location loc = new Location(etype, method.Name,
-                                    insn.Offset);
-                            report.AddMessage(new Message(
-                                        "possible double-check locking",
-                                        loc, MessageType.Warning));
-                                        */
-                        }
+                        if(!EffectivelyEqual(insn, insns[i]))
+                            continue;
+                        if(!EffectivelyEqual(twoBeforeI[0], twoBefore[0]))
+                            continue;
+                        if(!EffectivelyEqual(twoBeforeI[1], twoBefore[1]))
+                            continue;
+                        if(mcount <= 0)
+                            continue;
+                        if(insn.Offset >= (int)monitorOffsetList[mcount - 1])
+                            continue;
+                        IList messages = new ArrayList();
+                        string etype = method.DeclaringType.FullName;
+                        Location loc = new Location(etype, method.Name,
+                                insn.Offset);
+                        Message msg = new Message(
+                                    "possible double-check locking",
+                                    loc, MessageType.Warning);
+                        messages.Add(msg);
+                        return messages;
                     }
                 }
                 comparisons[insns[i]] = twoBefore;
@@ -66,7 +73,7 @@
                 if(mcount > 0)
                     monitorOffsetList.RemoveAt(monitorOffsetList.Count - 1);
         }
-        return true;
+        return null;
     }
 
     private bool IsMonitorMethod(IInstruction insn, string methodName)
@@ -110,3 +117,5 @@
         return false;
     }
 }
+
+}
Index: rules/Gendarme.Rules.Correctness/BadRecursiveInvocationRule.cs
===================================================================
--- rules/Gendarme.Rules.Correctness/BadRecursiveInvocationRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Correctness/BadRecursiveInvocationRule.cs	(working copy)
@@ -1,6 +1,6 @@
 /*
- * BadRecChecker.cs: looks for instances of problematic recursive
- * invocations.
+ * BadRecursiveInvocationRule.cs: looks for instances of problematic
+ * recursive invocations.
  *
  * Authors:
  *   Aaron Tomb <atomb at soe.ucsc.edu>
@@ -13,17 +13,21 @@
  **********************************************************************/
 
 using System;
+using System.Collections;
 using Mono.Cecil;
 using Mono.Cecil.Cil;
 using Gendarme.Framework;
 
+namespace Gendarme.Rules.Correctness {
+
 public class BadRecursiveInvocationRule : IMethodRule {
 
-    public bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module,
-            ITypeDefinition type, IMethodDefinition method)
+    public IList CheckMethod (IAssemblyDefinition assembly,
+            IModuleDefinition module, ITypeDefinition type,
+            IMethodDefinition method, Runner runner)
     {
         if(method.Body == null)
-            return true;
+            return null;
 
         IInstructionCollection instructions = method.Body.Instructions;
 
@@ -56,21 +60,19 @@
                 }
                 if(rName.Equals(mName) && rDecl.Equals(mDecl) && argsEqual) {
                     if(LoadsVerbatimArgs(method, i)) {
-                        return false;
-                        /* TODO: restore the ability to generate
-                         * messages. */
-                        /*
+                        IList messages = new ArrayList();
                         string etype = method.DeclaringType.FullName;
                         Location loc = new Location(etype, method.Name,
                                 insn.Offset);
-                        report.AddMessage(new Message("suspicious recursive call",
-                                    loc, MessageType.Warning));
-                                    */
+                        Message msg = new Message("suspicious recursive call",
+                                    loc, MessageType.Warning);
+                        messages.Add(msg);
+                        return messages;
                     }
                 }
             }
         }
-        return true;
+        return null;
     }
 
     private bool LoadsVerbatimArgs([NonNull] IMethodDefinition method,
@@ -105,3 +107,5 @@
         return false;
     }
 }
+
+}
Index: rules/Gendarme.Rules.Correctness/Gendarme.Rules.Correctness.xml.in
===================================================================
--- rules/Gendarme.Rules.Correctness/Gendarme.Rules.Correctness.xml.in	(revision 54494)
+++ rules/Gendarme.Rules.Correctness/Gendarme.Rules.Correctness.xml.in	(working copy)
@@ -2,7 +2,13 @@
 	<rule	Name="BadRecursiveInvocationRule" 
 		Type="Gendarme.Rules.Correctness.BadRecursiveInvocationRule, Gendarme.Rules.Correctness, Version=@VERSION@, Culture=neutral, PublicKeyToken=null"
 		Uri="http://www.mono-project.com/Gendarme" >
-                <problem>Method or property '{0}' invokes itself recursively in a suspcious way.</problem>
+		<problem>Method or property '{0}' invokes itself recursively in a suspcious way.</problem>
 		<solution>Ensure that the parameters to the vary in such a way that the recursion will terminate.</solution>
 	</rule>
+	<rule	Name="NullDerefRule"
+		Type="Gendarme.Rules.Correctness.NullDerefRule, Gendarme.Rules.Correctness, Version=@VERSION@, Culture=neutral, PublicKeyToken=null"
+		Uri="http://www.mono-project.com/Gendarme" >
+		<problem>Method or property '{0}' might dereference a null pointer, or cause other code to do so.</problem>
+		<solution>Examine the detailed listing of problem locations, and ensure that the variables in question cannot be null.</solution>
+	</rule>
 </rules>
Index: rules/Gendarme.Rules.Correctness/Makefile.am
===================================================================
--- rules/Gendarme.Rules.Correctness/Makefile.am	(revision 54494)
+++ rules/Gendarme.Rules.Correctness/Makefile.am	(working copy)
@@ -8,8 +8,18 @@
 
 correctness_rules_sources_in = ../../AssemblyInfo.cs.in
 correctness_rules_generated_sources = $(correctness_rules_sources_in:.in=)
-correctness_rules_sources = BadRecursiveInvocationRule.cs OpCodeConstants.cs NonNullAttribute.cs
+correctness_rules_sources = BadRecursiveInvocationRule.cs OpCodeConstants.cs \
+			    NonNullAttribute.cs NonNullAttributeCollector.cs \
+			    NullDerefAnalysis.cs NullDerefRule.cs \
+			    NullDerefFrame.cs Nullity.cs \
+			    graph/INode.cs graph/Node.cs \
+			    graph/IEdge.cs graph/Edge.cs graph/IGraph.cs \
+			    graph/Graph.cs dataflow/BasicBlock.cs \
+			    dataflow/CFG.cs dataflow/CFGEdge.cs \
+			    dataflow/Dataflow.cs graph/DFS.cs \
+			    dataflow/IDataflowAnalysis.cs
 
+
 correctness_rules_build_sources = $(addprefix $(srcdir)/, $(correctness_rules_sources))
 correctness_rules_build_sources += $(correctness_rules_generated_sources)
 
Index: rules/Gendarme.Rules.Correctness/OpCodeConstants.cs
===================================================================
--- rules/Gendarme.Rules.Correctness/OpCodeConstants.cs	(revision 54494)
+++ rules/Gendarme.Rules.Correctness/OpCodeConstants.cs	(working copy)
@@ -12,6 +12,8 @@
  * See the included LICENSE.MIT file for details.
  **********************************************************************/
 
+namespace Gendarme.Rules.Correctness {
+
 public class OpCodeConstants {
 
     /* Opcodes starting with 0x00FF */
@@ -234,3 +236,5 @@
     public const int Sizeof = 0xFE1C;
     public const int Refanytype = 0xFE1D;
 }
+
+}
Index: rules/Gendarme.Rules.Correctness/NonNullAttribute.cs
===================================================================
--- rules/Gendarme.Rules.Correctness/NonNullAttribute.cs	(revision 54494)
+++ rules/Gendarme.Rules.Correctness/NonNullAttribute.cs	(working copy)
@@ -15,6 +15,8 @@
 
 using System;
 
+namespace Gendarme.Rules.Correctness {
+
 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field |
         AttributeTargets.Property | AttributeTargets.Parameter)]
 public class NonNullAttribute : System.Attribute {
@@ -22,3 +24,5 @@
     {
     }
 }
+
+}
Index: rules/Gendarme.Rules.Performance/Test/EmptyDestructorTest.cs
===================================================================
--- rules/Gendarme.Rules.Performance/Test/EmptyDestructorTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Performance/Test/EmptyDestructorTest.cs	(working copy)
@@ -87,21 +87,21 @@
 		public void NoDestructor ()
 		{
 			ITypeDefinition type = GetTest ("NoDestructorClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void EmptyDestructor ()
 		{
 			ITypeDefinition type = GetTest ("EmptyDestructorClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void Destructor ()
 		{
 			ITypeDefinition type = GetTest ("DestructorClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Performance/Test/IDisposableWithDestructorWithoutSuppressFinalizeTest.cs
===================================================================
--- rules/Gendarme.Rules.Performance/Test/IDisposableWithDestructorWithoutSuppressFinalizeTest.cs	(revision 54494)
+++ rules/Gendarme.Rules.Performance/Test/IDisposableWithDestructorWithoutSuppressFinalizeTest.cs	(working copy)
@@ -141,56 +141,56 @@
 		public void NoDestructor ()
 		{
 			ITypeDefinition type = GetTest ("NoDestructorClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void Destructor ()
 		{
 			ITypeDefinition type = GetTest ("DestructorClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void IDisposableNoDestructorWithoutSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("IDisposableNoDestructorWithoutSuppressFinalizeClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void IDisposableNoDestructorWithSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("IDisposableNoDestructorWithSuppressFinalizeClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void IDisposableDestructorWithoutSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("IDisposableDestructorWithoutSuppressFinalizeClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void IDisposableDestructorWithSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("IDisposableDestructorWithSuppressFinalizeClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void ExplicitIDisposableDestructorWithoutSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("ExplicitIDisposableDestructorWithoutSuppressFinalizeClass");
-			Assert.IsFalse (rule.CheckType (assembly, module, type));
+			Assert.IsNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 
 		[Test]
 		public void ExplicitIDisposableDestructorWithSuppressFinalize ()
 		{
 			ITypeDefinition type = GetTest ("ExplicitIDisposableDestructorWithSuppressFinalizeClass");
-			Assert.IsTrue (rule.CheckType (assembly, module, type));
+			Assert.IsNotNull (rule.CheckType (assembly, module, type, new MinimalRunner()));
 		}
 	}
 }
Index: rules/Gendarme.Rules.Performance/IDisposableWithDestructorWithoutSuppressFinalizeRule.cs
===================================================================
--- rules/Gendarme.Rules.Performance/IDisposableWithDestructorWithoutSuppressFinalizeRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Performance/IDisposableWithDestructorWithoutSuppressFinalizeRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 
 using Mono.Cecil;
 using Mono.Cecil.Cil;
@@ -45,11 +46,12 @@
 			return (md.ReturnType.ReturnType.ToString () == "System.Void");
 		}
 
-		private bool Recurse (IMethodDefinition method, int level)
+		private IList Recurse (IMethodDefinition method, int level)
 		{
 			// some methods have no body (e.g. p/invokes, icalls)
-			if (method.Body == null)
-				return false;
+			if (method.Body == null) {
+				return new ArrayList();
+			}
 
 			foreach (IInstruction ins in method.Body.Instructions) {
 				switch (ins.OpCode.Name) {
@@ -57,21 +59,21 @@
 				case "callvirt":
 					// are we calling GC.SuppressFinalize ?
 					if (ins.Operand.ToString () == "System.Void System.GC::SuppressFinalize(System.Object)")
-						return true;
+						return null;
 					else if (level < 3) {
 						IMethodDefinition callee = (ins.Operand as IMethodDefinition);
 						if (callee != null) {
-							if (Recurse (callee, level + 1))
-								return true;
+							if (Recurse (callee, level + 1) == null)
+								return null;
 						}
 					}
 					break;
 				}
 			}
-			return false;
+			return new ArrayList();
 		}
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			// #1 - does the type implements System.IDisposable ?
 			bool idisposable = false;
@@ -82,7 +84,7 @@
 				}
 			}
 			if (!idisposable)
-				return true;
+				return null;
 
 			// #2 - look for the Dispose method
 			IMethodDefinition dispose = null;
@@ -95,7 +97,7 @@
 				}
 			}
 			if (dispose == null)
-				return true;
+				return null;
 
 			// #3 - look for a destructor
 			IMethodDefinition destructor = null;
@@ -106,7 +108,7 @@
 				}
 			}
 			if (destructor == null)
-				return true;
+				return null;
 
 			// #4 - look if GC.SuppressFinalize is being called in the 
 			// Dispose method - or one of the method it calls
Index: rules/Gendarme.Rules.Performance/EmptyDestructorRule.cs
===================================================================
--- rules/Gendarme.Rules.Performance/EmptyDestructorRule.cs	(revision 54494)
+++ rules/Gendarme.Rules.Performance/EmptyDestructorRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 
 using Mono.Cecil;
 using Mono.Cecil.Cil;
@@ -36,7 +37,7 @@
 
 	public class EmptyDestructorRule : ITypeRule {
 
-		public bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type)
+		public IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner)
 		{
 			IMethodDefinition destructor = null;
 			// #1 - look for a destructor
@@ -47,7 +48,7 @@
 				}
 			}
 			if (destructor == null)
-				return true;
+				return null;
 
 			// #2 - destructor is present, look if it has any code within it
 			// i.e. look if is does anything else than calling it's base class
@@ -57,7 +58,7 @@
 					// it's empty if we're calling the base class destructor
 					IMethodReference mr = (ins.Operand as IMethodReference);
 					if ((mr == null) || (mr.Name != "Finalize"))
-						return true;
+						return null;
 					break;
 				case "nop":
 				case "leave.s":
@@ -68,11 +69,11 @@
 					break;
 				default:
 					// destructor isn't empty (normal)
-					return true;
+					return null;
 				}
 			}
 			// destructor is empty (bad / useless)
-			return false;
+			return new ArrayList();
 		}
 	}
 }
Index: framework/IRule.cs
===================================================================
--- framework/IRule.cs	(revision 54494)
+++ framework/IRule.cs	(working copy)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections;
 using Mono.Cecil;
 
 namespace Gendarme.Framework {
@@ -35,18 +36,18 @@
 	}
 
 	public interface IAssemblyRule : IRule {
-		bool CheckAssembly (IAssemblyDefinition assembly);
+		IList CheckAssembly (IAssemblyDefinition assembly, Runner runner);
 	}
 
 	public interface IModuleRule : IRule {
-		bool CheckModule (IAssemblyDefinition assembly, IModuleDefinition module);
+		IList CheckModule (IAssemblyDefinition assembly, IModuleDefinition module, Runner runner);
 	}
 
 	public interface ITypeRule : IRule {
-		bool CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type);
+		IList CheckType (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, Runner runner);
 	}
 
 	public interface IMethodRule : IRule {
-		bool CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method);
+		IList CheckMethod (IAssemblyDefinition assembly, IModuleDefinition module, ITypeDefinition type, IMethodDefinition method, Runner runner);
 	}
 }
Index: framework/Violation.cs
===================================================================
--- framework/Violation.cs	(revision 54494)
+++ framework/Violation.cs	(working copy)
@@ -27,17 +27,20 @@
 //
 
 using System;
+using System.Collections;
 
 namespace Gendarme.Framework {
 
 	public struct Violation {
 		public IRule Rule;
 		public object Violator;
+		public IList Messages;
 
-		public Violation (IRule rule, object violator)
+		public Violation (IRule rule, object violator, IList messages)
 		{
 			Rule = rule;
 			Violator = violator;
+			Messages = messages;
 		}
 	}
 }
Index: framework/Makefile.am
===================================================================
--- framework/Makefile.am	(revision 54494)
+++ framework/Makefile.am	(working copy)
@@ -6,8 +6,10 @@
 
 framework_sources_in = ../AssemblyInfo.cs.in
 framework_generated_sources = $(framework_sources_in:.in=)
-framework_sources = AssemblyManager.cs IRule.cs RuleCollection.cs RuleInformation.cs \
-	RuleInformationManager.cs Rules.cs Runner.cs Violation.cs Violations.cs
+framework_sources = AssemblyManager.cs IRule.cs RuleCollection.cs \
+		    RuleInformation.cs  RuleInformationManager.cs \
+		    Rules.cs Runner.cs Violation.cs Violations.cs \
+		    Message.cs Location.cs MinimalRunner.cs
 
 framework_build_sources = $(addprefix $(srcdir)/, $(framework_sources))
 framework_build_sources += $(framework_generated_sources)
Index: framework/Violations.cs
===================================================================
--- framework/Violations.cs	(revision 54494)
+++ framework/Violations.cs	(working copy)
@@ -48,14 +48,14 @@
 			}
 		}
 
-		public void Add (IRule rule, object obj)
+		public void Add (IRule rule, object obj, IList messages)
 		{
 			if (rule == null)
 				throw new ArgumentNullException ("rule");
 			if (obj == null)
 				throw new ArgumentNullException ("obj");
 
-			List.Add (new Violation (rule, obj));
+			List.Add (new Violation (rule, obj, messages));
 		}
 
 		public void Add (Violation v)
Index: framework/Runner.cs
===================================================================
--- framework/Runner.cs	(revision 54494)
+++ framework/Runner.cs	(working copy)
@@ -39,6 +39,7 @@
 
 		private Rules rules;
 		private Violations violations;
+		protected bool debug = false;
 
 		public Rules Rules {
 			get {
@@ -56,6 +57,12 @@
 			}
 		}
 
+		public bool Debug {
+			get {
+				return debug;
+			}
+		}
+
 		private IRule CreateRuleFromType (Type type)
 		{
 			return (IRule) Activator.CreateInstance (type);
@@ -96,30 +103,35 @@
 
 		public void Process (IAssemblyDefinition assembly)
 		{
+			IList messages;
 			foreach (IAssemblyRule rule in Rules.Assembly) {
-				if (!rule.CheckAssembly (assembly))
-					Violations.Add (rule, assembly);
+				messages = rule.CheckAssembly(assembly, this);
+				if (messages != null)
+					Violations.Add (rule, assembly, messages);
 			}
 
 			foreach (IModuleDefinition module in assembly.Modules) {
 
 				foreach (IModuleRule rule in Rules.Module) {
-					if (!rule.CheckModule (assembly, module))
-						Violations.Add (rule, module);
+					messages = rule.CheckModule(assembly, module, this);
+					if (messages != null)
+						Violations.Add (rule, module, messages);
 				}
 
 				foreach (ITypeDefinition type in module.Types) {
 
 					foreach (ITypeRule rule in Rules.Type) {
-						if (!rule.CheckType (assembly, module, type))
-							Violations.Add (rule, type);
+						messages = rule.CheckType(assembly, module, type, this);
+						if (messages != null)
+							Violations.Add (rule, type, messages);
 					}
 
 					foreach (IMethodDefinition method in type.Methods) {
 
 						foreach (IMethodRule rule in Rules.Method) {
-							if (!rule.CheckMethod (assembly, module, type, method))
-								Violations.Add (rule, method);
+							messages = rule.CheckMethod(assembly, module, type, method, this);
+							if (messages != null)
+								Violations.Add (rule, method, messages);
 						}
 					}
 				}


More information about the Mono-devel-list mailing list