Author: spouliot
Date: 2007-11-21 17:58:20 -0500 (Wed, 21 Nov 2007)
New Revision: 90114

Modified:
   
trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/CallingEqualsWithNullArgRule.cs
   trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/ChangeLog
Log:
2007-11-21  Sebastien Pouliot  <[EMAIL PROTECTED]> 

        * CallingEqualsWithNullArgRule.cs: Avoid creating MessageCollection 
        if unneeded (e.g. no error). Check for calli (along with call and 
        callvirt). Check previous instructions (not just the last one) for
        ldnull (skipping NOP and constrained). Fix bug on MS.NET where a 
        constrained instruction could be found just before).



Modified: 
trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/CallingEqualsWithNullArgRule.cs
===================================================================
--- 
trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/CallingEqualsWithNullArgRule.cs
       2007-11-21 22:46:33 UTC (rev 90113)
+++ 
trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/CallingEqualsWithNullArgRule.cs
       2007-11-21 22:58:20 UTC (rev 90114)
@@ -3,8 +3,10 @@
 //
 // Authors:
 //     Nidhi Rawal <[EMAIL PROTECTED]>
+//     Sebastien Pouliot  <[EMAIL PROTECTED]>
 //
 // Copyright (c) <2007> Nidhi Rawal
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to 
deal
@@ -32,29 +34,61 @@
 using Gendarme.Framework;
 
 namespace Gendarme.Rules.Correctness {
-       public class CallingEqualsWithNullArgRule: IMethodRule
-       {
+
+       public class CallingEqualsWithNullArgRule: IMethodRule {
+
+               private bool IsEquals (MethodReference md)
+               {
+                       if ((md == null) || (md.Name != "Equals"))
+                               return false;
+
+                       return (md.ReturnType.ReturnType.FullName == 
"System.Boolean");
+               }
+
+               private bool IsCall (Instruction ins)
+               {
+                       OpCode oc = ins.OpCode;
+                       return ((oc == OpCodes.Call) || (oc == OpCodes.Calli) 
|| (oc == OpCodes.Callvirt));
+               }
+
+               private bool IsPreviousLdnull (Instruction ins)
+               {
+                       while (ins.Previous != null) {
+                               OpCode oc = ins.Previous.OpCode;
+                               if (oc == OpCodes.Ldnull) {
+                                       return true;
+                               } else if ((oc == OpCodes.Constrained) || (oc 
== OpCodes.Nop)) {
+                                       ins = ins.Previous;
+                               } else {
+                                       return false;
+                               }
+                       }
+                       return false;
+               }
+
                public MessageCollection CheckMethod (MethodDefinition method, 
Runner runner)
                {
-                       MessageCollection messageCollection = new 
MessageCollection ();
-
                        if (!method.HasBody)
                                return null;
 
-                       foreach (Instruction ins in method.Body.Instructions)
-                               if (ins.OpCode == OpCodes.Call || ins.OpCode == 
OpCodes.Callvirt) {
-                                       MethodReference calledMethod = 
(MethodReference) ins.Operand;
-                                       if (calledMethod.Name == "Equals" && 
calledMethod.ReturnType.ReturnType.FullName == "System.Boolean")
-                                               if (ins.Previous.OpCode == 
OpCodes.Ldnull) {
-                                                       Location location = new 
Location (method.DeclaringType.FullName, method.Name, 0);
-                                                       Message message = new 
Message ("You should not call Equals (null), i.e., argument should not be 
null", location, MessageType.Error);
-                                                       messageCollection.Add 
(message);
-                                               }
+                       MessageCollection mc = null;
+                       foreach (Instruction ins in method.Body.Instructions) {
+                               // if we're calling bool type.Equals()
+                               if (IsCall (ins) && IsEquals (ins.Operand as 
MethodReference)) {
+                                       // and that the previous, real, 
instruction is loading a null value
+                                       if (IsPreviousLdnull (ins)) {
+                                               Location location = new 
Location (method.DeclaringType.FullName, method.Name, ins.Offset);
+                                               Message message = new Message 
("You should not call Equals (null), i.e., argument should not be null", 
location, MessageType.Error);
+
+                                               if (mc == null)
+                                                       mc = new 
MessageCollection (message);
+                                               else
+                                                       mc.Add (message);
+                                       }
                                }
+                       }
 
-                       if (messageCollection.Count == 0)
-                               return null;
-                       return messageCollection;
+                       return mc;
                }
        }
 }

Modified: trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/ChangeLog
===================================================================
--- trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/ChangeLog     
2007-11-21 22:46:33 UTC (rev 90113)
+++ trunk/cecil/gendarme/rules/Gendarme.Rules.Correctness/ChangeLog     
2007-11-21 22:58:20 UTC (rev 90114)
@@ -1,3 +1,11 @@
+2007-11-21  Sebastien Pouliot  <[EMAIL PROTECTED]> 
+
+       * CallingEqualsWithNullArgRule.cs: Avoid creating MessageCollection 
+       if unneeded (e.g. no error). Check for calli (along with call and 
+       callvirt). Check previous instructions (not just the last one) for
+       ldnull (skipping NOP and constrained). Fix bug on MS.NET where a 
+       constrained instruction could be found just before).
+
 2007-11-03  Nestor Salceda  <[EMAIL PROTECTED]>
        
        * Gendarme.Rules.Correctness.xml.in: Added the Uri for

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to