SonarSource / sonar-dotnet

Code analyzer for C# and VB.NET projects
https://redirect.sonarsource.com/plugins/csharp.html
GNU Lesser General Public License v3.0
790 stars 227 forks source link

Fix S2589 FN: Support recursive pattern redundant null check #9203

Open jnyrup opened 6 months ago

jnyrup commented 6 months ago

Description

When using a property pattern is { } as a null check S2589 does not recognize it as redundant. Is that a bug or a deliberate design decision?

Repro steps

public class Class1
{
    public void A(string s)
    {
        _ = s.GetHashCode();
        if (s is not null) { /* Ignore */ } // TP
    }

    public void B(string s)
    {
        _ = s.GetHashCode();
        if (s != null) { /* Ignore */ } // TP
    }

    public void C(string s)
    {
        _ = s.GetHashCode();
        if (!ReferenceEquals(s, null)) { /* Ignore */ } // TP
    }

    public void E(string s)
    {
        _ = s.GetHashCode();
        if (s is { }) { /* Ignore */ } // FN: null check is not considered redundant
    }
}

Expected behavior

E() should report S2589

Actual behavior

E() does not report S2589

Known workarounds

Use is not null instead of is {} to trigger S2589

Related information

gregory-paidis-sonarsource commented 6 months ago

Hey,

That is a good find. As you might know, recursive pattern can be tricky, as it can appear in many, many forms. I will document it with a reproducer in our unit tests, and it will be taken care of at some point in the future, when we tackle Symbolic Execution FP/FNs.

Thanks for raising the issue.

PS: FluentAssertions is awesome!

jnyrup commented 6 months ago

Thanks for looking into this and for the kind words regarding Fluent Assertions

As you might know, recursive pattern can be tricky, as it can appear in many, many forms.

Yeah, I did think of the many forms recursive patterns can take. Without having the faintest insights into your analyzers, I wondered if perhaps is { } could somehow be special cased to be equivalent to a null check and then (for now) ignore the more complex patterns.