*/ private $errorTypes = [ 'variableArgument' => 'a variable argument', 'zeroArgument' => '0 as an argument', ]; /** * Tokens indicating this is definitely a variable argument. * * @since 10.0.0 * * @var array */ private $varArgTokens = [ \T_VARIABLE => \T_VARIABLE, \T_CLOSURE => \T_CLOSURE, \T_FN => \T_FN, ]; /** * Returns an array of tokens this test wants to listen for. * * @since 5.5 * * @return array */ public function register() { return [\T_BREAK, \T_CONTINUE]; } /** * Processes this test, when one of its tokens is encountered. * * @since 5.5 * * @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) { if (ScannedCode::shouldRunOnOrAbove('5.4') === false) { return; } $tokens = $phpcsFile->getTokens(); $nextSemicolonToken = $phpcsFile->findNext([\T_SEMICOLON, \T_CLOSE_TAG], ($stackPtr), null, false); $errorType = ''; for ($curToken = $stackPtr + 1; $curToken < $nextSemicolonToken; $curToken++) { if ($tokens[$curToken]['code'] === \T_STRING) { // If the next non-whitespace token after the string // is an opening parenthesis then it's a function call. $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, $curToken + 1, null, true); if ($tokens[$openBracket]['code'] === \T_OPEN_PARENTHESIS) { $errorType = 'variableArgument'; break; } } if (isset($this->varArgTokens[$tokens[$curToken]['code']]) === true) { $errorType = 'variableArgument'; break; } if ($tokens[$curToken]['code'] === \T_LNUMBER) { $numberInfo = Numbers::getCompleteNumber($phpcsFile, $curToken); if ($numberInfo['decimal'] === '0') { $errorType = 'zeroArgument'; break; } } } if ($errorType !== '') { $error = 'Using %s on break or continue is forbidden since PHP 5.4'; $errorCode = $errorType . 'Found'; $data = [$this->errorTypes[$errorType]]; $phpcsFile->addError($error, $stackPtr, $errorCode, $data); } } }