False Positive on csharpsquid:S2259

Then tell us:

  • What language is this for? CSharp
  • Which rule? csharpsquid:S2259
  • Why do you believe it’s a false-positive/false-negative? I have made recommended changes
  • Are you using
    • SonarQube Cloud? yes
    • SonarQube Server / Community Build - which version? no
    • SonarQube for IDE - which IDE/version? yes (for Rider, 10.12.0.79769)
      • in connected mode with SonarQube Server / Community Build or SonarQube Cloud? (tried both)
  • How can we reproduce the problem? Give us a self-contained snippet of code (formatted text, no screenshots)

          var singleBars = (ISingleBars)rebargrp;
          if (singleBars == null) {
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Rebar group is null.");
            return;
          }

          var positions = singleBars.Positions;

          if (positions == null) {
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Positions are null for the rebar group.");
            return;
          }

          foreach (var pos in positions) {
          ...
          }

The problem is on the positions inside the foreach. I have tried a lot of other ways of doing that that picked up from different posts. like putting the property in a variable so SonarQube is seeing that I made the check for that variable, not use complex pattern matching in switch statements (that is why I am also checking singleBars)

I am not sure what is the problem, but I don’t think it is related on this particular piece of code, as it looks correct to me. Could it be related to a comment set on the singleBars.Positions property API that warns thing might be null? Which take precedence?

    /// <summary>The positions for the <see cref="P:Oasys.AdSec.Reinforcement.Groups.ISingleBars.BarBundle" />s.</summary>
    /// <exception cref="!:System.ArgumentNullException">If Positions is set to null</exception>
    IList<IPoint> Positions { get; set; }

I would appreciate a workaround.

Although I think your snippit should not report anything, you might want to refactor, using pattern matching anyway:

if (rebargrp is not ISingleBars singleBars) 
{
    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Rebar group is null.");
    return;
}

if (singleBars.Positions is not { } positions) {
    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Positions are null for the rebar group.");
    return;
}

foreach (var pos in positions) {
    // ...
}

Does this also report?

2 Likes

Hey @spsarras thanks for your report.
This looks like a clear FP to me. However, I cannot reproduce it locally. Could you please do one of the following:

  • Check the issue in SonarQube Cloud and give us a screenshot of the issue. The newly added Execution Flows should give us a hint at what is going wrong here.
  • Create a fully self-contained reproducer that I can analyze without making assumptions about the rest of the solution.

For reference, this is my attempt at reproducing it (SharpLab link):

void Method(object rebargrp)
{
    var singleBars = (ISingleBars)rebargrp;
    if (singleBars == null) {
        AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Rebar group is null.");
        return;
    }

    var positions = singleBars.Positions;

    if (positions == null) {
        AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Positions are null for the rebar group.");
        return;
    }

    foreach (var pos in positions) {
        Console.Write(pos);
    }
}

void AddRuntimeMessage(object warning, string v)
{
    throw new NotImplementedException();
}

internal static class GH_RuntimeMessageLevel
{
    public static object Warning { get; }
}

internal interface ISingleBars
{
    IEnumerable<object> Positions { get; }
}

I could do you one better! This is an open source project, so you should be able to find the report on our dashboard here: SonarQube Cloud
This appears (correctly) on the main branch: SonarQube Cloud

This is the commit I’ve added the ignore. AdSecGh-64 spike testing component cherry by psarras · Pull Request #105 · arup-group/AdSec-Grasshopper · GitHub and as you can see the previous commit, also had a failed SonarQube and I was using a switch case, where it guarantees that rebargrp is of that type. I did also try to do further (unnecessary) checks as above, to try and convince SonarQube to stop complaining :slight_smile: Unfortunately, I would need to revert to demonstrate you that sonarQube on the dashboard was actually complaining with the following solution.

Ideally this should be enough:

// loop through rebar groups in flattened section
      foreach (var rebargrp in flat.ReinforcementGroups) {
        switch (rebargrp) {
          case ISingleBars singleBars:
            var positions = singleBars.Positions;

            if (positions == null) {
              AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Positions are null for the rebar group.");
              return;
            }

            foreach (var pos in positions) {}
         }
       }

let me know if I can provide more files. I can perhaps set a new branch that shows the problem on the daskboard for you.

2 Likes

ok, in trying to provide some evidence I think I found the problem…

Error


No error

The difference? There is a Try/Catch on the first one.

I think it still is a FP, I don’t understand why…but the reason I changed to a switch statement was to remove the try/Catch so I can fix the actual FP in my case but it still seems to misbehave if you have a try catch around a switch?

I managed to reproduce it and identify the underlying issue. Thanks for sharing all the details. I created an internal ticket to track the issue and it will be fixed in a future hardening sprint.
For reference, here is my reproducers:

void Method(IEnumerable<object> rebargrps)
{
    foreach (var rebargrp in rebargrps)
    {
        try // first try if not a link group type
        {
            var snglBrs = (ISingleBars)rebargrp;
            foreach (var pos in snglBrs.Positions)  // FP
            {
                Console.Write(pos);
            }
        }
        catch (Exception)
        {
        }
    }
}