From b767c632be7d446a115030f358f868e4121fb40b Mon Sep 17 00:00:00 2001 From: jrfnl Date: Wed, 28 Mar 2018 06:27:17 +0200 Subject: [PATCH] :sparkles: PHP 7.3: New sniff to detect references in list constructs > Array destructuring now supports reference assignments using the syntax `[&$a, [$b, &$c]] = $d`. The same is also supported for `list()`. Refs: * https://wiki.php.net/rfc/list_reference_assignment * https://github.com/php/php-src/commit/6d4de4cf0582cf33848826ab78aae58077dc2dea * https://github.com/php/php-src/blob/9b89b09b24ffe29c2b6de24c3d9b21df4f2a9de0/UPGRADING#L58-L60 --- .../Lists/NewListReferenceAssignmentSniff.php | 66 ++++++++++ .../NewListReferenceAssignmentUnitTest.inc | 37 ++++++ .../NewListReferenceAssignmentUnitTest.php | 117 ++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php create mode 100644 PHPCompatibility/Tests/Sniffs/Lists/NewListReferenceAssignmentUnitTest.inc create mode 100644 PHPCompatibility/Tests/Sniffs/Lists/NewListReferenceAssignmentUnitTest.php diff --git a/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php b/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php new file mode 100644 index 000000000..825ea98e9 --- /dev/null +++ b/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php @@ -0,0 +1,66 @@ + + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniffs\Lists\NewKeyedListSniff; + +/** + * Detect reference assignments in array destructuring using (short) list. + * + * PHP version 7.3 + * + * @category PHP + * @package PHPCompatibility + * @author Juliette Reinders Folmer + */ +class NewListReferenceAssignmentSniff extends NewKeyedListSniff +{ + /** + * The token(s) within the list construct which is being targeted. + * + * @var array + */ + protected $targetsInList = array( + T_BITWISE_AND => T_BITWISE_AND, + ); + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.2') === false); + } + + /** + * Examine the contents of a list construct to determine whether an error needs to be thrown. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $opener The position of the list open token. + * @param int $closer The position of the list close token. + * + * @return void + */ + protected function examineList(\PHP_CodeSniffer_File $phpcsFile, $opener, $closer) + { + $start = $opener; + while (($start = $this->hasTargetInList($phpcsFile, $start, $closer)) !== false) { + $phpcsFile->addError( + 'Reference assignments within list constructs are not supported in PHP 7.2 or earlier.', + $start, + 'Found' + ); + } + } +} diff --git a/PHPCompatibility/Tests/Sniffs/Lists/NewListReferenceAssignmentUnitTest.inc b/PHPCompatibility/Tests/Sniffs/Lists/NewListReferenceAssignmentUnitTest.inc new file mode 100644 index 000000000..4f7b53f67 --- /dev/null +++ b/PHPCompatibility/Tests/Sniffs/Lists/NewListReferenceAssignmentUnitTest.inc @@ -0,0 +1,37 @@ + + */ +class NewListReferenceAssignmentUnitTest extends BaseSniffTest +{ + const TEST_FILE = 'Sniffs/Lists/NewListReferenceAssignmentUnitTest.inc'; + + /** + * testNewListReferenceAssignment + * + * @dataProvider dataNewListReferenceAssignment + * + * @param int $line Line number where the error should occur. + * + * @return void + */ + public function testNewListReferenceAssignment($line) + { + $file = $this->sniffFile(self::TEST_FILE, '7.2'); + $this->assertError($file, $line, 'Reference assignments within list constructs are not supported in PHP 7.2 or earlier.'); + } + + /** + * dataNewListReferenceAssignment + * + * @see testNewListReferenceAssignment() + * + * @return array + */ + public function dataNewListReferenceAssignment() + { + return array( + array(16), + array(17), + array(20), + array(24), + array(30), + array(33), // x2. + array(36), // x2. + array(37), + ); + } + + + /** + * testNoFalsePositives + * + * @dataProvider dataNoFalsePositives + * + * @param int $line Line number with a valid list assignment. + * + * @return void + */ + public function testNoFalsePositives($line) + { + $file = $this->sniffFile(self::TEST_FILE, '7.2'); + $this->assertNoViolation($file, $line); + } + + /** + * dataNoFalsePositives + * + * @see testNoFalsePositives() + * + * @return array + */ + public function dataNoFalsePositives() + { + return array( + array(6), + array(7), + array(9), + array(10), + array(19), + array(21), + array(22), + array(23), + array(25), + array(29), + array(31), + array(32), + ); + } + + + /** + * Verify no notices are thrown at all. + * + * @return void + */ + public function testNoViolationsInFileOnValidVersion() + { + $file = $this->sniffFile(self::TEST_FILE, '7.3'); + $this->assertNoViolation($file); + } + +}