-
-
Notifications
You must be signed in to change notification settings - Fork 80
Description
The problem
PHP 8.2 introduced Disjunctive Normal Form Types, which now adds parentheses to the tokens allowed within type declarations.
This is currently not yet supported by PHP_CodeSniffer and the PHP_CodeSniffer\Tokenizers\PHP
class will not always handle tokens within DNF types correctly, which can lead to false positives/false negatives being reported for sniffs and incorrect fixes being made.
Typical issues in the Tokenizer:
- The
array
keyword when used in a type declaration may not be retokenized fromT_ARRAY
toT_STRING
. - The
true
/false
/null
keywords when used in a type declaration may not be retokenized fromT_STRING
toT_TRUE
/T_FALSE
/T_NULL
. - The
&
and|
characters may not be retokenized toT_TYPE_UNION
/T_TYPE_INTERSECTION
.
Typical resulting sniff issues:
- Sniffs handling arbitrary parentheses spacing may act on parentheses in DNF types.
- Sniffs listening for the
array
keyword may try to act on thearray
keyword when used in a DNF type. - Sniffs listening for bitwise and/or operators may act on the
&
and|
characters in DNF types. - etc
These issues also impact the functioning of the following PHPCS native helper functions and by extension all sniffs which use these methods:
File::getMethodParameters()
(parameter types)File::getMethodProperties()
(return types)File::getMemberProperties()
(property types)File::isReference()
Compounding the Problem
Aside from the above, standards may want to treat (spacing around) parentheses in DNF types differently from (spacing around) parentheses used in other places in a code base.
Proposed Solution
To support DNF types the PHP_CodeSniffer\Tokenizers\PHP
class will need significant updates.
When making these updates, I propose to include a change to retokenize the open and close parentheses when used in DNF types as T_TYPE_OPEN_PARENTHESIS
and T_TYPE_CLOSE_PARENTHESIS
respectively.
Having separate, PHPCS native tokens for the DNF parentheses will allow for sniff developers to decide on a case-by-case basis whether a sniff should or should not act on DNF parentheses.
This change also follows in the footsteps of the retokenization of the &
and |
tokens (when used in types) to T_TYPE_*
tokens.
As part of this change, the new T_TYPE_OPEN_PARENTHESIS
and T_TYPE_CLOSE_PARENTHESIS
tokens will need to be handled correctly by the PHP_CodeSniffer\Tokenizers\Tokenizer
class and tokens should get the parenthesis_opener
, parenthesis_closer
and nested_parenthesis
tokens, same as if the tokens were the "normal" T_OPEN_PARENTHESIS
and T_CLOSE_PARENTHESIS
tokens.
Open question
As PHP 8.2 has been out for a while, some external standards may have implemented work-arounds for the current state of things.
So, aside from opinions on the above proposal itself, I would also like to hear opinions on when this change should be made.
- Should this change go into the next PHPCS 3.x minor (once the PR has been prepared) ?
- Or should this change go into PHPCS 4.0 ? (expected in 3-4 months)
/cc @asispts @dingo-d @fredden @GaryJones @greg0ire @kukulich @michalbundyra @Ocramius @sirbrillig @stronk7 @weierophinney @wimg