Skip to content

Incorrect tokenization for ternary operator with match inside of it #3789

@schlndh

Description

@schlndh

Describe the bug
It seems that normally the ? ... : ... should be tokenized as T_INLINE_THEN ... T_INLINE_ELSE, however if there is a match with default branch inside the "then" part then : remains T_COLON, which can break some sniffs (in my case it's this 3rd party sniff).

Code sample

<?php

$a = $b !== null
	? match ($c) {
		default => 5,
	}
	: null;

This is tokenized as:

    *** START PHP TOKENIZING ***
    Process token [0]: T_OPEN_TAG => <?php\n
    Process token [1]: T_WHITESPACE => \n
    Process token [2]: T_VARIABLE => $a
    Process token [3]: T_WHITESPACE => ·
    Process token  4 : T_EQUAL => =
    Process token [5]: T_WHITESPACE => ·
    Process token [6]: T_VARIABLE => $b
    Process token [7]: T_WHITESPACE => ·
    Process token [8]: T_IS_NOT_IDENTICAL => !==
    Process token [9]: T_WHITESPACE => ·
    Process token [10]: T_STRING => null
    Process token [11]: T_WHITESPACE => \n\t
    Process token  12 : T_NONE => ?
        * token 12 changed from ? to T_INLINE_THEN
    Process token [13]: T_WHITESPACE => ·
    Process token [14]: T_MATCH => match
    Process token [15]: T_WHITESPACE => ·
    Process token  16 : T_OPEN_PARENTHESIS => (
    Process token [17]: T_VARIABLE => $c
    Process token  18 : T_CLOSE_PARENTHESIS => )
    Process token [19]: T_WHITESPACE => ·
    Process token  20 : T_OPEN_CURLY_BRACKET => {
    Process token [21]: T_WHITESPACE => \n\t\t
    Process token [22]: T_DEFAULT => default
        * token 24 changed from T_DOUBLE_ARROW to T_MATCH_ARROW
        * token 22 changed from T_DEFAULT to T_MATCH_DEFAULT
    Process token [23]: T_WHITESPACE => ·
    Process token [24]: T_MATCH_ARROW => =>
    Process token [25]: T_WHITESPACE => ·
    Process token [26]: T_LNUMBER => 5
    Process token  27 : T_COMMA => ,
    Process token [28]: T_WHITESPACE => \n\t
    Process token  29 : T_CLOSE_CURLY_BRACKET => }
    Process token [30]: T_WHITESPACE => \n\t
    Process token  31 : T_COLON => :
        * token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE
    Process token [32]: T_WHITESPACE => ·
    Process token [33]: T_STRING => null
    Process token  34 : T_SEMICOLON => ;
    Process token [35]: T_WHITESPACE => \n
    *** END PHP TOKENIZING ***

To reproduce
Steps to reproduce the behavior:

  1. Create a file called test.php with the code sample above...
  2. Run phpcs -vvv test.php ...
  3. See the generated tokens

Expected behavior
Tokenize ? ... : ... as T_INLINE_THEN ... T_INLINE_ELSE even with match (...) {default => ...} inside then branch.

Versions (please complete the following information):

  • OS: Linux
  • PHP: 8.2
  • PHPCS: 3.7.2
  • Standard: Any

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions