* @author Juliette Reinders Folmer * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @copyright 2019-2024 PHPCSStandards Contributors * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ namespace PHP_CodeSniffer\Tests\Core\File; use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; /** * Tests for the \PHP_CodeSniffer\Files\File::getMethodParameters method. * * @covers \PHP_CodeSniffer\Files\File::getMethodParameters */ final class GetMethodParametersTest extends AbstractMethodUnitTest { /** * Test receiving an expected exception when a non function/use token is passed. * * @param string $commentString The comment which preceeds the test. * @param int|string|array $targetTokenType The token type to search for after $commentString. * * @dataProvider dataUnexpectedTokenException * * @return void */ public function testUnexpectedTokenException($commentString, $targetTokenType) { $this->expectRunTimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_USE or T_FN'); $target = $this->getTargetToken($commentString, $targetTokenType); self::$phpcsFile->getMethodParameters($target); }//end testUnexpectedTokenException() /** * Data Provider. * * @see testUnexpectedTokenException() For the array format. * * @return array>> */ public static function dataUnexpectedTokenException() { return [ 'interface' => [ 'commentString' => '/* testNotAFunction */', 'targetTokenType' => T_INTERFACE, ], 'function-call-fn-phpcs-3.5.3-3.5.4' => [ 'commentString' => '/* testFunctionCallFnPHPCS353-354 */', 'targetTokenType' => [ T_FN, T_STRING, ], ], 'fn-live-coding' => [ 'commentString' => '/* testArrowFunctionLiveCoding */', 'targetTokenType' => [ T_FN, T_STRING, ], ], ]; }//end dataUnexpectedTokenException() /** * Test receiving an expected exception when a non-closure use token is passed. * * @param string $identifier The comment which preceeds the test. * * @dataProvider dataInvalidUse * * @return void */ public function testInvalidUse($identifier) { $this->expectRunTimeException('$stackPtr was not a valid T_USE'); $use = $this->getTargetToken($identifier, [T_USE]); self::$phpcsFile->getMethodParameters($use); }//end testInvalidUse() /** * Data Provider. * * @see testInvalidUse() For the array format. * * @return array> */ public static function dataInvalidUse() { return [ 'ImportUse' => ['/* testImportUse */'], 'ImportGroupUse' => ['/* testImportGroupUse */'], 'TraitUse' => ['/* testTraitUse */'], ]; }//end dataInvalidUse() /** * Test receiving an empty array when there are no parameters. * * @param string $commentString The comment which preceeds the test. * @param int|string|array $targetTokenType Optional. The token type to search for after $commentString. * Defaults to the function/closure/arrow tokens. * * @dataProvider dataNoParams * * @return void */ public function testNoParams($commentString, $targetTokenType=[T_FUNCTION, T_CLOSURE, T_FN]) { $target = $this->getTargetToken($commentString, $targetTokenType); $result = self::$phpcsFile->getMethodParameters($target); $this->assertSame([], $result); }//end testNoParams() /** * Data Provider. * * @see testNoParams() For the array format. * * @return array>> */ public static function dataNoParams() { return [ 'FunctionNoParams' => [ 'commentString' => '/* testFunctionNoParams */', ], 'ClosureNoParams' => [ 'commentString' => '/* testClosureNoParams */', ], 'ClosureUseNoParams' => [ 'commentString' => '/* testClosureUseNoParams */', 'targetTokenType' => T_USE, ], ]; }//end dataNoParams() /** * Verify pass-by-reference parsing. * * @return void */ public function testPassByReference() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 5, 'name' => '$var', 'content' => '&$var', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 4, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPassByReference() /** * Verify array hint parsing. * * @return void */ public function testArrayHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var', 'content' => 'array $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'array', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrayHint() /** * Verify variable. * * @return void */ public function testVariable() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$var', 'content' => '$var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testVariable() /** * Verify default value parsing with a single function param. * * @return void */ public function testSingleDefaultValue() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$var1', 'content' => '$var1=self::CONSTANT', 'default' => 'self::CONSTANT', 'default_token' => 6, 'default_equal_token' => 5, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testSingleDefaultValue() /** * Verify default value parsing. * * @return void */ public function testDefaultValues() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$var1', 'content' => '$var1=1', 'default' => '1', 'default_token' => 6, 'default_equal_token' => 5, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 7, ]; $expected[1] = [ 'token' => 9, 'name' => '$var2', 'content' => "\$var2='value'", 'default' => "'value'", 'default_token' => 11, 'default_equal_token' => 10, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testDefaultValues() /** * Verify type hint parsing. * * @return void */ public function testTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var1', 'content' => 'foo $var1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'foo', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => 7, ]; $expected[1] = [ 'token' => 11, 'name' => '$var2', 'content' => 'bar $var2', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'bar', 'type_hint_token' => 9, 'type_hint_end_token' => 9, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testTypeHint() /** * Verify self type hint parsing. * * @return void */ public function testSelfTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var', 'content' => 'self $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'self', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testSelfTypeHint() /** * Verify nullable type hint parsing. * * @return void */ public function testNullableTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$var1', 'content' => '?int $var1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 5, 'type_hint_end_token' => 5, 'nullable_type' => true, 'comma_token' => 8, ]; $expected[1] = [ 'token' => 14, 'name' => '$var2', 'content' => '?\bar $var2', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?\bar', 'type_hint_token' => 11, 'type_hint_end_token' => 12, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testNullableTypeHint() /** * Verify "bitwise and" in default value !== pass-by-reference. * * @return void */ public function testBitwiseAndConstantExpressionDefaultValue() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$a', 'content' => '$a = 10 & 20', 'default' => '10 & 20', 'default_token' => 8, 'default_equal_token' => 6, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testBitwiseAndConstantExpressionDefaultValue() /** * Verify that arrow functions are supported. * * @return void */ public function testArrowFunction() { // Offsets are relative to the T_FN token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$a', 'content' => 'int $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'int', 'type_hint_token' => 2, 'type_hint_end_token' => 2, 'nullable_type' => false, 'comma_token' => 5, ]; $expected[1] = [ 'token' => 8, 'name' => '$b', 'content' => '...$b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 7, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunction() /** * Verify that arrow functions are supported. * * @return void */ public function testArrowFunctionReturnByRef() { // Offsets are relative to the T_FN token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$a', 'content' => '?string $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?string', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunctionReturnByRef() /** * Verify default value parsing with array values. * * @return void */ public function testArrayDefaultValues() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$var1', 'content' => '$var1 = []', 'default' => '[]', 'default_token' => 8, 'default_equal_token' => 6, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 10, ]; $expected[1] = [ 'token' => 12, 'name' => '$var2', 'content' => '$var2 = array(1, 2, 3)', 'default' => 'array(1, 2, 3)', 'default_token' => 16, 'default_equal_token' => 14, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrayDefaultValues() /** * Verify having a T_STRING constant as a default value for the second parameter. * * @return void */ public function testConstantDefaultValueSecondParam() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$var1', 'content' => '$var1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 5, ]; $expected[1] = [ 'token' => 7, 'name' => '$var2', 'content' => '$var2 = M_PI', 'default' => 'M_PI', 'default_token' => 11, 'default_equal_token' => 9, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testConstantDefaultValueSecondParam() /** * Verify distinquishing between a nullable type and a ternary within a default expression. * * @return void */ public function testScalarTernaryExpressionInDefault() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 5, 'name' => '$a', 'content' => '$a = FOO ? \'bar\' : 10', 'default' => 'FOO ? \'bar\' : 10', 'default_token' => 9, 'default_equal_token' => 7, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 18, ]; $expected[1] = [ 'token' => 24, 'name' => '$b', 'content' => '? bool $b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?bool', 'type_hint_token' => 22, 'type_hint_end_token' => 22, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testScalarTernaryExpressionInDefault() /** * Verify a variadic parameter being recognized correctly. * * @return void */ public function testVariadicFunction() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$a', 'content' => 'int ... $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 7, 'type_hint' => 'int', 'type_hint_token' => 5, 'type_hint_end_token' => 5, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testVariadicFunction() /** * Verify a variadic parameter passed by reference being recognized correctly. * * @return void */ public function testVariadicByRefFunction() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$a', 'content' => '&...$a', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 5, 'variable_length' => true, 'variadic_token' => 6, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testVariadicByRefFunction() /** * Verify handling of a variadic parameter with a class based type declaration. * * @return void */ public function testVariadicFunctionClassType() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$unit', 'content' => '$unit', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 5, ]; $expected[1] = [ 'token' => 10, 'name' => '$intervals', 'content' => 'DateInterval ...$intervals', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 9, 'type_hint' => 'DateInterval', 'type_hint_token' => 7, 'type_hint_end_token' => 7, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testVariadicFunctionClassType() /** * Verify distinquishing between a nullable type and a ternary within a default expression. * * @return void */ public function testNameSpacedTypeDeclaration() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 12, 'name' => '$a', 'content' => '\Package\Sub\ClassName $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '\Package\Sub\ClassName', 'type_hint_token' => 5, 'type_hint_end_token' => 10, 'nullable_type' => false, 'comma_token' => 13, ]; $expected[1] = [ 'token' => 20, 'name' => '$b', 'content' => '?Sub\AnotherClass $b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?Sub\AnotherClass', 'type_hint_token' => 16, 'type_hint_end_token' => 18, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testNameSpacedTypeDeclaration() /** * Verify correctly recognizing all type declarations supported by PHP. * * @return void */ public function testWithAllTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$a', 'content' => '?ClassName $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?ClassName', 'type_hint_token' => 7, 'type_hint_end_token' => 7, 'nullable_type' => true, 'comma_token' => 10, ]; $expected[1] = [ 'token' => 15, 'name' => '$b', 'content' => 'self $b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'self', 'type_hint_token' => 13, 'type_hint_end_token' => 13, 'nullable_type' => false, 'comma_token' => 16, ]; $expected[2] = [ 'token' => 21, 'name' => '$c', 'content' => 'parent $c', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'parent', 'type_hint_token' => 19, 'type_hint_end_token' => 19, 'nullable_type' => false, 'comma_token' => 22, ]; $expected[3] = [ 'token' => 27, 'name' => '$d', 'content' => 'object $d', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'object', 'type_hint_token' => 25, 'type_hint_end_token' => 25, 'nullable_type' => false, 'comma_token' => 28, ]; $expected[4] = [ 'token' => 34, 'name' => '$e', 'content' => '?int $e', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 32, 'type_hint_end_token' => 32, 'nullable_type' => true, 'comma_token' => 35, ]; $expected[5] = [ 'token' => 41, 'name' => '$f', 'content' => 'string &$f', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 40, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'string', 'type_hint_token' => 38, 'type_hint_end_token' => 38, 'nullable_type' => false, 'comma_token' => 42, ]; $expected[6] = [ 'token' => 47, 'name' => '$g', 'content' => 'iterable $g', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'iterable', 'type_hint_token' => 45, 'type_hint_end_token' => 45, 'nullable_type' => false, 'comma_token' => 48, ]; $expected[7] = [ 'token' => 53, 'name' => '$h', 'content' => 'bool $h = true', 'default' => 'true', 'default_token' => 57, 'default_equal_token' => 55, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'bool', 'type_hint_token' => 51, 'type_hint_end_token' => 51, 'nullable_type' => false, 'comma_token' => 58, ]; $expected[8] = [ 'token' => 63, 'name' => '$i', 'content' => 'callable $i = \'is_null\'', 'default' => "'is_null'", 'default_token' => 67, 'default_equal_token' => 65, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'callable', 'type_hint_token' => 61, 'type_hint_end_token' => 61, 'nullable_type' => false, 'comma_token' => 68, ]; $expected[9] = [ 'token' => 73, 'name' => '$j', 'content' => 'float $j = 1.1', 'default' => '1.1', 'default_token' => 77, 'default_equal_token' => 75, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'float', 'type_hint_token' => 71, 'type_hint_end_token' => 71, 'nullable_type' => false, 'comma_token' => 78, ]; $expected[10] = [ 'token' => 84, 'name' => '$k', 'content' => 'array ...$k', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 83, 'type_hint' => 'array', 'type_hint_token' => 81, 'type_hint_end_token' => 81, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testWithAllTypes() /** * Verify correctly recognizing all type declarations supported by PHP when used with an arrow function. * * @return void */ public function testArrowFunctionWithAllTypes() { // Offsets are relative to the T_FN token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$a', 'content' => '?ClassName $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?ClassName', 'type_hint_token' => 5, 'type_hint_end_token' => 5, 'nullable_type' => true, 'comma_token' => 8, ]; $expected[1] = [ 'token' => 13, 'name' => '$b', 'content' => 'self $b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'self', 'type_hint_token' => 11, 'type_hint_end_token' => 11, 'nullable_type' => false, 'comma_token' => 14, ]; $expected[2] = [ 'token' => 19, 'name' => '$c', 'content' => 'parent $c', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'parent', 'type_hint_token' => 17, 'type_hint_end_token' => 17, 'nullable_type' => false, 'comma_token' => 20, ]; $expected[3] = [ 'token' => 25, 'name' => '$d', 'content' => 'object $d', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'object', 'type_hint_token' => 23, 'type_hint_end_token' => 23, 'nullable_type' => false, 'comma_token' => 26, ]; $expected[4] = [ 'token' => 32, 'name' => '$e', 'content' => '?int $e', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 30, 'type_hint_end_token' => 30, 'nullable_type' => true, 'comma_token' => 33, ]; $expected[5] = [ 'token' => 39, 'name' => '$f', 'content' => 'string &$f', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 38, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'string', 'type_hint_token' => 36, 'type_hint_end_token' => 36, 'nullable_type' => false, 'comma_token' => 40, ]; $expected[6] = [ 'token' => 45, 'name' => '$g', 'content' => 'iterable $g', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'iterable', 'type_hint_token' => 43, 'type_hint_end_token' => 43, 'nullable_type' => false, 'comma_token' => 46, ]; $expected[7] = [ 'token' => 51, 'name' => '$h', 'content' => 'bool $h = true', 'default' => 'true', 'default_token' => 55, 'default_equal_token' => 53, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'bool', 'type_hint_token' => 49, 'type_hint_end_token' => 49, 'nullable_type' => false, 'comma_token' => 56, ]; $expected[8] = [ 'token' => 61, 'name' => '$i', 'content' => 'callable $i = \'is_null\'', 'default' => "'is_null'", 'default_token' => 65, 'default_equal_token' => 63, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'callable', 'type_hint_token' => 59, 'type_hint_end_token' => 59, 'nullable_type' => false, 'comma_token' => 66, ]; $expected[9] = [ 'token' => 71, 'name' => '$j', 'content' => 'float $j = 1.1', 'default' => '1.1', 'default_token' => 75, 'default_equal_token' => 73, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'float', 'type_hint_token' => 69, 'type_hint_end_token' => 69, 'nullable_type' => false, 'comma_token' => 76, ]; $expected[10] = [ 'token' => 82, 'name' => '$k', 'content' => 'array ...$k', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 81, 'type_hint' => 'array', 'type_hint_token' => 79, 'type_hint_end_token' => 79, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunctionWithAllTypes() /** * Verify handling of a declaration interlaced with whitespace and comments. * * @return void */ public function testMessyDeclaration() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 25, 'name' => '$a', 'content' => '// comment ?\MyNS /* comment */ \ SubCat // phpcs:ignore Standard.Cat.Sniff -- for reasons. \ MyClass $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?\MyNS\SubCat\MyClass', 'type_hint_token' => 9, 'type_hint_end_token' => 23, 'nullable_type' => true, 'comma_token' => 26, ]; $expected[1] = [ 'token' => 29, 'name' => '$b', 'content' => "\$b /* test */ = /* test */ 'default' /* test*/", 'default' => "'default' /* test*/", 'default_token' => 37, 'default_equal_token' => 33, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 40, ]; $expected[2] = [ 'token' => 62, 'name' => '$c', 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- For reasons. ? /*comment*/ bool // phpcs:disable Stnd.Cat.Sniff -- For reasons. & /*test*/ ... /* phpcs:ignore */ $c', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 54, 'variable_length' => true, 'variadic_token' => 58, 'type_hint' => '?bool', 'type_hint_token' => 50, 'type_hint_end_token' => 50, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testMessyDeclaration() /** * Verify recognition of PHP8 mixed type declaration. * * @return void */ public function testPHP8MixedTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$var1', 'content' => 'mixed &...$var1', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 6, 'variable_length' => true, 'variadic_token' => 7, 'type_hint' => 'mixed', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8MixedTypeHint() /** * Verify recognition of PHP8 mixed type declaration with nullability. * * @return void */ public function testPHP8MixedTypeHintNullable() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$var1', 'content' => '?Mixed $var1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?Mixed', 'type_hint_token' => 5, 'type_hint_end_token' => 5, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8MixedTypeHintNullable() /** * Verify recognition of type declarations using the namespace operator. * * @return void */ public function testNamespaceOperatorTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$var1', 'content' => '?namespace\Name $var1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?namespace\Name', 'type_hint_token' => 5, 'type_hint_end_token' => 7, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testNamespaceOperatorTypeHint() /** * Verify recognition of PHP8 union type declaration. * * @return void */ public function testPHP8UnionTypesSimple() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$number', 'content' => 'int|float $number', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'int|float', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => 9, ]; $expected[1] = [ 'token' => 17, 'name' => '$obj', 'content' => 'self|parent &...$obj', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 15, 'variable_length' => true, 'variadic_token' => 16, 'type_hint' => 'self|parent', 'type_hint_token' => 11, 'type_hint_end_token' => 13, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesSimple() /** * Verify recognition of PHP8 union type declaration when the variable has either a spread operator or a reference. * * @return void */ public function testPHP8UnionTypesWithSpreadOperatorAndReference() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$paramA', 'content' => 'float|null &$paramA', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 8, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'float|null', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => 10, ]; $expected[1] = [ 'token' => 17, 'name' => '$paramB', 'content' => 'string|int ...$paramB', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 16, 'type_hint' => 'string|int', 'type_hint_token' => 12, 'type_hint_end_token' => 14, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesWithSpreadOperatorAndReference() /** * Verify recognition of PHP8 union type declaration with a bitwise or in the default value. * * @return void */ public function testPHP8UnionTypesSimpleWithBitwiseOrInDefault() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var', 'content' => 'int|float $var = CONSTANT_A | CONSTANT_B', 'default' => 'CONSTANT_A | CONSTANT_B', 'default_token' => 10, 'default_equal_token' => 8, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'int|float', 'type_hint_token' => 2, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesSimpleWithBitwiseOrInDefault() /** * Verify recognition of PHP8 union type declaration with two classes. * * @return void */ public function testPHP8UnionTypesTwoClasses() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 11, 'name' => '$var', 'content' => 'MyClassA|\Package\MyClassB $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'MyClassA|\Package\MyClassB', 'type_hint_token' => 4, 'type_hint_end_token' => 9, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesTwoClasses() /** * Verify recognition of PHP8 union type declaration with all base types. * * @return void */ public function testPHP8UnionTypesAllBaseTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 20, 'name' => '$var', 'content' => 'array|bool|callable|int|float|null|object|string $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'array|bool|callable|int|float|null|object|string', 'type_hint_token' => 4, 'type_hint_end_token' => 18, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesAllBaseTypes() /** * Verify recognition of PHP8 union type declaration with all pseudo types. * * Note: "Resource" is not a type, but seen as a class name. * * @return void */ public function testPHP8UnionTypesAllPseudoTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 16, 'name' => '$var', 'content' => 'false|mixed|self|parent|iterable|Resource $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'false|mixed|self|parent|iterable|Resource', 'type_hint_token' => 4, 'type_hint_end_token' => 14, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesAllPseudoTypes() /** * Verify recognition of PHP8 union type declaration with (illegal) nullability. * * @return void */ public function testPHP8UnionTypesNullable() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$number', 'content' => '?int|float $number', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int|float', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesNullable() /** * Verify recognition of PHP8 type declaration with (illegal) single type null. * * @return void */ public function testPHP8PseudoTypeNull() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var', 'content' => 'null $var = null', 'default' => 'null', 'default_token' => 10, 'default_equal_token' => 8, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'null', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8PseudoTypeNull() /** * Verify recognition of PHP8 type declaration with (illegal) single type false. * * @return void */ public function testPHP8PseudoTypeFalse() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$var', 'content' => 'false $var = false', 'default' => 'false', 'default_token' => 10, 'default_equal_token' => 8, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'false', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8PseudoTypeFalse() /** * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. * * @return void */ public function testPHP8PseudoTypeFalseAndBool() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$var', 'content' => 'bool|false $var = false', 'default' => 'false', 'default_token' => 12, 'default_equal_token' => 10, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'bool|false', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8PseudoTypeFalseAndBool() /** * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. * * @return void */ public function testPHP8ObjectAndClass() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$var', 'content' => 'object|ClassName $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'object|ClassName', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ObjectAndClass() /** * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. * * @return void */ public function testPHP8PseudoTypeIterableAndArray() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 10, 'name' => '$var', 'content' => 'iterable|array|Traversable $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'iterable|array|Traversable', 'type_hint_token' => 4, 'type_hint_end_token' => 8, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8PseudoTypeIterableAndArray() /** * Verify recognition of PHP8 type declaration with (illegal) duplicate types. * * @return void */ public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 17, 'name' => '$var', 'content' => 'int | string /*comment*/ | INT $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'int|string|INT', 'type_hint_token' => 5, 'type_hint_end_token' => 15, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() /** * Verify recognition of PHP8 constructor property promotion without type declaration, with defaults. * * @return void */ public function testPHP8ConstructorPropertyPromotionNoTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$x', 'content' => 'public $x = 0.0', 'default' => '0.0', 'default_token' => 12, 'default_equal_token' => 10, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'public', 'visibility_token' => 6, 'property_readonly' => false, 'comma_token' => 13, ]; $expected[1] = [ 'token' => 18, 'name' => '$y', 'content' => 'protected $y = \'\'', 'default' => "''", 'default_token' => 22, 'default_equal_token' => 20, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'protected', 'visibility_token' => 16, 'property_readonly' => false, 'comma_token' => 23, ]; $expected[2] = [ 'token' => 28, 'name' => '$z', 'content' => 'private $z = null', 'default' => 'null', 'default_token' => 32, 'default_equal_token' => 30, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 26, 'property_readonly' => false, 'comma_token' => 33, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ConstructorPropertyPromotionNoTypes() /** * Verify recognition of PHP8 constructor property promotion with type declarations. * * @return void */ public function testPHP8ConstructorPropertyPromotionWithTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 10, 'name' => '$x', 'content' => 'protected float|int $x', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'float|int', 'type_hint_token' => 6, 'type_hint_end_token' => 8, 'nullable_type' => false, 'property_visibility' => 'protected', 'visibility_token' => 4, 'property_readonly' => false, 'comma_token' => 11, ]; $expected[1] = [ 'token' => 19, 'name' => '$y', 'content' => 'public ?string &$y = \'test\'', 'default' => "'test'", 'default_token' => 23, 'default_equal_token' => 21, 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 18, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?string', 'type_hint_token' => 16, 'type_hint_end_token' => 16, 'nullable_type' => true, 'property_visibility' => 'public', 'visibility_token' => 13, 'property_readonly' => false, 'comma_token' => 24, ]; $expected[2] = [ 'token' => 30, 'name' => '$z', 'content' => 'private mixed $z', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'mixed', 'type_hint_token' => 28, 'type_hint_end_token' => 28, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 26, 'property_readonly' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ConstructorPropertyPromotionWithTypes() /** * Verify recognition of PHP8 constructor with both property promotion as well as normal parameters. * * @return void */ public function testPHP8ConstructorPropertyPromotionAndNormalParam() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$promotedProp', 'content' => 'public int $promotedProp', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'int', 'type_hint_token' => 6, 'type_hint_end_token' => 6, 'nullable_type' => false, 'property_visibility' => 'public', 'visibility_token' => 4, 'property_readonly' => false, 'comma_token' => 9, ]; $expected[1] = [ 'token' => 14, 'name' => '$normalArg', 'content' => '?int $normalArg', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 12, 'type_hint_end_token' => 12, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ConstructorPropertyPromotionAndNormalParam() /** * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword. * * @return void */ public function testPHP81ConstructorPropertyPromotionWithReadOnly() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 11, 'name' => '$promotedProp', 'content' => 'public readonly ?int $promotedProp', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 9, 'type_hint_end_token' => 9, 'nullable_type' => true, 'property_visibility' => 'public', 'visibility_token' => 4, 'property_readonly' => true, 'readonly_token' => 6, 'comma_token' => 12, ]; $expected[1] = [ 'token' => 23, 'name' => '$promotedToo', 'content' => 'ReadOnly private string|bool &$promotedToo', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 22, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'string|bool', 'type_hint_token' => 18, 'type_hint_end_token' => 20, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 16, 'property_readonly' => true, 'readonly_token' => 14, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81ConstructorPropertyPromotionWithReadOnly() /** * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword * without a property type. * * @return void */ public function testPHP81ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$promotedProp', 'content' => 'public readonly $promotedProp', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'public', 'visibility_token' => 4, 'property_readonly' => true, 'readonly_token' => 6, 'comma_token' => 9, ]; $expected[1] = [ 'token' => 16, 'name' => '$promotedToo', 'content' => 'ReadOnly private &$promotedToo', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 15, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 13, 'property_readonly' => true, 'readonly_token' => 11, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration() /** * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly * keyword without explicit visibility. * * @return void */ public function testPHP81ConstructorPropertyPromotionWithOnlyReadOnly() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 10, 'name' => '$promotedProp', 'content' => 'readonly Foo&Bar $promotedProp', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'Foo&Bar', 'type_hint_token' => 6, 'type_hint_end_token' => 8, 'nullable_type' => false, 'property_visibility' => 'public', 'visibility_token' => false, 'property_readonly' => true, 'readonly_token' => 4, 'comma_token' => 11, ]; $expected[1] = [ 'token' => 18, 'name' => '$promotedToo', 'content' => 'readonly ?bool $promotedToo', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?bool', 'type_hint_token' => 16, 'type_hint_end_token' => 16, 'nullable_type' => true, 'property_visibility' => 'public', 'visibility_token' => false, 'property_readonly' => true, 'readonly_token' => 13, 'comma_token' => 19, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81ConstructorPropertyPromotionWithOnlyReadOnly() /** * Verify behaviour when a non-constructor function uses PHP 8 property promotion syntax. * * @return void */ public function testPHP8ConstructorPropertyPromotionGlobalFunction() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$x', 'content' => 'private $x', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 4, 'property_readonly' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ConstructorPropertyPromotionGlobalFunction() /** * Verify behaviour when an abstract constructor uses PHP 8 property promotion syntax. * * @return void */ public function testPHP8ConstructorPropertyPromotionAbstractMethod() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$y', 'content' => 'public callable $y', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'callable', 'type_hint_token' => 6, 'type_hint_end_token' => 6, 'nullable_type' => false, 'property_visibility' => 'public', 'visibility_token' => 4, 'property_readonly' => false, 'comma_token' => 9, ]; $expected[1] = [ 'token' => 14, 'name' => '$x', 'content' => 'private ...$x', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 13, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 11, 'property_readonly' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8ConstructorPropertyPromotionAbstractMethod() /** * Verify and document behaviour when there are comments within a parameter declaration. * * @return void */ public function testCommentsInParameter() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 19, 'name' => '$param', 'content' => '// Leading comment. ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ \'default value\' . /*-*/ \'second part\' // Trailing comment.', 'default' => '\'default value\' . /*-*/ \'second part\' // Trailing comment.', 'default_token' => 27, 'default_equal_token' => 23, 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 13, 'variable_length' => true, 'variadic_token' => 16, 'type_hint' => '?MyClass', 'type_hint_token' => 9, 'type_hint_end_token' => 9, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testCommentsInParameter() /** * Verify behaviour when parameters have attributes attached. * * @return void */ public function testParameterAttributesInFunctionDeclaration() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 17, 'name' => '$constructorPropPromTypedParamSingleAttribute', 'content' => '#[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute', 'has_attributes' => true, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'string', 'type_hint_token' => 15, 'type_hint_end_token' => 15, 'nullable_type' => false, 'property_visibility' => 'private', 'visibility_token' => 13, 'property_readonly' => false, 'comma_token' => 18, ]; $expected[1] = [ 'token' => 39, 'name' => '$typedParamSingleAttribute', 'content' => '#[MyAttr([1, 2])] Type|false $typedParamSingleAttribute', 'has_attributes' => true, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'Type|false', 'type_hint_token' => 34, 'type_hint_end_token' => 36, 'nullable_type' => false, 'comma_token' => 40, ]; $expected[2] = [ 'token' => 59, 'name' => '$nullableTypedParamMultiAttribute', 'content' => '#[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute', 'has_attributes' => true, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 57, 'type_hint_end_token' => 57, 'nullable_type' => true, 'comma_token' => 60, ]; $expected[3] = [ 'token' => 74, 'name' => '$nonTypedParamTwoAttributes', 'content' => '#[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes', 'has_attributes' => true, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 75, ]; $expected[4] = [ 'token' => 95, 'name' => '$otherParam', 'content' => '#[MyAttribute(array("key" => "value"))] &...$otherParam', 'has_attributes' => true, 'pass_by_reference' => true, 'reference_token' => 93, 'variable_length' => true, 'variadic_token' => 94, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 96, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testParameterAttributesInFunctionDeclaration() /** * Verify recognition of PHP8.1 intersection type declaration. * * @return void */ public function testPHP8IntersectionTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$obj1', 'content' => 'Foo&Bar $obj1', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'Foo&Bar', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => 9, ]; $expected[1] = [ 'token' => 15, 'name' => '$obj2', 'content' => 'Boo&Bar $obj2', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'Boo&Bar', 'type_hint_token' => 11, 'type_hint_end_token' => 13, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8IntersectionTypes() /** * Verify recognition of PHP8.1 intersection type declaration when the variable * has either a spread operator or a reference. * * @return void */ public function testPHP81IntersectionTypesWithSpreadOperatorAndReference() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$paramA', 'content' => 'Boo&Bar &$paramA', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 8, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'Boo&Bar', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => 10, ]; $expected[1] = [ 'token' => 17, 'name' => '$paramB', 'content' => 'Foo&Bar ...$paramB', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 16, 'type_hint' => 'Foo&Bar', 'type_hint_token' => 12, 'type_hint_end_token' => 14, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81IntersectionTypesWithSpreadOperatorAndReference() /** * Verify recognition of PHP8.1 intersection type declaration with more types. * * @return void */ public function testPHP81MoreIntersectionTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 16, 'name' => '$var', 'content' => 'MyClassA&\Package\MyClassB&\Package\MyClassC $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', 'type_hint_token' => 4, 'type_hint_end_token' => 14, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81MoreIntersectionTypes() /** * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. * * @return void */ public function testPHP81IllegalIntersectionTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$numeric_string', 'content' => 'string&int $numeric_string', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'string&int', 'type_hint_token' => 3, 'type_hint_end_token' => 5, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81IllegalIntersectionTypes() /** * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. * * @return void */ public function testPHP81NullableIntersectionTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$object', 'content' => '?Foo&Bar $object', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?Foo&Bar', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81NullableIntersectionTypes() /** * Verify recognition of PHP 8.2 stand-alone `true` type. * * @return void */ public function testPHP82PseudoTypeTrue() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 7, 'name' => '$var', 'content' => '?true $var = true', 'default' => 'true', 'default_token' => 11, 'default_equal_token' => 9, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?true', 'type_hint_token' => 5, 'type_hint_end_token' => 5, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82PseudoTypeTrue() /** * Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true. * * @return void */ public function testPHP82PseudoTypeFalseAndTrue() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$var', 'content' => 'true|false $var = true', 'default' => 'true', 'default_token' => 12, 'default_equal_token' => 10, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'true|false', 'type_hint_token' => 4, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82PseudoTypeFalseAndTrue() /** * Verify behaviour when the default value uses the "new" keyword, as is allowed per PHP 8.1. * * @return void */ public function testPHP81NewInInitializers() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 8, 'name' => '$new', 'content' => 'TypeA $new = new TypeA(self::CONST_VALUE)', 'default' => 'new TypeA(self::CONST_VALUE)', 'default_token' => 12, 'default_equal_token' => 10, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'TypeA', 'type_hint_token' => 6, 'type_hint_end_token' => 6, 'nullable_type' => false, 'comma_token' => 20, ]; $expected[1] = [ 'token' => 28, 'name' => '$newToo', 'content' => '\Package\TypeB $newToo = new \Package\TypeB(10, \'string\')', 'default' => "new \Package\TypeB(10, 'string')", 'default_token' => 32, 'default_equal_token' => 30, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '\Package\TypeB', 'type_hint_token' => 23, 'type_hint_end_token' => 26, 'nullable_type' => false, 'comma_token' => 44, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81NewInInitializers() /** * Verify recognition of 8.2 DNF parameter type declarations. * * @return void */ public function testPHP82DNFTypes() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 21, 'name' => '$obj1', 'content' => '#[MyAttribute] false|(Foo&Bar)|true $obj1', 'has_attributes' => true, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => 'false|(Foo&Bar)|true', 'type_hint_token' => 11, 'type_hint_end_token' => 19, 'nullable_type' => false, 'comma_token' => 22, ]; $expected[1] = [ 'token' => 41, 'name' => '$obj2', 'content' => '(\Boo&\Pck\Bar)|(Boo&Baz) $obj2 = new Boo()', 'default' => 'new Boo()', 'default_token' => 45, 'default_equal_token' => 43, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '(\Boo&\Pck\Bar)|(Boo&Baz)', 'type_hint_token' => 25, 'type_hint_end_token' => 39, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypes() /** * Verify recognition of PHP 8.2 DNF parameter type declarations when the variable * has either a spread operator or a reference. * * @return void */ public function testPHP82DNFTypesWithSpreadOperatorAndReference() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 13, 'name' => '$paramA', 'content' => '(Countable&MeMe)|iterable &$paramA', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 12, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '(Countable&MeMe)|iterable', 'type_hint_token' => 4, 'type_hint_end_token' => 10, 'nullable_type' => false, 'comma_token' => 14, ]; $expected[1] = [ 'token' => 25, 'name' => '$paramB', 'content' => 'true|(Foo&Bar) ...$paramB', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 24, 'type_hint' => 'true|(Foo&Bar)', 'type_hint_token' => 16, 'type_hint_end_token' => 22, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypesWithSpreadOperatorAndReference() /** * Verify recognition of PHP 8.2 DNF parameter type declarations using the nullability operator (not allowed). * * @return void */ public function testPHP82DNFTypesIllegalNullable() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 27, 'name' => '$var', 'content' => '? ( MyClassA & /*comment*/ \Package\MyClassB & \Package\MyClassC ) $var', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?(MyClassA&\Package\MyClassB&\Package\MyClassC)', 'type_hint_token' => 5, 'type_hint_end_token' => 25, 'nullable_type' => true, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypesIllegalNullable() /** * Verify recognition of PHP 8.2 DNF parameter type declarations in an arrow function. * * @return void */ public function testPHP82DNFTypesInArrow() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 12, 'name' => '$range', 'content' => '(Hi&Ho)|FALSE &...$range', 'has_attributes' => false, 'pass_by_reference' => true, 'reference_token' => 10, 'variable_length' => true, 'variadic_token' => 11, 'type_hint' => '(Hi&Ho)|FALSE', 'type_hint_token' => 2, 'type_hint_end_token' => 8, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypesInArrow() /** * Verify handling of a closure. * * @return void */ public function testClosure() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 3, 'name' => '$a', 'content' => '$a = \'test\'', 'default' => "'test'", 'default_token' => 7, 'default_equal_token' => 5, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosure() /** * Verify handling of a closure T_USE token correctly. * * @return void */ public function testClosureUse() { // Offsets are relative to the T_USE token. $expected = []; $expected[0] = [ 'token' => 3, 'name' => '$foo', 'content' => '$foo', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 4, ]; $expected[1] = [ 'token' => 6, 'name' => '$bar', 'content' => '$bar', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => false, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected, [T_USE]); }//end testClosureUse() /** * Verify function declarations with trailing commas are handled correctly. * * @return void */ public function testFunctionParamListWithTrailingComma() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 9, 'name' => '$foo', 'content' => '?string $foo /*comment*/', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?string', 'type_hint_token' => 7, 'type_hint_end_token' => 7, 'nullable_type' => true, 'comma_token' => 13, ]; $expected[1] = [ 'token' => 16, 'name' => '$bar', 'content' => '$bar = 0', 'default' => '0', 'default_token' => 20, 'default_equal_token' => 18, 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 21, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testFunctionParamListWithTrailingComma() /** * Verify closure declarations with trailing commas are handled correctly. * * @return void */ public function testClosureParamListWithTrailingComma() { // Offsets are relative to the T_FUNCTION token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$foo', 'content' => '$foo', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 5, ]; $expected[1] = [ 'token' => 8, 'name' => '$bar', 'content' => '$bar', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 9, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosureParamListWithTrailingComma() /** * Verify arrow function declarations with trailing commas are handled correctly. * * @return void */ public function testArrowFunctionParamListWithTrailingComma() { // Offsets are relative to the T_FN token. $expected = []; $expected[0] = [ 'token' => 6, 'name' => '$a', 'content' => '?int $a', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '?int', 'type_hint_token' => 4, 'type_hint_end_token' => 4, 'nullable_type' => true, 'comma_token' => 8, ]; $expected[1] = [ 'token' => 11, 'name' => '$b', 'content' => '...$b', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => true, 'variadic_token' => 10, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 12, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunctionParamListWithTrailingComma() /** * Verify closure T_USE statements with trailing commas are handled correctly. * * @return void */ public function testClosureUseWithTrailingComma() { // Offsets are relative to the T_USE token. $expected = []; $expected[0] = [ 'token' => 4, 'name' => '$foo', 'content' => '$foo /*comment*/', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 8, ]; $expected[1] = [ 'token' => 11, 'name' => '$bar', 'content' => '$bar', 'has_attributes' => false, 'pass_by_reference' => false, 'reference_token' => false, 'variable_length' => false, 'variadic_token' => false, 'type_hint' => '', 'type_hint_token' => false, 'type_hint_end_token' => false, 'nullable_type' => false, 'comma_token' => 12, ]; $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected, [T_USE]); }//end testClosureUseWithTrailingComma() /** * Test helper. * * @param string $commentString The comment which preceeds the test. * @param array> $expected The expected function output. * @param int|string|array $targetType Optional. The token type to search for after $marker. * Defaults to the function/closure/arrow tokens. * * @return void */ private function getMethodParametersTestHelper($commentString, $expected, $targetType=[T_FUNCTION, T_CLOSURE, T_FN]) { $target = $this->getTargetToken($commentString, $targetType); $found = self::$phpcsFile->getMethodParameters($target); // Convert offsets to absolute positions in the token stream. foreach ($expected as $key => $param) { $expected[$key]['token'] += $target; if (is_int($param['reference_token']) === true) { $expected[$key]['reference_token'] += $target; } if (is_int($param['variadic_token']) === true) { $expected[$key]['variadic_token'] += $target; } if (is_int($param['type_hint_token']) === true) { $expected[$key]['type_hint_token'] += $target; } if (is_int($param['type_hint_end_token']) === true) { $expected[$key]['type_hint_end_token'] += $target; } if (is_int($param['comma_token']) === true) { $expected[$key]['comma_token'] += $target; } if (isset($param['default_token']) === true) { $expected[$key]['default_token'] += $target; } if (isset($param['default_equal_token']) === true) { $expected[$key]['default_equal_token'] += $target; } if (isset($param['visibility_token']) === true && is_int($param['visibility_token']) === true) { $expected[$key]['visibility_token'] += $target; } if (isset($param['readonly_token']) === true) { $expected[$key]['readonly_token'] += $target; } }//end foreach $this->assertSame($expected, $found); }//end getMethodParametersTestHelper() }//end class