* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @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::getMethodProperties method. * * @covers \PHP_CodeSniffer\Files\File::getMethodProperties */ final class GetMethodPropertiesTest extends AbstractMethodUnitTest { /** * Test receiving an expected exception when a non function token is passed. * * @param string $commentString The comment which preceeds the test. * @param string|int|array $targetTokenType The token type to search for after $commentString. * * @dataProvider dataNotAFunctionException * * @return void */ public function testNotAFunctionException($commentString, $targetTokenType) { $this->expectRunTimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_FN'); $next = $this->getTargetToken($commentString, $targetTokenType); self::$phpcsFile->getMethodProperties($next); }//end testNotAFunctionException() /** * Data Provider. * * @see testNotAFunctionException() For the array format. * * @return array>> */ public static function dataNotAFunctionException() { return [ 'return' => [ 'commentString' => '/* testNotAFunction */', 'targetTokenType' => T_RETURN, ], '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 dataNotAFunctionException() /** * Test a basic function. * * @return void */ public function testBasicFunction() { $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testBasicFunction() /** * Test a function with a return type. * * @return void */ public function testReturnFunction() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'array', 'return_type_token' => 11, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnFunction() /** * Test a closure used as a function argument. * * @return void */ public function testNestedClosure() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'int', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testNestedClosure() /** * Test a basic method. * * @return void */ public function testBasicMethod() { $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testBasicMethod() /** * Test a private static method. * * @return void */ public function testPrivateStaticMethod() { $expected = [ 'scope' => 'private', 'scope_specified' => true, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => true, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPrivateStaticMethod() /** * Test a basic final method. * * @return void */ public function testFinalMethod() { $expected = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => true, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testFinalMethod() /** * Test a protected method with a return type. * * @return void */ public function testProtectedReturnMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'protected', 'scope_specified' => true, 'return_type' => 'int', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testProtectedReturnMethod() /** * Test a public method with a return type. * * @return void */ public function testPublicReturnMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => 'array', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPublicReturnMethod() /** * Test a public method with a nullable return type. * * @return void */ public function testNullableReturnMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => '?array', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testNullableReturnMethod() /** * Test a public method with a nullable return type. * * @return void */ public function testMessyNullableReturnMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => '?array', 'return_type_token' => 18, 'return_type_end_token' => 18, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testMessyNullableReturnMethod() /** * Test a method with a namespaced return type. * * @return void */ public function testReturnNamespace() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '\MyNamespace\MyClass', 'return_type_token' => 7, 'return_type_end_token' => 10, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnNamespace() /** * Test a method with a messy namespaces return type. * * @return void */ public function testReturnMultilineNamespace() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '\MyNamespace\MyClass\Foo', 'return_type_token' => 7, 'return_type_end_token' => 23, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnMultilineNamespace() /** * Test a method with an unqualified named return type. * * @return void */ public function testReturnUnqualifiedName() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'private', 'scope_specified' => true, 'return_type' => '?MyClass', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnUnqualifiedName() /** * Test a method with a partially qualified namespaced return type. * * @return void */ public function testReturnPartiallyQualifiedName() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'Sub\Level\MyClass', 'return_type_token' => 7, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnPartiallyQualifiedName() /** * Test a basic abstract method. * * @return void */ public function testAbstractMethod() { $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => true, 'is_final' => false, 'is_static' => false, 'has_body' => false, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testAbstractMethod() /** * Test an abstract method with a return type. * * @return void */ public function testAbstractReturnMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'protected', 'scope_specified' => true, 'return_type' => 'bool', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => true, 'is_final' => false, 'is_static' => false, 'has_body' => false, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testAbstractReturnMethod() /** * Test a basic interface method. * * @return void */ public function testInterfaceMethod() { $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => false, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testInterfaceMethod() /** * Test a static arrow function. * * @return void */ public function testArrowFunction() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'int', 'return_type_token' => 9, 'return_type_end_token' => 9, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => true, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunction() /** * Test a function with return type "static". * * @return void */ public function testReturnTypeStatic() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'private', 'scope_specified' => true, 'return_type' => 'static', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnTypeStatic() /** * Test a function with return type "?static". * * @return void */ public function testReturnTypeNullableStatic() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?static', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testReturnTypeNullableStatic() /** * Test a function with return type "mixed". * * @return void */ public function testPHP8MixedTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'mixed', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8MixedTypeHint() /** * Test a function with return type "mixed" and nullability. * * @return void */ public function testPHP8MixedTypeHintNullable() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?mixed', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8MixedTypeHintNullable() /** * Test a function with return type using the namespace operator. * * @return void */ public function testNamespaceOperatorTypeHint() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?namespace\Name', 'return_type_token' => 9, 'return_type_end_token' => 11, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'int|float', 'return_type_token' => 9, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8UnionTypesSimple() /** * Verify recognition of PHP8 union type declaration with two classes. * * @return void */ public function testPHP8UnionTypesTwoClasses() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'MyClassA|\Package\MyClassB', 'return_type_token' => 6, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'array|bool|callable|int|float|null|Object|string', 'return_type_token' => 8, 'return_type_end_token' => 22, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'false|MIXED|self|parent|static|iterable|Resource|void', 'return_type_token' => 9, 'return_type_end_token' => 23, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?int|float', 'return_type_token' => 12, 'return_type_end_token' => 14, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'null', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'false', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'bool|false', 'return_type_token' => 7, 'return_type_end_token' => 9, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'object|ClassName', 'return_type_token' => 7, 'return_type_end_token' => 9, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => 'iterable|array|Traversable', 'return_type_token' => 7, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => false, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'int|string|INT', 'return_type_token' => 7, 'return_type_end_token' => 17, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() /** * Verify recognition of PHP8.1 type "never". * * @return void */ public function testPHP81NeverType() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'never', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81NeverType() /** * Verify recognition of PHP8.1 type "never" with (illegal) nullability. * * @return void */ public function testPHP81NullableNeverType() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?never', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81NullableNeverType() /** * Verify recognition of PHP8.1 intersection type declaration. * * @return void */ public function testPHP8IntersectionTypes() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'Foo&Bar', 'return_type_token' => 7, 'return_type_end_token' => 9, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP8IntersectionTypes() /** * 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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', 'return_type_token' => 7, 'return_type_end_token' => 17, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81MoreIntersectionTypes() /** * Verify recognition of PHP8.1 intersection type declaration in arrow function. * * @return void */ public function testPHP81IntersectionArrowFunction() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'MyClassA&\Package\MyClassB', 'return_type_token' => 6, 'return_type_end_token' => 11, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP81IntersectionArrowFunction() /** * 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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'string&int', 'return_type_token' => 6, 'return_type_end_token' => 8, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?Foo&Bar', 'return_type_token' => 7, 'return_type_end_token' => 9, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?true', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__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 = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'true|false', 'return_type_token' => 7, 'return_type_end_token' => 9, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82PseudoTypeFalseAndTrue() /** * Verify recognition of PHP 8.2 DNF return type declaration. * * @return void */ public function testPHP82DNFType() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'bool|(Foo&Bar)|string', 'return_type_token' => 8, 'return_type_end_token' => 16, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFType() /** * Verify recognition of PHP 8.2 DNF return type declaration on an abstract method. * * @return void */ public function testPHP82DNFTypeAbstractMethod() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'protected', 'scope_specified' => true, 'return_type' => 'float|(Foo&Bar)', 'return_type_token' => 8, 'return_type_end_token' => 14, 'nullable_return_type' => false, 'is_abstract' => true, 'is_final' => false, 'is_static' => false, 'has_body' => false, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypeAbstractMethod() /** * Verify recognition of PHP 8.2 DNF return type declaration with illegal nullability. * * @return void */ public function testPHP82DNFTypeIllegalNullable() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?(A&\Pck\B)|bool', 'return_type_token' => 8, 'return_type_end_token' => 17, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypeIllegalNullable() /** * Verify recognition of PHP 8.2 DNF return type declaration on a closure. * * @return void */ public function testPHP82DNFTypeClosure() { // Offsets are relative to the T_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'object|(namespace\Foo&Countable)', 'return_type_token' => 6, 'return_type_end_token' => 14, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypeClosure() /** * Verify recognition of PHP 8.2 DNF return type declaration on an arrow function. * * @return void */ public function testPHP82DNFTypeFn() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'null|(Partially\Qualified&Traversable)|void', 'return_type_token' => 6, 'return_type_end_token' => 16, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPHP82DNFTypeFn() /** * Test for incorrect tokenization of array return type declarations in PHPCS < 2.8.0. * * @link https://github.com/squizlabs/PHP_CodeSniffer/pull/1264 * * @return void */ public function testPhpcsIssue1264() { // Offsets are relative to the T_FUNCTION token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'array', 'return_type_token' => 8, 'return_type_end_token' => 8, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testPhpcsIssue1264() /** * Test handling of incorrect tokenization of array return type declarations for arrow functions * in a very specific code sample in PHPCS < 3.5.4. * * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/2773 * * @return void */ public function testArrowFunctionArrayReturnValue() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'array', 'return_type_token' => 5, 'return_type_end_token' => 5, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunctionArrayReturnValue() /** * Test handling of an arrow function returning by reference. * * @return void */ public function testArrowFunctionReturnByRef() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?string', 'return_type_token' => 12, 'return_type_end_token' => 12, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testArrowFunctionReturnByRef() /** * Test handling of function declaration nested in a ternary, where the colon for the * return type was incorrectly tokenized as T_INLINE_ELSE prior to PHPCS 3.5.7. * * @return void */ public function testFunctionDeclarationNestedInTernaryPHPCS2975() { // Offsets are relative to the T_FN token. $expected = [ 'scope' => 'public', 'scope_specified' => true, 'return_type' => 'c', 'return_type_token' => 7, 'return_type_end_token' => 7, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testFunctionDeclarationNestedInTernaryPHPCS2975() /** * Test handling of closure declarations with a use variable import without a return type declaration. * * @return void */ public function testClosureWithUseNoReturnType() { // Offsets are relative to the T_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosureWithUseNoReturnType() /** * Test handling of closure declarations with an illegal use variable for a property import (not allowed in PHP) * without a return type declaration. * * @return void */ public function testClosureWithUseNoReturnTypeIllegalUseProp() { // Offsets are relative to the T_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '', 'return_type_token' => false, 'return_type_end_token' => false, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosureWithUseNoReturnTypeIllegalUseProp() /** * Test handling of closure declarations with a use variable import with a return type declaration. * * @return void */ public function testClosureWithUseWithReturnType() { // Offsets are relative to the T_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => 'Type', 'return_type_token' => 14, 'return_type_end_token' => 14, 'nullable_return_type' => false, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosureWithUseWithReturnType() /** * Test handling of closure declarations with a use variable import with a return type declaration. * * @return void */ public function testClosureWithUseMultiParamWithReturnType() { // Offsets are relative to the T_CLOSURE token. $expected = [ 'scope' => 'public', 'scope_specified' => false, 'return_type' => '?array', 'return_type_token' => 32, 'return_type_end_token' => 32, 'nullable_return_type' => true, 'is_abstract' => false, 'is_final' => false, 'is_static' => false, 'has_body' => true, ]; $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); }//end testClosureWithUseMultiParamWithReturnType() /** * Test helper. * * @param string $commentString The comment which preceeds the test. * @param array $expected The expected function output. * * @return void */ private function getMethodPropertiesTestHelper($commentString, $expected) { $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); $found = self::$phpcsFile->getMethodProperties($function); // Convert offsets to absolute positions in the token stream. if (is_int($expected['return_type_token']) === true) { $expected['return_type_token'] += $function; } if (is_int($expected['return_type_end_token']) === true) { $expected['return_type_end_token'] += $function; } $this->assertSame($expected, $found); }//end getMethodPropertiesTestHelper() }//end class