Open r1pped opened 1 year ago
@r1pped Thanks for reporting this. I can confirm the issue.
It's actually the combination of the curly braces being used for the first case
AND the deliberately fall-through (no break
/continue
) which causes the issue.
It results in the second case
having the T_COLON
as a scope_opener
, the T_BREAK
as the scope_closer
, but the T_BREAK
doesn't get its scope_condition
set to the first case
, which is what the sniff expects and what should have happened.
This will need some digging into what exactly is going wrong with the setting of the scope_*
indexes.
I'm noticing another inconsistency in the token arrays related to this.
switch (true) {
case 2 === 2:
echo "bar";
break;
case 3 === 3:
echo "bar";
break;
}
In the above, the T_COLON
and the T_BREAK
tokens have only the T_SWITCH
in the conditions
array. The tokens in between have T_SWITCH
and T_CASE
.
The T_CASE
and the associated T_COLON
and T_BREAK
each have the same set of scope_condition
(T_CASE
), scope_opener
(T_COLON
) and scope_closer
(T_BREAK
) set.
switch (true) {
case 1 === 1: {
echo "foo";
break;
}
case 2 === 2: {
echo "bar";
break;
}
}
In this second code sample, the T_OPEN_CURLY_BRACKET
has both the T_SWITCH
and the T_CASE
in the conditions
array, while the T_CLOSE_CURLY_BRACKET
only has the T_SWITCH
in the conditions
array.
The T_CASE
and the associated T_COLON
and T_BREAK
each have the same set of scope_condition
(T_CASE
), scope_opener
(T_COLON
) and scope_closer
(T_BREAK
) set.
👉🏻 _IMO it would be more consistent if the T_OPEN_CURLY_BRACKET
would not have the T_CASE
in the conditions
array._
If we then take (a variation on) the original code sample:
switch (true) {
case 1 === 1: {
echo "foo";
// omitting break; causes Internal.Exception
}
case 2 === 2:
echo "bar";
break;
case 3 === 3:
echo "bar";
break;
}
The first case
behaves like the second code sample above (open curly has two conditions, close curly one, rest consistent).
The second case
is where things get weird:
T_COLON
has only the T_SWITCH
in the conditions
array, while the T_BREAK
has both the T_SWITCH
as well as the (second) T_CASE
in the conditions
array.T_COLON
has the scope_condition
set to the second T_CASE
, the scope_opener
to itself and the scope_closer
to the T_BREAK
(in the second case).T_BREAK
(in the second case) has NO scope_condition
, scope_opener
or scope_closer
set AT ALL.The third case
behaves as expected, exactly like the first code sample above (everything consistent).
I'm fairly confident that the culprit is somewhere in the last part of the Tokenizer\PHP::processAdditional()
method (after the // Only interested in CASE and DEFAULT statements from here on in.
comment), but as there are no dedicated tests covering that part of the code, changing anything there has a high risk of breaking things elsewhere.
@gsherwood Got an opinion on this ?
Describe the bug Running sniffer with PSR-12 standard on some valid switch statements (mixing curly braces syntax with classic syntax) shows an Internal.Exception, which aborts checking rest of the code
Code sample
To reproduce Steps to reproduce the behavior:
test.php
with the code sample above...phpcs --standard=psr12 test.php
Time: 31ms; Memory: 8MB