From d16f825b5b16433e50f29ee538d67554c30f7e70 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Thu, 13 Apr 2023 04:10:14 +0200 Subject: [PATCH] BCFile::getDeclarationName(): sync with upstream Follow up on 451 Upstream PR squizlabs/PHP_CodeSniffer 3797, which will be included in PHPCS 3.8.0, fixes a tokenizer issue which affected the `File::getDeclarationName()` and, by extension, the `BackCompat::getDeclarationName()` method. The function name for functions named `self`, `parent` or `static` and declared to return by reference, could previously not be retrieved. The PHPCSUtils native version of the method `ObjectDeclarations::getName()` already handled things correctly. This commit adds back the BC-layer for the `getDeclarationName()` method and polyfills the fix from PHPCS 3.8.0 to backport it for PHPCS < 3.8.0. As the methods will now handle these functions in the same way, this commit also moves the related tests from the `GetNameDiffTest` to the `GetDeclarationNameTest`. --- PHPCSUtils/BackCompat/BCFile.php | 42 ++++++++++++++++++- .../BCFile/GetDeclarationNameTest.inc | 9 ++++ .../BCFile/GetDeclarationNameTest.php | 12 ++++++ .../ObjectDeclarations/GetNameDiffTest.inc | 9 ---- .../ObjectDeclarations/GetNameDiffTest.php | 12 ------ 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/PHPCSUtils/BackCompat/BCFile.php b/PHPCSUtils/BackCompat/BCFile.php index 3c9b56a0..030bde4b 100644 --- a/PHPCSUtils/BackCompat/BCFile.php +++ b/PHPCSUtils/BackCompat/BCFile.php @@ -50,6 +50,7 @@ * any affected utility functions: * - `readonly` classes. * - Constructor property promotion with `readonly` without visibility. + * - OO methods called `self`, `parent` or `static`. * * Most functions in this class will have a related twin-function in the relevant * class in the `PHPCSUtils\Utils` namespace. @@ -75,7 +76,7 @@ final class BCFile * * Changelog for the PHPCS native function: * - Introduced in PHPCS 0.0.5. - * - The upstream method has received no significant updates since PHPCS 3.7.1. + * - PHPCS 3.8.0: OO methods called `self`, `parent` or `static` are now correctly recognized. * * @see \PHP_CodeSniffer\Files\File::getDeclarationName() Original source. * @see \PHPCSUtils\Utils\ObjectDeclarations::getName() PHPCSUtils native improved version. @@ -97,7 +98,44 @@ final class BCFile */ public static function getDeclarationName(File $phpcsFile, $stackPtr) { - return $phpcsFile->getDeclarationName($stackPtr); + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + + if ($tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + return null; + } + + if ($tokenCode !== T_FUNCTION + && $tokenCode !== T_CLASS + && $tokenCode !== T_INTERFACE + && $tokenCode !== T_TRAIT + && $tokenCode !== T_ENUM + ) { + throw new RuntimeException('Token type "' . $tokens[$stackPtr]['type'] . '" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + } + + if ($tokenCode === T_FUNCTION + && strtolower($tokens[$stackPtr]['content']) !== 'function' + ) { + // This is a function declared without the "function" keyword. + // So this token is the function name. + return $tokens[$stackPtr]['content']; + } + + $content = null; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] === T_STRING + // BC: PHPCS < 3.8.0. + || $tokens[$i]['code'] === T_SELF + || $tokens[$i]['code'] === T_PARENT + || $tokens[$i]['code'] === T_STATIC + ) { + $content = $tokens[$i]['content']; + break; + } + } + + return $content; } /** diff --git a/Tests/BackCompat/BCFile/GetDeclarationNameTest.inc b/Tests/BackCompat/BCFile/GetDeclarationNameTest.inc index eba7b48c..14902245 100644 --- a/Tests/BackCompat/BCFile/GetDeclarationNameTest.inc +++ b/Tests/BackCompat/BCFile/GetDeclarationNameTest.inc @@ -88,6 +88,15 @@ enum Suit: int implements Colorful, CardGame {} /* testFunctionReturnByRefWithReservedKeywordEach */ function &each() {} +/* testFunctionReturnByRefWithReservedKeywordParent */ +function &parent() {} + +/* testFunctionReturnByRefWithReservedKeywordSelf */ +function &self() {} + +/* testFunctionReturnByRefWithReservedKeywordStatic */ +function &static() {} + /* testLiveCoding */ // Intentional parse error. This has to be the last test in the file. function // Comment. diff --git a/Tests/BackCompat/BCFile/GetDeclarationNameTest.php b/Tests/BackCompat/BCFile/GetDeclarationNameTest.php index f4fbe64c..f7c8a358 100644 --- a/Tests/BackCompat/BCFile/GetDeclarationNameTest.php +++ b/Tests/BackCompat/BCFile/GetDeclarationNameTest.php @@ -196,6 +196,18 @@ public static function dataGetDeclarationName() '/* testFunctionReturnByRefWithReservedKeywordEach */', 'each', ], + 'function-return-by-reference-with-reserved-keyword-parent' => [ + '/* testFunctionReturnByRefWithReservedKeywordParent */', + 'parent', + ], + 'function-return-by-reference-with-reserved-keyword-self' => [ + '/* testFunctionReturnByRefWithReservedKeywordSelf */', + 'self', + ], + 'function-return-by-reference-with-reserved-keyword-static' => [ + '/* testFunctionReturnByRefWithReservedKeywordStatic */', + 'static', + ], ]; } } diff --git a/Tests/Utils/ObjectDeclarations/GetNameDiffTest.inc b/Tests/Utils/ObjectDeclarations/GetNameDiffTest.inc index 3e54ed11..7a7ae4e5 100644 --- a/Tests/Utils/ObjectDeclarations/GetNameDiffTest.inc +++ b/Tests/Utils/ObjectDeclarations/GetNameDiffTest.inc @@ -12,15 +12,6 @@ interface switch{ // Intentional parse error. public function someFunction(); } -/* testFunctionReturnByRefWithReservedKeywordParent */ -function &parent() {} - -/* testFunctionReturnByRefWithReservedKeywordSelf */ -function &self() {} - -/* testFunctionReturnByRefWithReservedKeywordStatic */ -function &static() {} - /* testLiveCoding */ // Intentional parse error. Redundancy testing. abstract class diff --git a/Tests/Utils/ObjectDeclarations/GetNameDiffTest.php b/Tests/Utils/ObjectDeclarations/GetNameDiffTest.php index 1bcb6942..f30d9549 100644 --- a/Tests/Utils/ObjectDeclarations/GetNameDiffTest.php +++ b/Tests/Utils/ObjectDeclarations/GetNameDiffTest.php @@ -117,18 +117,6 @@ public static function dataGetName() 'testMarker' => '/* testInvalidInterfaceName */', 'expected' => 'switch', ], - 'function-return-by-reference-with-reserved-keyword-parent' => [ - '/* testFunctionReturnByRefWithReservedKeywordParent */', - 'parent', - ], - 'function-return-by-reference-with-reserved-keyword-self' => [ - '/* testFunctionReturnByRefWithReservedKeywordSelf */', - 'self', - ], - 'function-return-by-reference-with-reserved-keyword-static' => [ - '/* testFunctionReturnByRefWithReservedKeywordStatic */', - 'static', - ], ]; } }