diff --git a/tests/Core/File/IsReferenceTest.inc b/tests/Core/File/IsReferenceTest.inc index f71e2639d8..93c7acc677 100644 --- a/tests/Core/File/IsReferenceTest.inc +++ b/tests/Core/File/IsReferenceTest.inc @@ -1,6 +1,8 @@ getValue(); /* testAssignByReferenceE */ $collection = &collector(); +/* testAssignByReferenceF */ +$collection ??= &collector(); + +/* testShortListAssignByReferenceNoKeyA */ +[ + &$a, + /* testShortListAssignByReferenceNoKeyB */ + &$b, + /* testNestedShortListAssignByReferenceNoKey */ + [$c, &$d] +] = $array; + +/* testLongListAssignByReferenceNoKeyA */ +list($a, &$b, list(/* testLongListAssignByReferenceNoKeyB */ &$c, /* testLongListAssignByReferenceNoKeyC */ &$d)) = $array; + +[ + /* testNestedShortListAssignByReferenceWithKeyA */ + 'a' => [&$a, $b], + /* testNestedShortListAssignByReferenceWithKeyB */ + 'b' => [$c, &$d] +] = $array; + + +/* testLongListAssignByReferenceWithKeyA */ +list(get_key()[1] => &$e) = [1, 2, 3]; + /* testPassByReferenceA */ functionCall(&$something, $somethingElse); @@ -128,6 +156,9 @@ functionCall($something, &\SomeNS\SomeClass::$somethingElse); /* testPassByReferenceJ */ functionCall($something, &namespace\SomeClass::$somethingElse); +/* testPassByReferencePartiallyQualifiedName */ +functionCall($something, &Sub\Level\SomeClass::$somethingElse); + /* testNewByReferenceA */ $foobar2 = &new Foobar(); @@ -137,9 +168,27 @@ functionCall( $something , &new Foobar() ); /* testUseByReference */ $closure = function() use (&$var){}; +/* testUseByReferenceWithCommentFirstParam */ +$closure = function() use /*comment*/ (&$this->value){}; + +/* testUseByReferenceWithCommentSecondParam */ +$closure = function() use /*comment*/ ($varA, &$varB){}; + /* testArrowFunctionReturnByReference */ fn&($x) => $x; +$closure = function ( + /* testBitwiseAndExactParameterA */ + $a = MY_CONSTANT & parent::OTHER_CONSTANT, + /* testPassByReferenceExactParameterB */ + &$b, + /* testPassByReferenceExactParameterC */ + &...$c, + /* testBitwiseAndExactParameterD */ + $d = E_NOTICE & E_STRICT, +) {}; + +// Issue PHPCS#3049. /* testArrowFunctionPassByReferenceA */ $fn = fn(array &$one) => 1; @@ -148,3 +197,14 @@ $fn = fn($param, &...$moreParams) => 1; /* testClosureReturnByReference */ $closure = function &($param) use ($value) {}; + +/* testBitwiseAndArrowFunctionInDefault */ +$fn = fn( $one = E_NOTICE & E_STRICT) => 1; + +/* testTokenizerIssue1284PHPCSlt280A */ +if ($foo) {} +[&$a, /* testTokenizerIssue1284PHPCSlt280B */ &$b] = $c; + +/* testTokenizerIssue1284PHPCSlt280C */ +if ($foo) {} +[&$a, $b]; diff --git a/tests/Core/File/IsReferenceTest.php b/tests/Core/File/IsReferenceTest.php index 5372bf163c..929779d43b 100644 --- a/tests/Core/File/IsReferenceTest.php +++ b/tests/Core/File/IsReferenceTest.php @@ -20,6 +20,19 @@ class IsReferenceTest extends AbstractMethodUnitTest { + /** + * Test that false is returned when a non-"bitwise and" token is passed. + * + * @return void + */ + public function testNotBitwiseAndToken() + { + $target = $this->getTargetToken('/* testBitwiseAndA */', T_STRING); + $this->assertFalse(self::$phpcsFile->isReference($target)); + + }//end testNotBitwiseAndToken() + + /** * Test correctly identifying whether a "bitwise and" token is a reference or not. * @@ -44,206 +57,298 @@ public function testIsReference($identifier, $expected) * * @see testIsReference() * - * @return array + * @return array> */ public function dataIsReference() { return [ - [ - '/* testBitwiseAndA */', - false, + 'issue-1971-list-first-in-file' => [ + 'testMarker' => '/* testTokenizerIssue1971PHPCSlt330gt271A */', + 'expected' => true, + ], + 'issue-1971-list-first-in-file-nested' => [ + 'testMarker' => '/* testTokenizerIssue1971PHPCSlt330gt271B */', + 'expected' => true, + ], + 'bitwise and: param in function call' => [ + 'testMarker' => '/* testBitwiseAndA */', + 'expected' => false, + ], + 'bitwise and: in unkeyed short array, first value' => [ + 'testMarker' => '/* testBitwiseAndB */', + 'expected' => false, + ], + 'bitwise and: in unkeyed short array, last value' => [ + 'testMarker' => '/* testBitwiseAndC */', + 'expected' => false, + ], + 'bitwise and: in unkeyed long array, last value' => [ + 'testMarker' => '/* testBitwiseAndD */', + 'expected' => false, + ], + 'bitwise and: in keyed short array, last value' => [ + 'testMarker' => '/* testBitwiseAndE */', + 'expected' => false, + ], + 'bitwise and: in keyed long array, last value' => [ + 'testMarker' => '/* testBitwiseAndF */', + 'expected' => false, + ], + 'bitwise and: in assignment' => [ + 'testMarker' => '/* testBitwiseAndG */', + 'expected' => false, + ], + 'bitwise and: in param default value in function declaration' => [ + 'testMarker' => '/* testBitwiseAndH */', + 'expected' => false, + ], + 'bitwise and: in param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndI */', + 'expected' => false, + ], + 'reference: function declared to return by reference' => [ + 'testMarker' => '/* testFunctionReturnByReference */', + 'expected' => true, + ], + 'reference: only param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceA */', + 'expected' => true, + ], + 'reference: last param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceB */', + 'expected' => true, + ], + 'reference: only param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceC */', + 'expected' => true, + ], + 'reference: last param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceD */', + 'expected' => true, + ], + 'reference: typed param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceE */', + 'expected' => true, + ], + 'reference: typed param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceF */', + 'expected' => true, + ], + 'reference: variadic param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceG */', + 'expected' => true, + ], + 'reference: foreach value' => [ + 'testMarker' => '/* testForeachValueByReference */', + 'expected' => true, + ], + 'reference: foreach key' => [ + 'testMarker' => '/* testForeachKeyByReference */', + 'expected' => true, + ], + 'reference: keyed short array, first value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceA */', + 'expected' => true, + ], + 'reference: keyed short array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceB */', + 'expected' => true, + ], + 'reference: unkeyed short array, only value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceC */', + 'expected' => true, ], - [ - '/* testBitwiseAndB */', - false, + 'reference: unkeyed short array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceD */', + 'expected' => true, ], - [ - '/* testBitwiseAndC */', - false, + 'reference: keyed long array, first value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceE */', + 'expected' => true, ], - [ - '/* testBitwiseAndD */', - false, + 'reference: keyed long array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceF */', + 'expected' => true, ], - [ - '/* testBitwiseAndE */', - false, + 'reference: unkeyed long array, only value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceG */', + 'expected' => true, ], - [ - '/* testBitwiseAndF */', - false, + 'reference: unkeyed long array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceH */', + 'expected' => true, ], - [ - '/* testBitwiseAndG */', - false, + 'reference: variable, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceA */', + 'expected' => true, ], - [ - '/* testBitwiseAndH */', - false, + 'reference: variable, assign by reference, spacing variation' => [ + 'testMarker' => '/* testAssignByReferenceB */', + 'expected' => true, ], - [ - '/* testBitwiseAndI */', - false, + 'reference: variable, assign by reference, concat assign' => [ + 'testMarker' => '/* testAssignByReferenceC */', + 'expected' => true, ], - [ - '/* testFunctionReturnByReference */', - true, + 'reference: property, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceD */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceA */', - true, + 'reference: function return value, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceE */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceB */', - true, + 'reference: function return value, assign by reference, null coalesce assign' => [ + 'testMarker' => '/* testAssignByReferenceF */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceC */', - true, + 'reference: unkeyed short list, first var, assign by reference' => [ + 'testMarker' => '/* testShortListAssignByReferenceNoKeyA */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceD */', - true, + 'reference: unkeyed short list, second var, assign by reference' => [ + 'testMarker' => '/* testShortListAssignByReferenceNoKeyB */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceE */', - true, + 'reference: unkeyed short list, nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceNoKey */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceF */', - true, + 'reference: unkeyed long list, second var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyA */', + 'expected' => true, ], - [ - '/* testFunctionPassByReferenceG */', - true, + 'reference: unkeyed long list, first nested var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyB */', + 'expected' => true, ], - [ - '/* testForeachValueByReference */', - true, + 'reference: unkeyed long list, last nested var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyC */', + 'expected' => true, ], - [ - '/* testForeachKeyByReference */', - true, + 'reference: keyed short list, first nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceWithKeyA */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceA */', - true, + 'reference: keyed short list, last nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceWithKeyB */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceB */', - true, + 'reference: keyed long list, only var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceWithKeyA */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceC */', - true, + 'reference: first param in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceA */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceD */', - true, + 'reference: last param in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceB */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceE */', - true, + 'reference: property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceC */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceF */', - true, + 'reference: hierarchical self property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceD */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceG */', - true, + 'reference: hierarchical parent property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceE */', + 'expected' => true, ], - [ - '/* testArrayValueByReferenceH */', - true, + 'reference: hierarchical static property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceF */', + 'expected' => true, ], - [ - '/* testAssignByReferenceA */', - true, + 'reference: static property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceG */', + 'expected' => true, ], - [ - '/* testAssignByReferenceB */', - true, + 'reference: static property in function call, first with FQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceH */', + 'expected' => true, ], - [ - '/* testAssignByReferenceC */', - true, + 'reference: static property in function call, last with FQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceI */', + 'expected' => true, ], - [ - '/* testAssignByReferenceD */', - true, + 'reference: static property in function call, last with namespace relative name, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceJ */', + 'expected' => true, ], - [ - '/* testAssignByReferenceE */', - true, + 'reference: static property in function call, last with PQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferencePartiallyQualifiedName */', + 'expected' => true, ], - [ - '/* testPassByReferenceA */', - true, + 'reference: new by reference' => [ + 'testMarker' => '/* testNewByReferenceA */', + 'expected' => true, ], - [ - '/* testPassByReferenceB */', - true, + 'reference: new by reference as function call param' => [ + 'testMarker' => '/* testNewByReferenceB */', + 'expected' => true, ], - [ - '/* testPassByReferenceC */', - true, + 'reference: closure use by reference' => [ + 'testMarker' => '/* testUseByReference */', + 'expected' => true, ], - [ - '/* testPassByReferenceD */', - true, + 'reference: closure use by reference, first param, with comment' => [ + 'testMarker' => '/* testUseByReferenceWithCommentFirstParam */', + 'expected' => true, ], - [ - '/* testPassByReferenceE */', - true, + 'reference: closure use by reference, last param, with comment' => [ + 'testMarker' => '/* testUseByReferenceWithCommentSecondParam */', + 'expected' => true, ], - [ - '/* testPassByReferenceF */', - true, + 'reference: arrow fn declared to return by reference' => [ + 'testMarker' => '/* testArrowFunctionReturnByReference */', + 'expected' => true, ], - [ - '/* testPassByReferenceG */', - true, + 'bitwise and: first param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndExactParameterA */', + 'expected' => false, ], - [ - '/* testPassByReferenceH */', - true, + 'reference: param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceExactParameterB */', + 'expected' => true, ], - [ - '/* testPassByReferenceI */', - true, + 'reference: variadic param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceExactParameterC */', + 'expected' => true, ], - [ - '/* testPassByReferenceJ */', - true, + 'bitwise and: last param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndExactParameterD */', + 'expected' => false, ], - [ - '/* testNewByReferenceA */', - true, + 'reference: typed param in arrow fn declaration, pass by reference' => [ + 'testMarker' => '/* testArrowFunctionPassByReferenceA */', + 'expected' => true, ], - [ - '/* testNewByReferenceB */', - true, + 'reference: variadic param in arrow fn declaration, pass by reference' => [ + 'testMarker' => '/* testArrowFunctionPassByReferenceB */', + 'expected' => true, ], - [ - '/* testUseByReference */', - true, + 'reference: closure declared to return by reference' => [ + 'testMarker' => '/* testClosureReturnByReference */', + 'expected' => true, ], - [ - '/* testArrowFunctionReturnByReference */', - true, + 'bitwise and: param default value in arrow fn declaration' => [ + 'testMarker' => '/* testBitwiseAndArrowFunctionInDefault */', + 'expected' => false, ], - [ - '/* testArrowFunctionPassByReferenceA */', - true, + 'issue-1284-short-list-directly-after-close-curly-control-structure' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280A */', + 'expected' => true, ], - [ - '/* testArrowFunctionPassByReferenceB */', - true, + 'issue-1284-short-list-directly-after-close-curly-control-structure-second-item' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280B */', + 'expected' => true, ], - [ - '/* testClosureReturnByReference */', - true, + 'issue-1284-short-array-directly-after-close-curly-control-structure' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280C */', + 'expected' => true, ], ];