3

I want to find all methods that can explicitly return null.

Is this possible in NDepend using CQL?

Steve Dunn
  • 21,044
  • 11
  • 62
  • 87

1 Answers1

2

Not for now, CQL so far doesn't know about value of variables, fields and values returned.

However this default rule below is proposed. The idea is that if a method returns a reference it should never be null, and a contract should be added to assert this. If you wish such a method to return null, instead use the Try... pattern, like in TryParse(string s, out T val):bool.

// <Name>Public methods returning a reference needs a contract to ensure that a non-null reference is returned</Name>
warnif count > 0
let ensureMethods = Application.Methods.WithFullName(
   "System.Diagnostics.Contracts.__ContractsRuntime.Ensures(Boolean,String,String)")

from ensureMethod in ensureMethods
from m in ensureMethod.ParentAssembly.ChildMethods where 
  m.IsPubliclyVisible &&
 !m.IsAbstract &&
  m.ReturnType != null &&
  // Identify that the return type is a reference type
  (m.ReturnType.IsClass || m.ReturnType.IsInterface) &&
 !m.IsUsing(ensureMethod) &&

  // Don't match method not implemented yet!
 !m.CreateA("System.NotImplementedException".AllowNoMatch())

select new { 
   m, 
   ReturnTypeReference = m.ReturnType 
}

//<Description>
// **Code Contracts** are useful to decrease ambiguity between callers and callees.
// Not ensuring that a reference returned by a method is *non-null* leaves ambiguity 
// for the caller. This rule matches methods returning an instance of a reference type 
// (class or interface) that don't use a **Contract.Ensure()** method.
//
// *Contract.Ensure()* is defined in the **Microsoft Code Contracts for .NET** 
// library, and is typically used to write a code contract on returned reference:
// *Contract.Ensures(Contract.Result<ReturnType>() != null, "returned reference is not null");*
// https://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970
//</Description>

//<HowToFix>
// Use *Microsoft Code Contracts for .NET* on the public surface of your API,
// to remove most ambiguity presented to your client. Most of such ambiguities
// are about *null* or *not null* references.
//
// Don't use *null* reference if you need to express that a method might not 
// return a result. Use instead the **TryXXX()** pattern exposed for example 
// in the *System.Int32.TryParse()* method.
//</HowToFix>
Patrick from NDepend team
  • 13,237
  • 6
  • 61
  • 92