t3chb0t
t3chb0t

Reputation: 18655

Can I teach ReSharper a custom null check?

ReSharper is clever enough to know that a string.Format requires a not-null format argument so it warns me about it when I simply write

_message = string.Format(messageFormat, args);

where messageFormat can indeed be null. As soon as I add a condition for this variable:

if (!string.IsNullOrEmpty(messageFormat))
{
    _message = string.Format(messageFormat, args);
}

the warning disappears. Unfortunately it doesn't when I use an extension method:

if (messageFormat.IsNotNullOrEmpty())
{
    _message = string.Format(messageFormat, args); // possible 'null' assignment warning
}

My question is: is there a way to teach ReSharper that my extension method has the same meaning as !string.IsNullOrEmpty(messageFormat)?

The extension is defined as:

public static bool IsNotNullOrEmpty([CanBeNull] this string value) => !IsNullOrEmpty(value);

Upvotes: 16

Views: 1571

Answers (1)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

Yes there is. You need to use the ReSharper annotations to guide ReSharper's analysis. You're already using [CanBeNull] so they're already defined in your project.

The one you'll be interested in is ContractAnnotationAttribute:

Contract annotations let you define expected outputs for given inputs, or put in other words, define dependencies between reference type and boolean arguments of a function and its return value. The mechanism of contract annotations allows creating APIs that could be consumed in easier and safer way.

This is how you use it:

[ContractAnnotation("null => false")]
public static bool IsNotNullOrEmpty(this string value)
    => !string.IsNullOrEmpty(value);

The argument is a map of possible inputs (null, notnull, true, false) to outputs (null, notnull, canbenull, true, false, halt):

Here's another example:

[ContractAnnotation("foo: null => halt; bar: notnull => notnull")]
public string Frob(string foo, string bar)

Means that the decorated function will never return (or throw an exception) if you pass it null to the foo parameter, and guarantees that it won't return null if you pass a non-null value to bar.

The documentation describes the syntax in more detail.


Here's what happens without the attribute:

before

The warning disappears after you add it:

after

Upvotes: 16

Related Questions