Returns true if the specified token position represents a reference.
Returns false if the token represents a bitwise operator.
public isReference ( integer $stackPtr ) : boolean | ||
$stackPtr | integer | The position of the T_BITWISE_AND token. |
Результат | boolean |
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void * @see PHP_CodeSniffer_Sniff::process() */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // Ignore normal references if (true === $phpcsFile->isReference($stackPtr)) { return; } // Ignore all but variables $tokens = $phpcsFile->getTokens(); $token = $tokens[$stackPtr + 1]; if (T_VARIABLE !== $token['code']) { return; } $warning = sprintf('Use of deprecated runtime references for variable "%s"!', $token['content']); $phpcsFile->addWarning($warning, $stackPtr); }
/** * Given a pointer to a bracketed expression (such as T_ARRAY or T_OPEN_SHORT_ARRAY), returns the stack pointer for the opening bracket. * * @param PHP_CodeSniffer_File $phpcsFile The file where the bracketed expression is declared. * @param int $stackPtr The position of the expression element in the stack in $phpcsFile. * * @return int The position of the opening bracket, or if not found, the given $stackPtr. */ public static function isUnary(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['code'] === T_BOOLEAN_NOT) { return true; } if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr)) { return true; } if ($tokens[$stackPtr]['code'] === T_MINUS) { $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); $unaryHints = array_unique(array_merge(PHP_CodeSniffer_Tokens::$comparisonTokens, PHP_CodeSniffer_Tokens::$operators, PHP_CodeSniffer_Tokens::$assignmentTokens, [T_RETURN, T_COMMA, T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET, T_DOUBLE_ARROW, T_COLON, T_INLINE_THEN, T_INLINE_ELSE, T_CASE])); if (in_array($tokens[$prev]['code'], $unaryHints)) { return true; } } return false; }
/** * Processes this sniff, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being checked. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Skip default values in function declarations. if ($tokens[$stackPtr]['code'] === T_EQUAL || $tokens[$stackPtr]['code'] === T_MINUS) { if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { $bracket = end($tokens[$stackPtr]['nested_parenthesis']); if (isset($tokens[$bracket]['parenthesis_owner']) === true) { $function = $tokens[$bracket]['parenthesis_owner']; if ($tokens[$function]['code'] === T_FUNCTION) { return; } } } } if ($tokens[$stackPtr]['code'] === T_EQUAL) { // Skip for '=&' case. if (isset($tokens[$stackPtr + 1]) === true && $tokens[$stackPtr + 1]['code'] === T_BITWISE_AND) { return; } } if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { // If its not a reference, then we expect one space either side of the // bitwise operator. if ($phpcsFile->isReference($stackPtr) === false) { // Check there is one space before the & operator. if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space before "&" operator; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeAmp'); } else { if (strlen($tokens[$stackPtr - 1]['content']) !== 1) { $found = strlen($tokens[$stackPtr - 1]['content']); $error = 'Expected 1 space before "&" operator; %s found'; $data = array($found); $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeAmp', $data); } } // Check there is one space after the & operator. if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space after "&" operator; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterAmp'); } else { if (strlen($tokens[$stackPtr + 1]['content']) !== 1) { $found = strlen($tokens[$stackPtr + 1]['content']); $error = 'Expected 1 space after "&" operator; %s found'; $data = array($found); $phpcsFile->addError($error, $stackPtr, 'SpacingAfterAmp', $data); } } } //end if } else { if ($tokens[$stackPtr]['code'] === T_MINUS) { // Check minus spacing, but make sure we aren't just assigning // a minus value or returning one. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_RETURN) { // Just returning a negative value; eg. return -1. return; } if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$operators) === true) { // Just trying to operate on a negative value; eg. ($var * -1). return; } if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) { // Just trying to compare a negative value; eg. ($var === -1). return; } // A list of tokens that indicate that the token is not // part of an arithmetic operation. $invalidTokens = array(T_COMMA, T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET, T_DOUBLE_ARROW, T_COLON); if (in_array($tokens[$prev]['code'], $invalidTokens) === true) { // Just trying to use a negative value; eg. myFunction($var, -2). return; } $number = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if (in_array($tokens[$number]['code'], array(T_LNUMBER, T_VARIABLE)) === true) { $semi = $phpcsFile->findNext(T_WHITESPACE, $number + 1, null, true); if ($tokens[$semi]['code'] === T_SEMICOLON) { if ($prev !== false && in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) { // This is a negative assignment. return; } } } } //end if $operator = $tokens[$stackPtr]['content']; if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space before \"{$operator}\"; 0 found"; $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore'); } else { if (strlen($tokens[$stackPtr - 1]['content']) !== 1) { // Don't throw an error for assignments, because other standards allow // multiple spaces there to align multiple assignments. if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === false) { $found = strlen($tokens[$stackPtr - 1]['content']); $error = 'Expected 1 space before "%s"; %s found'; $data = array($operator, $found); $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); } } } if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space after \"{$operator}\"; 0 found"; $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter'); } else { if (strlen($tokens[$stackPtr + 1]['content']) !== 1) { $found = strlen($tokens[$stackPtr + 1]['content']); $error = 'Expected 1 space after "%s"; %s found'; $data = array($operator, $found); $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data); } } } //end if }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $functionName = $phpcsFile->findNext(array(T_STRING), $stackPtr); $openBracket = $tokens[$stackPtr]['parenthesis_opener']; $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; $multiLine = $tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']; $nextParam = $openBracket; $params = array(); while (($nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket)) !== false) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextParam + 1, $closeBracket + 1, true); if ($nextToken === false) { break; } $nextCode = $tokens[$nextToken]['code']; if ($nextCode === T_EQUAL) { // Check parameter default spacing. if ($nextToken - $nextParam > 1) { $error = 'Expected 0 spaces between argument "%s" and equals sign; %s found'; $data = array($tokens[$nextParam]['content'], strlen($tokens[$nextParam + 1]['content'])); $phpcsFile->addError($error, $nextToken, 'SpaceBeforeEquals', $data); } if ($tokens[$nextToken + 1]['code'] === T_WHITESPACE) { $error = 'Expected 0 spaces between default value and equals sign for argument "%s"; %s found'; $data = array($tokens[$nextParam]['content'], strlen($tokens[$nextToken + 1]['content'])); $phpcsFile->addError($error, $nextToken, 'SpaceAfterDefault', $data); } } // Find and check the comma (if there is one). $nextComma = $phpcsFile->findNext(T_COMMA, $nextParam + 1, $closeBracket); if ($nextComma !== false) { // Comma found. if ($tokens[$nextComma - 1]['code'] === T_WHITESPACE) { $error = 'Expected 0 spaces between argument "%s" and comma; %s found'; $data = array($tokens[$nextParam]['content'], strlen($tokens[$nextComma - 1]['content'])); $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data); } } // Take references into account when expecting the // location of whitespace. if ($phpcsFile->isReference($nextParam - 1) === true) { $whitespace = $tokens[$nextParam - 2]; } else { $whitespace = $tokens[$nextParam - 1]; } if (empty($params) === false) { // This is not the first argument in the function declaration. $arg = $tokens[$nextParam]['content']; if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); // Before we throw an error, make sure there is no type hint. $comma = $phpcsFile->findPrevious(T_COMMA, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $comma + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = 'Expected 1 space between type hint and argument "%s"; %s found'; $data = array($arg, $gap); $phpcsFile->addError($error, $nextToken, 'SpacingAfterHint', $data); } if ($multiLine === false) { if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space between comma and type hint "%s"; 0 found'; $data = array($hint); $phpcsFile->addError($error, $nextToken, 'NoSapceBeforeHint', $data); } else { $gap = strlen($tokens[$comma + 1]['content']); if ($gap !== 1) { $error = 'Expected 1 space between comma and type hint "%s"; %s found'; $data = array($hint, $gap); $phpcsFile->addError($error, $nextToken, 'SpacingBeforeHint', $data); } } } } else { if ($multiLine === false && $gap !== 1) { $error = 'Expected 1 space between comma and argument "%s"; %s found'; $data = array($arg, $gap); $phpcsFile->addError($error, $nextToken, 'SpacingBeforeArg', $data); } } //end if } else { $error = 'Expected 1 space between comma and argument "%s"; 0 found'; $data = array($arg); $phpcsFile->addError($error, $nextToken, 'NoSpaceBeforeArg', $data); } //end if } else { // First argument in function declaration. if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint. $bracket = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $bracket + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = 'Expected 1 space between type hint and argument "%s"; %s found'; $data = array($arg, $gap); $phpcsFile->addError($error, $nextToken, 'SpacingAfterHint', $data); } if ($multiLine === false && $tokens[$bracket + 1]['code'] === T_WHITESPACE) { $error = 'Expected 0 spaces between opening bracket and type hint "%s"; %s found'; $data = array($hint, strlen($tokens[$bracket + 1]['content'])); $phpcsFile->addError($error, $nextToken, 'SpacingAfterOpenHint', $data); } } else { if ($multiLine === false) { $error = 'Expected 0 spaces between opening bracket and argument "%s"; %s found'; $data = array($arg, $gap); $phpcsFile->addError($error, $nextToken, 'SpacingAfterOpen', $data); } } } //end if } //end if $params[] = $nextParam; } //end while if (empty($params) === true) { // There are no parameters for this function. if ($closeBracket - $openBracket !== 1) { $error = 'Expected 0 spaces between brackets of function declaration; %s found'; $data = array(strlen($tokens[$closeBracket - 1]['content'])); $phpcsFile->addError($error, $stackPtr, 'SpacingBetween', $data); } } else { if ($multiLine === false && $tokens[$closeBracket - 1]['code'] === T_WHITESPACE) { $lastParam = array_pop($params); $error = 'Expected 0 spaces between argument "%s" and closing bracket; %s found'; $data = array($tokens[$lastParam]['content'], strlen($tokens[$closeBracket - 1]['content'])); $phpcsFile->addError($error, $closeBracket, 'SpacingBeforeClose', $data); } } }
/** * Processes this sniff, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being checked. * @param int $stackPtr The position of the current token in * the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Skip default values in function declarations. if ($tokens[$stackPtr]['code'] === T_EQUAL || $tokens[$stackPtr]['code'] === T_MINUS) { if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); $bracket = array_pop($parenthesis); if (isset($tokens[$bracket]['parenthesis_owner']) === true) { $function = $tokens[$bracket]['parenthesis_owner']; if ($tokens[$function]['code'] === T_FUNCTION || $tokens[$function]['code'] === T_CLOSURE) { return; } } } } if ($tokens[$stackPtr]['code'] === T_EQUAL) { // Skip for '=&' case. if (isset($tokens[$stackPtr + 1]) === true && $tokens[$stackPtr + 1]['code'] === T_BITWISE_AND) { return; } } // Skip short ternary such as: "$foo = $bar ?: true;". if ($tokens[$stackPtr]['code'] == T_INLINE_THEN && $tokens[$stackPtr + 1]['code'] == T_INLINE_ELSE || $tokens[$stackPtr - 1]['code'] == T_INLINE_THEN && $tokens[$stackPtr]['code'] == T_INLINE_ELSE) { return; } if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { // If it's not a reference, then we expect one space either side of the // bitwise operator. if ($phpcsFile->isReference($stackPtr) === true) { return; } // Check there is one space before the & operator. if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space before "&" operator; 0 found'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAmp'); if ($fix === true) { $phpcsFile->fixer->addContentBefore($stackPtr, ' '); } $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); } else { if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) { $found = 'newline'; } else { $found = $tokens[$stackPtr - 1]['length']; } $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); if ($found !== 1) { $error = 'Expected 1 space before "&" operator; %s found'; $data = array($found); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAmp', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($stackPtr - 1, ' '); } } } //end if // Check there is one space after the & operator. if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space after "&" operator; 0 found'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAmp'); if ($fix === true) { $phpcsFile->fixer->addContent($stackPtr, ' '); } $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); } else { if ($tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) { $found = 'newline'; } else { $found = $tokens[$stackPtr + 1]['length']; } $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); if ($found !== 1) { $error = 'Expected 1 space after "&" operator; %s found'; $data = array($found); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAmp', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); } } } //end if return; } //end if if ($tokens[$stackPtr]['code'] === T_MINUS) { // Check minus spacing, but make sure we aren't just assigning // a minus value or returning one. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_RETURN) { // Just returning a negative value; eg. (return -1). return; } if (isset(PHP_CodeSniffer_Tokens::$operators[$tokens[$prev]['code']]) === true) { // Just trying to operate on a negative value; eg. ($var * -1). return; } if (isset(PHP_CodeSniffer_Tokens::$comparisonTokens[$tokens[$prev]['code']]) === true) { // Just trying to compare a negative value; eg. ($var === -1). return; } if (isset(PHP_CodeSniffer_Tokens::$assignmentTokens[$tokens[$prev]['code']]) === true) { // Just trying to assign a negative value; eg. ($var = -1). return; } // A list of tokens that indicate that the token is not // part of an arithmetic operation. $invalidTokens = array(T_COMMA => true, T_OPEN_PARENTHESIS => true, T_OPEN_SQUARE_BRACKET => true, T_DOUBLE_ARROW => true, T_COLON => true, T_INLINE_THEN => true, T_INLINE_ELSE => true, T_CASE => true); if (isset($invalidTokens[$tokens[$prev]['code']]) === true) { // Just trying to use a negative value; eg. myFunction($var, -2). return; } } //end if $operator = $tokens[$stackPtr]['content']; if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space before \"{$operator}\"; 0 found"; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); if ($fix === true) { $phpcsFile->fixer->addContentBefore($stackPtr, ' '); } $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); } else { if (isset(PHP_CodeSniffer_Tokens::$assignmentTokens[$tokens[$stackPtr]['code']]) === false) { // Don't throw an error for assignments, because other standards allow // multiple spaces there to align multiple assignments. if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) { $found = 'newline'; } else { $found = $tokens[$stackPtr - 1]['length']; } $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); if ($found !== 1) { $error = 'Expected 1 space before "%s"; %s found'; $data = array($operator, $found); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($stackPtr - 1, ' '); } } } } //end if if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space after \"{$operator}\"; 0 found"; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); if ($fix === true) { $phpcsFile->fixer->addContent($stackPtr, ' '); } $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); } else { if ($tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) { $found = 'newline'; } else { $found = $tokens[$stackPtr + 1]['length']; } $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); if ($found !== 1) { $error = 'Expected 1 space after "%s"; %s found'; $data = array($operator, $found); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfter', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); } } } //end if }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $constName = $tokens[$stackPtr]['content']; // If this token is in a heredoc, ignore it. if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) { return; } // Special case for PHPUnit. if ($constName === 'PHPUnit_MAIN_METHOD') { return; } // If the next non-whitespace token after this token // is not an opening parenthesis then it is not a function call. $openBracket = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { $functionKeyword = $phpcsFile->findPrevious(array(T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING, T_NS_SEPARATOR), $stackPtr - 1, null, true); $declarations = array(T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT, T_IMPLEMENTS, T_EXTENDS, T_INSTANCEOF, T_NEW, T_NAMESPACE, T_USE, T_AS, T_GOTO, T_INSTEADOF); if (in_array($tokens[$functionKeyword]['code'], $declarations) === true) { // This is just a declaration; no constants here. return; } if ($tokens[$functionKeyword]['code'] === T_CONST) { // This is a class constant. if (strtoupper($constName) !== $constName) { $error = 'Class constants must be uppercase; expected %s but found %s'; $data = array(strtoupper($constName), $constName); $phpcsFile->addError($error, $stackPtr, 'ClassConstantNotUpperCase', $data); } return; } // Is this a class name? $nextPtr = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$nextPtr]['code'] === T_DOUBLE_COLON) { return; } // Is this a namespace name? if ($tokens[$nextPtr]['code'] === T_NS_SEPARATOR) { return; } // Is this an insteadof name? if ($tokens[$nextPtr]['code'] === T_INSTEADOF) { return; } // Is this a type hint? if ($tokens[$nextPtr]['code'] === T_VARIABLE || $phpcsFile->isReference($nextPtr) === true) { return; } // Is this a member var name? $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) { return; } // Is this a variable name, in the form ${varname} ? if ($tokens[$prevPtr]['code'] === T_OPEN_CURLY_BRACKET) { $nextPtr = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$nextPtr]['code'] === T_CLOSE_CURLY_BRACKET) { return; } } // Is this a namespace name? if ($tokens[$prevPtr]['code'] === T_NS_SEPARATOR) { return; } // Is this an instance of declare() $prevPtrDeclare = $phpcsFile->findPrevious(array(T_WHITESPACE, T_OPEN_PARENTHESIS), $stackPtr - 1, null, true); if ($tokens[$prevPtrDeclare]['code'] === T_DECLARE) { return; } // Is this a goto label target? if ($tokens[$nextPtr]['code'] === T_COLON) { if (in_array($tokens[$prevPtr]['code'], array(T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_COLON), true)) { return; } } // This is a real constant. if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected %s but found %s'; $data = array(strtoupper($constName), $constName); $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } } else { if (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { /* This may be a "define" or "constant" function call. */ // Make sure this is not a method call. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR || $tokens[$prev]['code'] === T_DOUBLE_COLON) { return; } // The next non-whitespace token must be the constant name. $constPtr = $phpcsFile->findNext(T_WHITESPACE, $openBracket + 1, null, true); if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $constName = $tokens[$constPtr]['content']; // Check for constants like self::CONSTANT. $prefix = ''; $splitPos = strpos($constName, '::'); if ($splitPos !== false) { $prefix = substr($constName, 0, $splitPos + 2); $constName = substr($constName, $splitPos + 2); } if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected %s but found %s'; $data = array($prefix . strtoupper($constName), $prefix . $constName); $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } } } //end if }
/** * Processes the contents of a single set of brackets. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $openBracket The position of the open bracket * in the stack passed in $tokens. * * @return void */ public function processBracket(PHP_CodeSniffer_File $phpcsFile, $openBracket) { $tokens = $phpcsFile->getTokens(); $closeBracket = $tokens[$openBracket]['parenthesis_closer']; $multiLine = $tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']; $nextParam = $openBracket; $params = array(); while (($nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket)) !== false) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextParam + 1, $closeBracket + 1, true); if ($nextToken === false) { break; } $nextCode = $tokens[$nextToken]['code']; if ($nextCode === T_EQUAL) { // Check parameter default spacing. $spacesBefore = 0; if ($nextToken - $nextParam > 1) { $spacesBefore = strlen($tokens[$nextParam + 1]['content']); } if ($spacesBefore !== $this->equalsSpacing) { $error = 'Incorrect spacing between argument "%s" and equals sign; expected ' . $this->equalsSpacing . ' but found %s'; $data = array($tokens[$nextParam]['content'], $spacesBefore); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeEquals', $data); if ($fix === true) { $padding = str_repeat(' ', $this->equalsSpacing); if ($spacesBefore === 0) { $phpcsFile->fixer->addContentBefore($nextToken, $padding); } else { $phpcsFile->fixer->replaceToken($nextToken - 1, $padding); } } } //end if $spacesAfter = 0; if ($tokens[$nextToken + 1]['code'] === T_WHITESPACE) { $spacesAfter = strlen($tokens[$nextToken + 1]['content']); } if ($spacesAfter !== $this->equalsSpacing) { $error = 'Incorrect spacing between default value and equals sign for argument "%s"; expected ' . $this->equalsSpacing . ' but found %s'; $data = array($tokens[$nextParam]['content'], $spacesAfter); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceAfterDefault', $data); if ($fix === true) { $padding = str_repeat(' ', $this->equalsSpacing); if ($spacesAfter === 0) { $phpcsFile->fixer->addContent($nextToken, $padding); } else { $phpcsFile->fixer->replaceToken($nextToken + 1, $padding); } } } //end if } //end if // Find and check the comma (if there is one). $nextComma = $phpcsFile->findNext(T_COMMA, $nextParam + 1, $closeBracket); if ($nextComma !== false) { // Comma found. if ($tokens[$nextComma - 1]['code'] === T_WHITESPACE) { $error = 'Expected 0 spaces between argument "%s" and comma; %s found'; $data = array($tokens[$nextParam]['content'], strlen($tokens[$nextComma - 1]['content'])); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($nextComma - 1, ''); } } } // Take references into account when expecting the // location of whitespace. $checkToken = $nextParam - 1; if ($tokens[$checkToken]['code'] === T_ELLIPSIS) { $checkToken--; } if ($phpcsFile->isReference($checkToken) === true) { $whitespace = $checkToken - 1; } else { $whitespace = $checkToken; } if (empty($params) === false) { // This is not the first argument in the function declaration. $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint. $comma = $phpcsFile->findPrevious(T_COMMA, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $comma + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } $gap = 0; if ($tokens[$whitespace]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$whitespace]['content']); } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = 'Expected 1 space between type hint and argument "%s"; %s found'; $data = array($arg, $gap); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingAfterHint', $data); if ($fix === true) { if ($gap === 0) { $phpcsFile->fixer->addContent($whitespace, ' '); } else { $phpcsFile->fixer->replaceToken($whitespace, ' '); } } } if ($multiLine === false) { if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space between comma and type hint "%s"; 0 found'; $data = array($hint); $fix = $phpcsFile->addFixableError($error, $nextToken, 'NoSpaceBeforeHint', $data); if ($fix === true) { $phpcsFile->fixer->addContent($comma, ' '); } } else { $gap = strlen($tokens[$comma + 1]['content']); if ($gap !== 1) { $error = 'Expected 1 space between comma and type hint "%s"; %s found'; $data = array($hint, $gap); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingBeforeHint', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($comma + 1, ' '); } } } //end if } //end if } else { // No type hint. if ($gap === 0) { $error = 'Expected 1 space between comma and argument "%s"; 0 found'; $data = array($arg); $fix = $phpcsFile->addFixableError($error, $nextToken, 'NoSpaceBeforeArg', $data); if ($fix === true) { $phpcsFile->fixer->addContent($whitespace, ' '); } } else { if ($gap !== 1) { // Just make sure this is not actually an indent. if ($tokens[$whitespace]['line'] === $tokens[$whitespace - 1]['line']) { $error = 'Expected 1 space between comma and argument "%s"; %s found'; $data = array($arg, $gap); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingBeforeArg', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($whitespace, ' '); } } } } //end if } //end if } else { $gap = 0; if ($tokens[$whitespace]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$whitespace]['content']); } $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint. $bracket = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $bracket + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($tokens[$nextToken]['code'] !== T_ELLIPSIS && $nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = 'Expected 1 space between type hint and argument "%s"; %s found'; $data = array($arg, $gap); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingAfterHint', $data); if ($fix === true) { if ($gap === 0) { $phpcsFile->fixer->addContent($nextToken, ' '); } else { $phpcsFile->fixer->replaceToken($nextToken + 1, ' '); } } } $spaceAfterOpen = 0; if ($tokens[$bracket + 1]['code'] === T_WHITESPACE) { $spaceAfterOpen = strlen($tokens[$bracket + 1]['content']); } if ($multiLine === false && $spaceAfterOpen !== $this->requiredSpacesAfterOpen) { $error = 'Expected %s spaces between opening bracket and type hint "%s"; %s found'; $data = array($this->requiredSpacesAfterOpen, $hint, $spaceAfterOpen); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingAfterOpenHint', $data); if ($fix === true) { $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); if ($spaceAfterOpen === 0) { $phpcsFile->fixer->addContent($openBracket, $padding); } else { $phpcsFile->fixer->replaceToken($openBracket + 1, $padding); } } } } else { if ($multiLine === false && $gap !== $this->requiredSpacesAfterOpen) { $error = 'Expected %s spaces between opening bracket and argument "%s"; %s found'; $data = array($this->requiredSpacesAfterOpen, $arg, $gap); $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpacingAfterOpen', $data); if ($fix === true) { $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); if ($gap === 0) { $phpcsFile->fixer->addContent($openBracket, $padding); } else { $phpcsFile->fixer->replaceToken($openBracket + 1, $padding); } } } } //end if } //end if $params[] = $nextParam; } //end while $gap = 0; if ($tokens[$closeBracket - 1]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$closeBracket - 1]['content']); } if (empty($params) === true) { // There are no parameters for this function. if ($closeBracket - $openBracket !== 1) { $error = 'Expected 0 spaces between brackets of function declaration; %s found'; $data = array($gap); $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingBetween', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($openBracket + 1, ''); } } } else { if ($multiLine === false && $gap !== $this->requiredSpacesBeforeClose) { $lastParam = array_pop($params); $error = 'Expected %s spaces between argument "%s" and closing bracket; %s found'; $data = array($this->requiredSpacesBeforeClose, $tokens[$lastParam]['content'], $gap); $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpacingBeforeClose', $data); if ($fix === true) { $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); if ($gap === 0) { $phpcsFile->fixer->addContentBefore($closeBracket, $padding); } else { $phpcsFile->fixer->replaceToken($closeBracket - 1, $padding); } } } } //end if }
/** * Processes this test, when one of its tokens is encountered * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned * @param integer $stackPtr The position of the current token in the stack passed in $tokens * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $functionName = $phpcsFile->findNext(array(T_STRING), $stackPtr); $openBracket = $tokens[$stackPtr]['parenthesis_opener']; $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; $nextParam = $openBracket; $params = array(); $nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket); while ($nextParam !== false) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextParam + 1, $closeBracket + 1, true); if ($nextToken === false and $tokens[$nextParam + 1]['code'] === T_CLOSE_PARENTHESIS) { break; } $nextCode = $tokens[$nextToken]['code']; if ($nextCode === T_EQUAL) { // Check parameter default spacing $content = $tokens[$nextParam + 1]['content']; if ($content !== ' ') { $gap = strlen($content); if ($gap === 1) { $gap = 0; } $arg = $tokens[$nextParam]['content']; $error = "Expected 1 space between argument \"{$arg}\" and equals sign; {$gap} found"; $phpcsFile->addError($error, $nextToken); } $content = $tokens[$nextToken + 1]['content']; if ($content !== ' ') { if ($tokens[$nextToken + 1]['code'] !== T_WHITESPACE) { $gap = 0; } else { $gap = strlen($content); } $arg = $tokens[$nextParam]['content']; $error = "Expected 1 space between default value and equals sign for argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } // Find and check the comma (if there is one) $nextComma = $phpcsFile->findNext(T_COMMA, $nextParam + 1, $closeBracket); if ($nextComma !== false) { // Comma found if ($tokens[$nextComma - 1]['code'] === T_WHITESPACE) { $space = strlen($tokens[$nextComma - 1]['content']); $arg = $tokens[$nextParam]['content']; $error = "Expected 0 spaces between argument \"{$arg}\" and comma; {$space} found"; $phpcsFile->addError($error, $nextToken); } } // Take references into account when expecting the location of whitespace if ($phpcsFile->isReference($nextParam - 1) === true) { $whitespace = $tokens[$nextParam - 2]; } else { $whitespace = $tokens[$nextParam - 1]; } if (empty($params) === false) { // This is not the first argument in the function declaration $arg = $tokens[$nextParam]['content']; if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); // Before we throw an error, make sure there is no type hint $comma = $phpcsFile->findPrevious(T_COMMA, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $comma + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between the hint and the variable as well $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = "Expected 1 space between type hint and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space between comma and type hint \"{$hint}\"; 0 found"; $phpcsFile->addError($error, $nextToken); } else { $gap = strlen($tokens[$comma + 1]['content']); if ($gap !== 1) { $error = "Expected 1 space between comma and type hint \"{$hint}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } else { if ($gap !== 1) { $error = "Expected 1 space between comma and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } else { $error = "Expected 1 space between comma and argument \"{$arg}\"; 0 found"; $phpcsFile->addError($error, $nextToken); } } else { // First argument in function declaration if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint $bracket = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $bracket + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between the hint and the variable as well $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { $error = "Expected 1 space between type hint and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } if ($tokens[$bracket + 1]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$bracket + 1]['content']); $error = "Expected 0 spaces between opening bracket and type hint \"{$hint}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } else { $error = "Expected 0 spaces between opening bracket and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } $params[] = $nextParam; $nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket); } if (empty($params) === true) { // There are no parameters for this function if ($closeBracket - $openBracket !== 1) { $space = strlen($tokens[$closeBracket - 1]['content']); $error = "Expected 0 spaces between brackets of function declaration; {$space} found"; $phpcsFile->addError($error, $stackPtr); } } else { if ($tokens[$closeBracket - 1]['code'] === T_WHITESPACE) { $lastParam = array_pop($params); $arg = $tokens[$lastParam]['content']; $gap = strlen($tokens[$closeBracket - 1]['content']); $error = "Expected 0 spaces between argument \"{$arg}\" and closing bracket; {$gap} found"; $phpcsFile->addError($error, $closeBracket); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) { // JavaScript uses the plus operator for string concatenation as well // so we cannot accurately determine if it is a string concat or addition. // So just ignore it. return; } // If the & is a reference, then we don't want to check for brackets. if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) { return; } // There is one instance where brackets aren't needed, which involves // the minus sign being used to assign a negative number to a variable. if ($tokens[$stackPtr]['code'] === T_MINUS) { // Check to see if we are trying to return -n. $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_RETURN) { return; } $number = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) { $previous = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($previous !== false) { $isAssignment = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens); $isEquality = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$equalityTokens); $isComparison = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens); if ($isAssignment === true || $isEquality === true || $isComparison === true) { // This is a negative assignment or comparion. // We need to check that the minus and the number are // adjacent. if ($number - $stackPtr !== 1) { $error = 'No space allowed between minus sign and number'; $phpcsFile->addError($error, $stackPtr); } return; } } } } //end if $lastBracket = false; if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); foreach ($parenthesis as $bracket => $endBracket) { $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $bracket - 1, null, true); $prevCode = $tokens[$prevToken]['code']; if ($prevCode === T_ISSET) { // This operation is inside an isset() call, but has // no bracket of it's own. break; } if ($prevCode === T_STRING) { // We allow very simple operations to not be bracketed: // ceil($one / $two); $allowed = array(T_VARIABLE, T_LNUMBER, T_DNUMBER, T_STRING, T_WHITESPACE, T_THIS, T_OBJECT_OPERATOR); for ($prev = $stackPtr - 1; $prev > $bracket; $prev--) { if (in_array($tokens[$prev]['code'], $allowed) === true) { continue; } if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { $prev = $tokens[$prev]['parenthesis_opener']; } else { break; } } if ($prev !== $bracket) { break; } for ($next = $stackPtr + 1; $next < $endBracket; $next++) { if (in_array($tokens[$next]['code'], $allowed) === true) { continue; } if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { $next = $tokens[$next]['parenthesis_closer']; } else { break; } } if ($next !== $endBracket) { break; } } //end if if (in_array($prevCode, PHP_CodeSniffer_Tokens::$scopeOpeners) === true) { // This operation is inside an a control structure like FOREACH // or IF, but has no bracket of it's own. break; } if ($prevCode === T_OPEN_PARENTHESIS) { // These are two open parenthesis in a row. If the current // one doesn't enclose the operator, go to the previous one. if ($endBracket < $stackPtr) { continue; } } $lastBracket = $bracket; break; } //end foreach } //end if if ($lastBracket === false) { // It is not in a bracketed statement at all. $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true, null, true); if ($previousToken !== false) { // A list of tokens that indicate that the token is not // part of an arithmetic operation. $invalidTokens = array(T_COMMA, T_COLON, T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET); if (in_array($tokens[$previousToken]['code'], $invalidTokens) === false) { $error = 'Arithmetic operation must be bracketed'; $phpcsFile->addError($error, $stackPtr); } return; } } else { if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) { // There are a set of brackets in front of it that don't include it. $error = 'Arithmetic operation must be bracketed'; $phpcsFile->addError($error, $stackPtr); return; } else { // We are enclosed in a set of bracket, so the last thing to // check is that we are not also enclosed in square brackets // like this: ($array[$index + 1]), which is invalid. $brackets = array(T_OPEN_SQUARE_BRACKET, T_CLOSE_SQUARE_BRACKET); $squareBracket = $phpcsFile->findPrevious($brackets, $stackPtr - 1, $lastBracket); if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) { $closeSquareBracket = $phpcsFile->findNext($brackets, $stackPtr + 1); if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) { $error = 'Arithmetic operation must be bracketed'; $phpcsFile->addError($error, $stackPtr); } } return; } } //end if $lastAssignment = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $stackPtr, null, false, null, true); if ($lastAssignment !== false && $lastAssignment > $lastBracket) { $error = 'Arithmetic operation must be bracketed'; $phpcsFile->addError($error, $stackPtr); } }
/** * Processes this sniff, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being checked. * @param integer $stackPtr The position of the current token in the * stack passed in $tokens. * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Skip default values in function declarations. if ($tokens[$stackPtr]['code'] === T_EQUAL || $tokens[$stackPtr]['code'] === T_MINUS) { if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); $bracket = array_pop($parenthesis); if (isset($tokens[$bracket]['parenthesis_owner']) === true) { $function = $tokens[$bracket]['parenthesis_owner']; if ($tokens[$function]['code'] === T_FUNCTION) { return; } } } } if ($tokens[$stackPtr]['code'] === T_EQUAL) { // Skip for '=&' case. if (isset($tokens[$stackPtr + 1]) === true && $tokens[$stackPtr + 1]['code'] === T_BITWISE_AND) { return; } } if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { // If its not a reference, then we expect one space either side of the // bitwise operator. if (!$phpcsFile->isReference($stackPtr) && !$this->_isVariable($stackPtr, $tokens, $phpcsFile)) { // Check there is one space before the & operator. if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space before "&" operator; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeAmp'); } // Check there is one space after the & operator. if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space after "&" operator; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterAmp'); } } } else { if ($tokens[$stackPtr]['code'] === T_MINUS) { // Skip declaration of negative value in new array format; eg. $arr = [-1]. if ($tokens[$stackPtr - 1]['code'] === T_OPEN_SHORT_ARRAY) { return; } // Check minus spacing, but make sure we aren't just assigning // a minus value or returning one. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_RETURN) { // Just returning a negative value; eg. return -1. return; } if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$operators) === true) { // Just trying to operate on a negative value; eg. ($var * -1). return; } if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) { // Just trying to compare a negative value; eg. ($var === -1). return; } // A list of tokens that indicate that the token is not // part of an arithmetic operation. $invalidTokens = array(T_COMMA, T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET, T_DOUBLE_ARROW, T_COLON, T_INLINE_THEN, T_INLINE_ELSE, T_CASE); if (in_array($tokens[$prev]['code'], $invalidTokens) === true) { // Just trying to use a negative value; eg. myFunction($var, -2). return; } if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) { // Just trying to assign a negative value; eg. ($var = -1). return; } } $operator = $tokens[$stackPtr]['content']; if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space before \"{$operator}\"; 0 found"; $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore'); } if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space after \"{$operator}\"; 0 found"; $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter'); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $functionName = $phpcsFile->findNext(array(T_STRING), $stackPtr); $openBracket = $tokens[$stackPtr]['parenthesis_opener']; $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; $multiLine = $tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']; $nextParam = $openBracket; $params = array(); while (($nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket)) !== false) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextParam + 1, $closeBracket + 1, true); if ($nextToken === false) { break; } $nextCode = $tokens[$nextToken]['code']; if ($nextCode === T_EQUAL) { if ($tokens[$nextToken + 1]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$nextToken + 1]['content']); $arg = $tokens[$nextParam]['content']; if ($gap != 1) { $error = "Expected 1 space between default value and equals sign for argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } else { $error = "Expected 1 space between default value and equals sign for argument"; $phpcsFile->addError($error, $nextToken); } } // Find and check the comma (if there is one). $nextComma = $phpcsFile->findNext(T_COMMA, $nextParam + 1, $closeBracket); if ($nextComma !== false) { // Comma found. if ($tokens[$nextComma - 1]['code'] === T_WHITESPACE) { $space = strlen($tokens[$nextComma - 1]['content']); $arg = $tokens[$nextParam]['content']; $error = "Expected 0 spaces between argument \"{$arg}\" and comma; {$space} found"; $phpcsFile->addError($error, $nextToken); } } // Take references into account when expecting the // location of whitespace. if ($phpcsFile->isReference($nextParam - 1) === true) { $whitespace = $tokens[$nextParam - 2]; } else { $whitespace = $tokens[$nextParam - 1]; } if (empty($params) === false) { // This is not the first argument in the function declaration. $arg = $tokens[$nextParam]['content']; if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); // Before we throw an error, make sure there is no type hint. $comma = $phpcsFile->findPrevious(T_COMMA, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $comma + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1 && $multiLine === false) { $error = "Expected 1 space between type hint and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } if ($multiLine === false) { if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { $error = "Expected 1 space between comma and type hint \"{$hint}\"; 0 found"; $phpcsFile->addError($error, $nextToken); } else { $gap = strlen($tokens[$comma + 1]['content']); if ($gap !== 1) { $error = "Expected 1 space between comma and type hint \"{$hint}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } } elseif ($multiLine === false && $gap !== 1) { $error = "Expected 1 space between comma and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } //end if } else { $error = "Expected 1 space between comma and argument \"{$arg}\"; 0 found"; $phpcsFile->addError($error, $nextToken); } //end if } else { // First argument in function declaration. if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint. $bracket = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $bracket + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1 && $multiLine === false) { $error = "Expected 1 space between type hint and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } if ($multiLine === false && $tokens[$bracket + 1]['code'] === T_WHITESPACE) { $gap = strlen($tokens[$bracket + 1]['content']); if ($gap != 1) { $error = "Expected 1 space between opening bracket and type hint \"{$hint}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } elseif ($multiLine === false) { if ($gap != 1) { $error = "Expected 1 space between opening bracket and argument \"{$arg}\"; {$gap} found"; $phpcsFile->addError($error, $nextToken); } } } //end if } //end if $params[] = $nextParam; } //end while if (empty($params) === true) { // There are no parameters for this function. if ($closeBracket - $openBracket !== 1) { $space = strlen($tokens[$closeBracket - 1]['content']); $error = "Expected 0 spaces between brackets of function declaration; {$space} found"; $phpcsFile->addError($error, $stackPtr); } } else { // There should be exactly one space after the opening parenthesis if ($tokens[$openBracket + 1]['code'] !== T_WHITESPACE || strlen($tokens[$openBracket + 1]['content']) != 1) { // If the open bracket doesn't have a space after it and it's not the last thing on the line, throw an error if ($tokens[$openBracket + 1]['content'] != PHP_EOL) { $error = "Expected 1 space between the opening parenthesis and first argument"; $phpcsFile->addError($error, $openBracket); } } // There should be exactly one space or a newline before the closing // parenthesis (todo: check for proper indentation if newline) if ($tokens[$closeBracket - 1]['code'] !== T_WHITESPACE || strlen($tokens[$closeBracket - 1]['content']) != 1 && $tokens[$closeBracket - 2]['content'] !== PHP_EOL) { $firstOnLine = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closeBracket, true); // Don't throw an error if the closing parenthesis is the first thing on the line if ($firstOnLine != $closeBracket) { $error = "Expected 1 space between the last argument and the closing parenthesis"; $phpcsFile->addError($error, $closeBracket); } } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $functionName = $phpcsFile->findNext(array(T_STRING), $stackPtr); $openBracket = $tokens[$stackPtr]['parenthesis_opener']; $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; $multiLine = $tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']; $nextParam = $openBracket; $params = array(); while (($nextParam = $phpcsFile->findNext(T_VARIABLE, $nextParam + 1, $closeBracket)) !== false) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextParam + 1, $closeBracket + 1, true); if ($nextToken === false) { break; } $nextCode = $tokens[$nextToken]['code']; if ($nextCode === T_EQUAL) { // Check parameter default spacing. if ($nextToken - $nextParam > 1) { //$gap = strlen($tokens[($nextParam + 1)]['content']); //$arg = $tokens[$nextParam]['content']; //$error = "Expected 0 spaces between argument \"$arg\" and equals sign; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_SPACING_NOPSACE_BEFORE_EQUALS', array(), $nextToken); } if ($tokens[$nextToken + 1]['code'] === T_WHITESPACE && $tokens[$nextToken + 1]['content'] !== ' ') { //$gap = strlen($tokens[($nextToken + 1)]['content']); //$arg = $tokens[$nextParam]['content']; //$error = "Expected 1 space between default value and equals sign for argument \"$arg\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_SPACING_ONESPACE_AFTER_EQUALS', array(), $nextToken); } if ($tokens[$nextToken + 1]['code'] !== T_WHITESPACE) { //$arg = $tokens[$nextParam]['content']; //$error = "Expected 1 space between default value and equals sign for argument \"$arg\"; 0 found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_SPACING_ONESPACE_AFTER_EQUALS', array(), $nextToken); } } // Find and check the comma (if there is one). $nextComma = $phpcsFile->findNext(T_COMMA, $nextParam + 1, $closeBracket); if ($nextComma !== false) { // Comma found. if ($tokens[$nextComma - 1]['code'] === T_WHITESPACE) { //$space = strlen($tokens[($nextComma - 1)]['content']); //$arg = $tokens[$nextParam]['content']; //$error = "Expected 0 spaces between argument \"$arg\" and comma; $space found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_SPACING_NOSPACE_BEFORE_COMMA', array(), $nextToken); } } // Take references into account when expecting the // location of whitespace. if ($phpcsFile->isReference($nextParam - 1) === true) { $whitespace = $tokens[$nextParam - 2]; } else { $whitespace = $tokens[$nextParam - 1]; } if (empty($params) === false) { // This is not the first argument in the function declaration. $arg = $tokens[$nextParam]['content']; if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); // Before we throw an error, make sure there is no type hint. $comma = $phpcsFile->findPrevious(T_COMMA, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $comma + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { //$error = "Expected 1 space between type hint and argument \"$arg\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_AFTER_HINT', array(), $nextToken); } if ($multiLine === false) { if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { //$error = "Expected 1 space between comma and type hint \"$hint\"; 0 found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_COMMA_AND_HINT', array(), $nextToken); } else { $gap = strlen($tokens[$comma + 1]['content']); if ($gap !== 1) { //$error = "Expected 1 space between comma and type hint \"$hint\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_COMMA_AND_HINT', array(), $nextToken); } } } } else { if ($multiLine === false && $gap !== 1) { //$error = "Expected 1 space between comma and argument \"$arg\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_COMMA_AND_ARGUMENT', array(), $nextToken); } } //end if } else { //$error = "Expected 1 space between comma and argument \"$arg\"; 0 found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_COMMA_AND_ARGUMENT', array(), $nextToken); } //end if } else { // First argument in function declaration. if ($whitespace['code'] === T_WHITESPACE) { $gap = strlen($whitespace['content']); $arg = $tokens[$nextParam]['content']; // Before we throw an error, make sure there is no type hint. $bracket = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, $nextParam - 1); $nextToken = $phpcsFile->findNext(T_WHITESPACE, $bracket + 1, null, true); if ($phpcsFile->isReference($nextToken) === true) { $nextToken++; } if ($nextToken !== $nextParam) { // There was a type hint, so check the spacing between // the hint and the variable as well. $hint = $tokens[$nextToken]['content']; if ($gap !== 1) { //$error = "Expected 1 space between type hint and argument \"$arg\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_AFTER_HINT', array(), $nextToken); } if ($multiLine === false && $tokens[$bracket + 1]['code'] === T_WHITESPACE) { //$gap = strlen($tokens[($bracket + 1)]['content']); //$error = "Expected 0 spaces between opening bracket and type hint \"$hint\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_BRACKET_AND_HINT', array(), $nextToken); } } else { if ($multiLine === false) { //$error = "Expected 0 spaces between opening bracket and argument \"$arg\"; $gap found"; //$phpcsFile->addError($error, $nextToken); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_BRACKET_AND_ARGUMENT', array(), $nextToken); } } } //end if } //end if $params[] = $nextParam; } //end while if (empty($params) === true) { // There are no parameters for this function. if ($closeBracket - $openBracket !== 1) { //$space = strlen($tokens[($closeBracket - 1)]['content']); //$error = "Expected 0 spaces between brackets of function declaration; $space found"; //$phpcsFile->addError($error, $stackPtr); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_ONESPACE_BETWEEN_BRACKETS', array(), $stackPtr); } } else { if ($multiLine === false && $tokens[$closeBracket - 1]['code'] === T_WHITESPACE) { //$lastParam = array_pop($params); //$arg = $tokens[$lastParam]['content']; //$gap = strlen($tokens[($closeBracket - 1)]['content']); //$error = "Expected 0 spaces between argument \"$arg\" and closing bracket; $gap found"; //$phpcsFile->addError($error, $closeBracket); $phpcsFile->addEvent('XP_FUNCTION_DECLARATION_ARGUMENT_NOSPACE_BETWEEN_ARGUMENT_AND_CLOSING_BRACKET', array(), $closeBracket); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $constName = $tokens[$stackPtr]['content']; // If this token is in a heredoc, ignore it. if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) { return; } // If the next non-whitespace token after this token // is not an opening parenthesis then it is not a function call. $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { $functionKeyword = $phpcsFile->findPrevious(array(T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING), ($stackPtr - 1), null, true); $declarations = array( T_FUNCTION, T_CLASS, T_INTERFACE, T_IMPLEMENTS, T_EXTENDS, T_INSTANCEOF, T_NEW, ); if (in_array($tokens[$functionKeyword]['code'], $declarations) === true) { // This is just a declaration; no constants here. return; } if ($tokens[$functionKeyword]['code'] === T_CONST) { // This is a class constant. if (strtoupper($constName) !== $constName) { $error = 'Class constants must be uppercase; expected '.strtoupper($constName)." but found $constName"; $phpcsFile->addError($error, $stackPtr, 'ClassConstantNotUpperCase'); } return; } // Is this a class name? $nextPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); if ($tokens[$nextPtr]['code'] === T_DOUBLE_COLON) { return; } // Is this a type hint? if ($tokens[$nextPtr]['code'] === T_VARIABLE) { return; } else if ($phpcsFile->isReference($nextPtr) === true) { return; } // Is this a member var name? $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) { return; } // Is this an instance of declare() $prevPtr = $phpcsFile->findPrevious(array(T_WHITESPACE, T_OPEN_PARENTHESIS), ($stackPtr - 1), null, true); if ($tokens[$prevPtr]['code'] === T_DECLARE) { return; } // This is a real constant. if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected '.strtoupper($constName)." but found $constName"; $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase'); } } else if (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { /* This may be a "define" or "constant" function call. */ // Make sure this is not a method call. $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR) { return; } // The next non-whitespace token must be the constant name. $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $constName = $tokens[$constPtr]['content']; if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected '.strtoupper($constName)." but found $constName"; $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase'); } }//end if }//end process()
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $constName = $tokens[$stackPtr]['content']; $constNameUpper = strtoupper($constName); // If this token is in a heredoc, ignore it. if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) { return; } // Special case for PHPUnit. if ($constName === 'PHPUnit_MAIN_METHOD') { return; } // If the next non-whitespace token after this token // is not an opening parenthesis then it is not a function call. $openBracket = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { if ($constNameUpper == $constName) { return; } $functionKeyword = $phpcsFile->findPrevious(array(T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING), $stackPtr - 1, null, true); switch ($tokens[$functionKeyword]['code']) { case T_FUNCTION: case T_CLASS: case T_INTERFACE: case T_IMPLEMENTS: case T_EXTENDS: case T_INSTANCEOF: case T_NEW: case T_NAMESPACE: case T_USE: case T_AS: // This is just a declaration; no constants here. return; } if (version_compare(PHP_VERSION, '5.4.0') >= 0) { switch ($tokens[$functionKeyword]['code']) { case T_TRAIT: return; } } if ($tokens[$functionKeyword]['code'] === T_CONST) { // This is a class constant. $error = 'Class constants must be uppercase; expected %s but found %s'; $data = array($constNameUpper, $constName); $phpcsFile->addError($error, $stackPtr, 'ClassConstantNotUpperCase', $data); return; } // Is this a class name? $nextPtr = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); switch ($tokens[$nextPtr]['code']) { // Is this a class name? case T_DOUBLE_COLON: // Is this a namespace name? // Is this a namespace name? case T_NS_SEPARATOR: // Is this a goto label? // Is this a goto label? case T_COLON: return; } // Is this a type hint? if ($tokens[$nextPtr]['code'] === T_VARIABLE || $phpcsFile->isReference($nextPtr) === true) { return; } $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); switch ($tokens[$prevPtr]['code']) { // Is this a member var name? case T_OBJECT_OPERATOR: // Is this a namespace name? // Is this a namespace name? case T_NS_SEPARATOR: // Is this a goto jump? // Is this a goto jump? case T_GOTO: return; } // Is this an instance of declare() $prevPtr = $phpcsFile->findPrevious(array(T_WHITESPACE, T_OPEN_PARENTHESIS), $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_DECLARE) { return; } // Are we inside an import of namespace? if (($prevPtr = $phpcsFile->findPrevious(T_USE, $stackPtr - 1, null)) !== false && ($nextPtr = $phpcsFile->findNext(T_SEMICOLON, $prevPtr + 1, null)) !== false && $prevPtr < $stackPtr && $nextPtr > $stackPtr) { return; } // This is a real constant. $error = 'Constants must be uppercase; expected %s but found %s'; $data = array($constNameUpper, $constName); $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } else { if (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { /* This may be a "define" or "constant" function call. */ // Make sure this is not a method call. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR) { return; } // The next non-whitespace token must be the constant name. $constPtr = $phpcsFile->findNext(T_WHITESPACE, $openBracket + 1, null, true); if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $constName = $tokens[$constPtr]['content']; if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected %s but found %s'; $data = array(strtoupper($constName), $constName); $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } } } //end if }
/** * Processes this test, when one of its tokens is encountered. * * @param CodeSnifferFile $file The file being scanned. * @param integer $stackPtr The position of the current token in the stack passed in $tokens. * @return null */ public function process(CodeSnifferFile $file, $stackPtr) { $tokens = $file->getTokens(); $constName = $tokens[$stackPtr]['content']; // If this token is in a heredoc, ignore it. if ($file->hasCondition($stackPtr, T_START_HEREDOC) === true) { return; } $previousNonStringPtr = $file->findPrevious([T_STRING, T_WHITESPACE, T_CONST, T_NS_SEPARATOR, T_FUNCTION], $stackPtr - 1, null, true); if ($tokens[$previousNonStringPtr]['code'] === T_USE) { return; } // Special case for PHPUnit. if ($constName === 'PHPUnit_MAIN_METHOD') { return; } if ($constName === 'class') { return; } // If the next non-whitespace token after this token // is not an opening parenthesis then it is not a function call. $openBracket = $file->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { $functionKeyword = $file->findPrevious([T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING, T_NS_SEPARATOR], $stackPtr - 1, null, true); $declarations = [T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT, T_IMPLEMENTS, T_EXTENDS, T_INSTANCEOF, T_NEW, T_NAMESPACE, T_USE, T_AS, T_GOTO, T_INSTEADOF]; if (in_array($tokens[$functionKeyword]['code'], $declarations) === true) { // This is just a declaration; no constants here. return; } if ($tokens[$functionKeyword]['code'] === T_CONST) { $class = $file->findPrevious(T_CLASS, $stackPtr - 1, null, false, null); $className = $file->findNext(T_STRING, $class + 1, null, false, null, true); if ($this->isEventClassName($tokens[$className]['content'])) { if (!$this->isValidEventConstName($constName)) { $error = 'Class constants for event types must be camelcase and start with ' . '"on", "before" or "after". Found %s'; $file->addError($error, $stackPtr, 'EventClassConstantNotCamelCase', [$constName]); } return; } // This is a class constant. if (strtoupper($constName) !== $constName) { $error = 'Class constants must be uppercase; expected %s but found %s'; $data = [strtoupper($constName), $constName]; $file->addError($error, $stackPtr, 'ClassConstantNotUpperCase', $data); } return; } // Is this a class name? $nextPtr = $file->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$nextPtr]['code'] === T_DOUBLE_COLON) { return; } // Is this a namespace name? if ($tokens[$nextPtr]['code'] === T_NS_SEPARATOR) { return; } // Is it the first part of a trait use statement with aliasing ("foo" in foo as bar)? if ($tokens[$nextPtr]['code'] === T_AS) { return; } // Is it the second part of a trait use statement with aliasing ("bar" in foo as bar)? $prevPtr = $file->findPrevious([T_WHITESPACE, T_PUBLIC, T_PRIVATE, T_PROTECTED], $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_AS) { return; } // Is this an insteadof name? if ($tokens[$nextPtr]['code'] === T_INSTEADOF) { return; } // Is this a type hint? if ($tokens[$nextPtr]['code'] === T_VARIABLE || $file->isReference($nextPtr) === true) { return; } // Is this a member var name? $prevPtr = $file->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) { return; } // Is this a variable name, in the form ${varname} ? if ($tokens[$prevPtr]['code'] === T_OPEN_CURLY_BRACKET) { $nextPtr = $file->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$nextPtr]['code'] === T_CLOSE_CURLY_BRACKET) { return; } } // Is this a namespace name? if ($tokens[$prevPtr]['code'] === T_NS_SEPARATOR) { return; } // Is this an instance of declare() $prevPtrDeclare = $file->findPrevious([T_WHITESPACE, T_OPEN_PARENTHESIS], $stackPtr - 1, null, true); if ($tokens[$prevPtrDeclare]['code'] === T_DECLARE) { return; } // Is this a goto label target? if ($tokens[$nextPtr]['code'] === T_COLON) { if (in_array($tokens[$prevPtr]['code'], [T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_COLON], true)) { return; } } $className = $file->findPrevious(T_STRING, $stackPtr - 1, null, false, null, true); if ($this->isEventClassName($tokens[$className]['content'])) { if (!$this->isEventClassName($tokens[$className]['content'])) { if (!$this->isValidEventConstName($constName)) { $error = 'Class constants for event types must be camelcase and start with ' . '"on", "before" or "after". Found %s'; $file->addError($error, $stackPtr, 'EventClassConstantNotCamelCase', [$constName]); } } return; } // This is a real constant. if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected %s but found %s'; $data = [strtoupper($constName), $constName]; $file->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } } elseif (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { /* This may be a "define" or "constant" function call. */ // Make sure this is not a method call. $prev = $file->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR || $tokens[$prev]['code'] === T_DOUBLE_COLON) { return; } // The next non-whitespace token must be the constant name. $constPtr = $file->findNext(T_WHITESPACE, $openBracket + 1, null, true); if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $constName = $tokens[$constPtr]['content']; // Check for constants like self::CONSTANT. $prefix = ''; $splitPos = strpos($constName, '::'); if ($splitPos !== false) { $prefix = substr($constName, 0, $splitPos + 2); $constName = substr($constName, $splitPos + 2); } if (strtoupper($constName) !== $constName) { $error = 'Constants must be uppercase; expected %s but found %s'; $data = [$prefix . strtoupper($constName), $prefix . $constName]; $file->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $constName = $tokens[$stackPtr]['content']; // If this token is in a heredoc, ignore it. if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) { return; } // If the next non-whitespace token after this token // is not an opening parenthesis then it is not a function call. $openBracket = $phpcsFile->findNext(array(T_WHITESPACE), $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { $functionKeyword = $phpcsFile->findPrevious(array(T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING), $stackPtr - 1, null, true); $declarations = array(T_FUNCTION, T_CLASS, T_INTERFACE, T_IMPLEMENTS, T_EXTENDS, T_INSTANCEOF, T_NEW); if (in_array($tokens[$functionKeyword]['code'], $declarations) === true) { // This is just a declaration; no constants here. return; } if ($tokens[$functionKeyword]['code'] === T_CONST) { // This is a class constant - do not check return; } if ($tokens[$stackPtr - 1]['code'] == T_NS_SEPARATOR || $tokens[$stackPtr + 1]['code'] == T_NS_SEPARATOR || $tokens[$stackPtr - 2]['code'] == T_NAMESPACE) { // This is a namespace prefix return; } // Is this a class name? $nextPtr = $phpcsFile->findNext(array(T_WHITESPACE), $stackPtr + 1, null, true); if ($tokens[$nextPtr]['code'] === T_DOUBLE_COLON) { return; } // Is this a type hint? if ($tokens[$nextPtr]['code'] === T_VARIABLE || $phpcsFile->isReference($nextPtr) === true) { return; } // Is this a member var name? $prevPtr = $phpcsFile->findPrevious(array(T_WHITESPACE), $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) { return; } // Is this an instance of declare() $prevPtr = $phpcsFile->findPrevious(array(T_WHITESPACE, T_OPEN_PARENTHESIS), $stackPtr - 1, null, true); if ($tokens[$prevPtr]['code'] === T_DECLARE) { return; } if ($tokens[$stackPtr - 1]['code'] == T_PAAMAYIM_NEKUDOTAYIM) { return; } // This is a real constant. $this->checkConstant($constName, $phpcsFile, $stackPtr); } else { if (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { /* This may be a "define" or "constant" function call. */ // The next non-whitespace token must be the constant name. $constPtr = $phpcsFile->findNext(array(T_WHITESPACE), $openBracket + 1, null, true); if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $constName = substr($tokens[$constPtr]['content'], 1, -1); $this->checkConstant($constName, $phpcsFile, $stackPtr); } } //end if }