Skip to content

Commit

Permalink
Merge pull request #356 from PHPCSStandards/php8.0/add-support-for-ma…
Browse files Browse the repository at this point in the history
…tch-expressions

PHP 8.0: add support for match expressions
  • Loading branch information
jrfnl committed Oct 15, 2022
2 parents dbc671c + 390e964 commit 25ac2cd
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 1 deletion.
2 changes: 2 additions & 0 deletions PHPCSUtils/Tokens/Collections.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class Collections
* DEPRECATED: Control structure tokens.
*
* @since 1.0.0-alpha2
* @since 1.0.0-alpha4 Added the T_MATCH token for PHP 8.0 match expressions.
*
* @deprecated 1.0.0-alpha4 Use the {@see Collections::controlStructureTokens()} method instead.
*
Expand All @@ -217,6 +218,7 @@ class Collections
\T_DO => \T_DO,
\T_WHILE => \T_WHILE,
\T_DECLARE => \T_DECLARE,
\T_MATCH => \T_MATCH,
];

/**
Expand Down
5 changes: 4 additions & 1 deletion PHPCSUtils/Utils/Arrays.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Arrays

// Inline function and control structures to skip over.
\T_FN => \T_FN,
\T_MATCH => \T_MATCH,
];

/**
Expand Down Expand Up @@ -295,6 +296,7 @@ public static function getOpenClose(File $phpcsFile, $stackPtr, $isShortArray =
*
* @since 1.0.0
* @since 1.0.0-alpha2 Now allows for arrow functions in arrays.
* @since 1.0.0-alpha4 Now allows for match expressions in arrays.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being examined.
* @param int $start Stack pointer to the start of the array item.
Expand Down Expand Up @@ -344,7 +346,8 @@ public static function getDoubleArrowPtr(File $phpcsFile, $start, $end)

// Skip over closed scopes which may contain foreach structures or generators.
if ((isset(Collections::closedScopes()[$tokens[$doubleArrow]['code']]) === true
|| $tokens[$doubleArrow]['code'] === \T_FN)
|| $tokens[$doubleArrow]['code'] === \T_FN
|| $tokens[$doubleArrow]['code'] === \T_MATCH)
&& isset($tokens[$doubleArrow]['scope_closer']) === true
) {
$doubleArrow = $tokens[$doubleArrow]['scope_closer'];
Expand Down
1 change: 1 addition & 0 deletions PHPCSUtils/Utils/ControlStructures.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ControlStructures
* regarded as empty.
*
* @since 1.0.0
* @since 1.0.0-alpha4 Added support for PHP 8.0 match control structures.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the token we are checking.
Expand Down
18 changes: 18 additions & 0 deletions Tests/Utils/Arrays/GetDoubleArrowPtrTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ $array = [
/* testDoubleArrowTokenizedAsTstring-PHPCS2865 */
$obj->fn => 'value',

/* testNoArrowValueMatchExpr */
match($a) {
FOO => BAR,
default => [0 => BAZ],
},

/* testArrowValueMatchExpr */
'key' => match($a) {
[0 => 10] => BAR,
default => BAZ,
},

/* testArrowKeyMatchExpr */
match($a) {
FOO => BAR,
default => [0 => 10],
} => 'value',

/* testEmptyArrayItem */
// Intentional parse error.
,
Expand Down
15 changes: 15 additions & 0 deletions Tests/Utils/Arrays/GetDoubleArrowPtrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ public function dataGetDoubleArrowPtr()
'testMarker' => '/* testDoubleArrowTokenizedAsTstring-PHPCS2865 */',
'expected' => 10,
],

// Safeguard that PHP 8.0 match expressions are handled correctly.
'test-no-arrow-value-match-expression' => [
'testMarker' => '/* testNoArrowValueMatchExpr */',
'expected' => false,
],
'test-double-arrow-value-match-expression' => [
'testMarker' => '/* testArrowValueMatchExpr */',
'expected' => 8,
],
'test-double-arrow-key-match-expression' => [
'testMarker' => '/* testArrowKeyMatchExpr */',
'expected' => 38,
],

'test-empty-array-item' => [
'testMarker' => '/* testEmptyArrayItem */',
'expected' => false,
Expand Down
22 changes: 22 additions & 0 deletions Tests/Utils/ControlStructures/HasBodyTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,28 @@ do
echo $i;
while (++$i <= 10);


/*
* PHP 8.0 match expressions.
*/

/* testMatchEmptyBody */
// Intentional fatal error, "unhandled match case", but not the concern of this method.
$match = match($a) {};

/* testMatchEmptyBodyWithComment */
// Intentional fatal error, "unhandled match case", but not the concern of this method.
$match = match($a) {
// Deliberately empty.
};

/* testMatchWithCode */
$match = match ($a) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};

// Live coding.
// Intentional parse error. This test has to be the last in the file.
if ($a) {
Expand Down
23 changes: 23 additions & 0 deletions Tests/Utils/ControlStructures/HasBodyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,29 @@ public function dataHasBody()
'hasBody' => true,
'hasNonEmptyBody' => true,
],

/*
* Match without body cannot be tested as, in that case, `match` will tokenize as `T_STRING`.
* Without body (`match();`), match will either yield a parse error
* or be interpreted as a function call (`\match();` or `self::match()` etc).
*/

'match-empty-body' => [
'testMarker' => '/* testMatchEmptyBody */',
'hasBody' => true,
'hasNonEmptyBody' => false,
],
'match-empty-body-comment-only' => [
'testMarker' => '/* testMatchEmptyBodyWithComment */',
'hasBody' => true,
'hasNonEmptyBody' => false,
],
'match-with-code' => [
'testMarker' => '/* testMatchWithCode */',
'hasBody' => true,
'hasNonEmptyBody' => true,
],

'else-live-coding' => [
'testMarker' => '/* testElseLiveCoding */',
'hasBody' => true,
Expand Down

0 comments on commit 25ac2cd

Please sign in to comment.