Skip to content

Commit

Permalink
Allow array unpacking in ArrayDeclaration multiline Sniff (#3843)
Browse files Browse the repository at this point in the history
Ignore array unpacking when determining whether an array is a list- or dict-shaped.

Includes tests.

Fixes #3557
  • Loading branch information
edorian authored Jul 11, 2023
1 parent 653f390 commit 5ce46a8
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 9 deletions.
23 changes: 18 additions & 5 deletions src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,13 @@ public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $array
}

if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) {
$error = 'No key specified for array entry; first entry specifies key';
$phpcsFile->addError($error, $nextToken, 'NoKeySpecified');
return;
$nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($lastToken + 1), null, true);
// Allow for PHP 7.4+ array unpacking within an array declaration.
if ($tokens[$nextToken]['code'] !== T_ELLIPSIS) {
$error = 'No key specified for array entry; first entry specifies key';
$phpcsFile->addError($error, $nextToken, 'NoKeySpecified');
return;
}
}

if ($keyUsed === false) {
Expand Down Expand Up @@ -470,8 +474,17 @@ public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $array
true
);

$indices[] = ['value' => $valueContent];
$singleUsed = true;
$indices[] = ['value' => $valueContent];
$usesArrayUnpacking = $phpcsFile->findPrevious(
Tokens::$emptyTokens,
($nextToken - 2),
null,
true
);
if ($tokens[$usesArrayUnpacking]['code'] !== T_ELLIPSIS) {
// Don't decide if an array is key => value indexed or not when PHP 7.4+ array unpacking is used.
$singleUsed = true;
}
}//end if

$lastToken = $nextToken;
Expand Down
47 changes: 45 additions & 2 deletions src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -475,14 +475,57 @@ yield array(
static fn () : string => '',
);

$foo = [
$foo = array(
'foo' => match ($anything) {
'foo' => 'bar',
default => null,
},
];
);

// Intentional syntax error.
$a = array(
'a' =>
);

// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered.
$x = array(
...$a,
'foo' => 'bar',
);

$x = array(
'foo' => 'bar',
...$a,
);

$x = array(
'foo' => 'bar',
...$a,
'baz' => 'bar',
);

$x = array(
...$a,
'foo' => 'bar', // OK.
'bar', // NoKeySpecified Error (based on second entry).
);

$x = array(
...$a,
'bar', // OK.
'foo' => 'bar', // KeySpecified Error (based on second entry).
);

$x = array(
'foo' => 'bar',
...$a,
'baz' => 'bar',
'bar', // NoKeySpecified Error (based on first entry).
);

$x = array(
'bar',
...$a,
'bar',
'baz' => 'bar', // KeySpecified (based on first entry).
);
Original file line number Diff line number Diff line change
Expand Up @@ -511,14 +511,57 @@ yield array(
static fn () : string => '',
);

$foo = [
$foo = array(
'foo' => match ($anything) {
'foo' => 'bar',
default => null,
},
];
);

// Intentional syntax error.
$a = array(
'a' =>
);

// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered.
$x = array(
...$a,
'foo' => 'bar',
);

$x = array(
'foo' => 'bar',
...$a,
);

$x = array(
'foo' => 'bar',
...$a,
'baz' => 'bar',
);

$x = array(
...$a,
'foo' => 'bar', // OK.
'bar', // NoKeySpecified Error (based on second entry).
);

$x = array(
...$a,
'bar', // OK.
'foo' => 'bar', // KeySpecified Error (based on second entry).
);

$x = array(
'foo' => 'bar',
...$a,
'baz' => 'bar',
'bar', // NoKeySpecified Error (based on first entry).
);

$x = array(
'bar',
...$a,
'bar',
'baz' => 'bar', // KeySpecified (based on first entry).
);
50 changes: 50 additions & 0 deletions src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,57 @@ yield [
static fn () : string => '',
];

$foo = [
'foo' => match ($anything) {
'foo' => 'bar',
default => null,
},
];

// Intentional syntax error.
$a = [
'a' =>
];

// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered.
$x = [
...$a,
'foo' => 'bar',
];

$x = [
'foo' => 'bar',
...$a,
];

$x = [
'foo' => 'bar',
...$a,
'baz' => 'bar',
];

$x = [
...$a,
'foo' => 'bar', // OK.
'bar', // NoKeySpecified Error (based on second entry).
];

$x = [
...$a,
'bar', // OK.
'foo' => 'bar', // KeySpecified Error (based on second entry).
];

$x = [
'foo' => 'bar',
...$a,
'baz' => 'bar',
'bar', // NoKeySpecified Error (based on first entry).
];

$x = [
'bar',
...$a,
'bar',
'baz' => 'bar', // KeySpecified (based on first entry).
];
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,57 @@ yield [
static fn () : string => '',
];

$foo = [
'foo' => match ($anything) {
'foo' => 'bar',
default => null,
},
];

// Intentional syntax error.
$a = [
'a' =>
];

// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered.
$x = [
...$a,
'foo' => 'bar',
];

$x = [
'foo' => 'bar',
...$a,
];

$x = [
'foo' => 'bar',
...$a,
'baz' => 'bar',
];

$x = [
...$a,
'foo' => 'bar', // OK.
'bar', // NoKeySpecified Error (based on second entry).
];

$x = [
...$a,
'bar', // OK.
'foo' => 'bar', // KeySpecified Error (based on second entry).
];

$x = [
'foo' => 'bar',
...$a,
'baz' => 'bar',
'bar', // NoKeySpecified Error (based on first entry).
];

$x = [
'bar',
...$a,
'bar',
'baz' => 'bar', // KeySpecified (based on first entry).
];
8 changes: 8 additions & 0 deletions src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ public function getErrorList($testFile='')
467 => 1,
471 => 1,
472 => 1,
510 => 1,
516 => 1,
523 => 1,
530 => 1,
];
case 'ArrayDeclarationUnitTest.2.inc':
return [
Expand Down Expand Up @@ -210,6 +214,10 @@ public function getErrorList($testFile='')
456 => 1,
460 => 1,
461 => 1,
499 => 1,
505 => 1,
512 => 1,
519 => 1,
];
default:
return [];
Expand Down

0 comments on commit 5ce46a8

Please sign in to comment.