Hi,
We’re getting false positives on S2259: is null on at least one execution path, when our null check is in method. We have a wrapper on checking null to simplify it, but sonar doesn’t understand it and throwing an errors all the time. Can you help us, please?
Example below:
public class Class1
{
public void Check() {
Monkey? _monkey = null;
QAssert.IsNotNull(_monkey);
Console.WriteLine(_monkey.Name);
}
}
public class Monkey
{
public string? Name { get; set; }
}
public static class QAssert
{
public static void IsNotNull(Monkey? o)
{
if (o is null)
{
throw new ArgumentException("Wrong Monkey");
}
}
}
Hi Łukasz,
I can reproduce the behavior: we are aware of this limitation but have a workaround.
The symbolic execution engine, that powers the rule S2259, is currently single-method-based and is not looking into the effects that the method QAssert.IsNotNull has on the Class1.Check.
That means that after the second line of Class1.Check (QAssert.IsNotNull(_monkey);), the engine doesn’t infer that _monkey can’t possibly be null, because otherwise QAssert.IsNotNull would have raised an exception and the flow would have never reached the instruction Console.WriteLine(_monkey.Name);.
Scenarios involving constraints from other methods are complex to handle, and while we may tackle them in the future, we provide a workaround to handle cases like yours, by declaring a ValidatedNotNullAttribute and decorating the Monkey?o parameter of QAssert.IsNotNull with that attribute:
public static class QAssert
{
public static void IsNotNull([ValidatedNotNull]Monkey? o)
{
if (o is null)
{
throw new ArgumentException("Wrong Monkey");
}
}
}
public sealed class ValidatedNotNullAttribute : Attribute { }
That will help our engine understand that, whenever QAssert.IsNotNull is called, its first parameter is going to be checked against null, and have that constraint in the following steps of the execution.
More information about the use of the ValidatedNotNullAttribute is available in the description of the C# version of the S2259 rule: RSPEC