Incorrect suggestion S5797 for state changing in match cases within an outer loop

Please provide

  • Operating system: MacOS Sequoia 15.0.1
  • Visual Studio version: 1.94.1
  • SonarLint plugin version: 4.11.1
  • Programming language you’re coding in: python 3.12.4
  • Is connected mode used:
    • Connected to SonarCloud or SonarQube (and which version): No
    • settings.json statement: “sonarlint.connectedMode.connections.sonarqube”: ,

And a thorough description of the problem / question:
I am receiving this message twice but I believe inQuotes can change based on the prior passes through the match on codepoints in the string. The intent is to mark when we’ve encountered our first double quote and when we’ve found its matching double quote (skipping escaped quotes in between). I think the rule needs to take into consideration the outer loop that can allow multiple passes through the match block:

Replace this expression; used as a condition it will always be constant. [+1 location]

For the inQuotes variable in the code below for the if/elif inQuotes tests:

        inQuotes = False
        for i in range(0, len(codePoints)):
            chPrior = ch  # save prior character
            ch = codePoints[i]
            match (ch):
                case 0x2C:
                    if inQuotes:
                        sb += str(ch)
                    else:
                        # don't save the comma
                        strList.append(sb)
                        sb = ""
                    break
                case 0x22:
                    # check if this quote is escaped
                    if chPrior == 0x5C:
                        # just keep as is
                        sb = sb + str(ch)
                    elif inQuotes:
                        if i < len(codePoints) - 1:
                            # check if this is an escaped quote
                            if codePoints[i + 1] == 0x22:
                                sb = sb + str(ch)
                                break
                            else:
                                # if prior is a quote this is escaped
                                if chPrior == 0x22:
                                    sb += str(ch)
                                    break
                        # else this is ending the quoted field
                        inQuotes = False
                    else:
                        inQuotes = True
                    break
                case _:
                    sb += str(ch)
                    break

This problem, where lint does not look at variables outside the match block, gets reported as S1854, stating that setting a variable within the match block used in the loop outside the match is unnecessary.

Hello,

In the example you provided, you mention the outer for loop. I assume that this is the loop present in your example. Feel free to correct me if this is wrong.

Assuming that, the rule being raised should be correct.
The inQuotes variable is initialized at False. It can then only be mutated in the 0x22 case.
But the mutation is always followed by the break instruction. In Python, break only works on loops, which means that the loop does not run after the mutation.

It is therefore impossible to reach either of the raised issues.
If you remove the break after mutating inQuotes, the issues disappear as I would expect.

A smaller test case is this one :

def reproducer():
    condition = False

    for i in range(0, 3):
        print(f"{i=}, {condition=}")
        match (i):
            case 0:
                condition = True # run on the first iteration and mutates condition
                print("SET")
                break # We leave the loop immediately after the mutation
            case 1:
                if condition: # S5797 is raised here
                    print("HIT")
            case _:
                ...

reproducer()

When running the code, we never get HIT despite the condition being set to True.

I hope my answer helped you. If I misunderstood the problem, feel free to correct me.

1 Like