*/ public function register() { return [ \T_FUNCTION, ]; } /** * Processes this test, when one of its tokens is encountered. * * @since 10.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in * the stack passed in $tokens. * * @return void */ public function process(File $phpcsFile, $stackPtr) { $functionName = FunctionDeclarations::getName($phpcsFile, $stackPtr); if (empty($functionName) === true) { return; } if (\preg_match('|^__[^_]|', $functionName) !== 1) { // Name doesn't start with double underscore. return; } if ($this->isFunctionDeprecated($phpcsFile, $stackPtr) === true) { /* * Deprecated functions don't have to comply with the naming conventions, * otherwise functions deprecated in favour of a function with a compliant * name would still trigger an error. */ return; } $ooPtr = Scopes::validDirectScope($phpcsFile, $stackPtr, Tokens::$ooScopeTokens); /* * Check functions declared in the global namespace or in a namespace. */ if ($ooPtr === false) { if (FunctionDeclarations::isMagicFunctionName($functionName) === true) { return; } $phpcsFile->addWarning( 'Function name "%s" is discouraged; PHP has reserved all function names with a double underscore prefix for future use.', $stackPtr, 'FunctionDoubleUnderscore', [$functionName] ); return; } /* * Check method declarations. */ if (FunctionDeclarations::isMagicMethodName($functionName) === true) { return; } if (FunctionDeclarations::isPHPDoubleUnderscoreMethod($phpcsFile, $stackPtr) === true) { return; } $className = ObjectDeclarations::getName($phpcsFile, $ooPtr); if (empty($className)) { $className = '[anonymous class]'; } $phpcsFile->addWarning( 'Method name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.', $stackPtr, 'MethodDoubleUnderscore', [$className . '::' . $functionName] ); } /** * Check whether a function has been marked as deprecated via a @deprecated tag * in the function docblock. * * @since 9.3.2 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of a T_FUNCTION * token in the stack. * * @return bool */ private function isFunctionDeprecated(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $ignore = Tokens::$methodPrefixes; $ignore += Tokens::$phpcsCommentTokens; $ignore[\T_WHITESPACE] = \T_WHITESPACE; $ignore[\T_COMMENT] = \T_COMMENT; for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { continue; } if ($tokens[$commentEnd]['code'] === \T_ATTRIBUTE_END && isset($tokens[$commentEnd]['attribute_opener']) === true ) { $commentEnd = $tokens[$commentEnd]['attribute_opener']; continue; } break; } if ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { // Function doesn't have a doc comment or is using the wrong type of comment. return false; } $commentStart = $tokens[$commentEnd]['comment_opener']; foreach ($tokens[$commentStart]['comment_tags'] as $tag) { if ($tokens[$tag]['content'] === '@deprecated') { return true; } } return false; } }