It provides a means for traversing the token stack, along with other token related operations. If a PHP_CodeSniffer_Sniff finds and error or warning within a PHP_CodeSniffer_File, you can raise an error using the addError() or addWarning() methods. Token Information Each token within the stack contains information about itself: array( 'code' => 301, // the token type code (see token_get_all()) 'content' => 'if', // the token content 'type' => 'T_IF', // the token name 'line' => 56, // the line number when the token is located 'column' => 12, // the column in the line where this token starts (starts from 1) 'level' => 2 // the depth a token is within the scopes open 'conditions' => array( // a list of scope condition token positions => codes that 2 => 50, // opened the scopes that this token exists 9 => 353, // in (see conditional tokens section below) ), ); Conditional Tokens In addition to the standard token fields, conditions contain information to determine where their scope begins and ends: array( 'scope_condition' => 38, // the token position of the condition 'scope_opener' => 41, // the token position that started the scope 'scope_closer' => 70, // the token position that ended the scope ); The condition, the scope opener and the scope closer each contain this information. Parenthesis Tokens Each parenthesis token (T_OPEN_PARENTHESIS and T_CLOSE_PARENTHESIS) has a reference to their opening and closing parenthesis, one being itself, the other being its opposite. array( 'parenthesis_opener' => 34, 'parenthesis_closer' => 40, ); Some tokens can "own" a set of parenthesis. For example a T_FUNCTION token has parenthesis around its argument list. These tokens also have the parenthesis_opener and and parenthesis_closer indices. Not all parenthesis have owners, for example parenthesis used for arithmetic operations and function calls. The parenthesis tokens that have an owner have the following auxiliary array indices. array( 'parenthesis_opener' => 34, 'parenthesis_closer' => 40, 'parenthesis_owner' => 33, ); Each token within a set of parenthesis also has an array index 'nested_parenthesis' which is an array of the left parenthesis => right parenthesis token positions. 'nested_parenthesis' => array( 12 => 15 11 => 14 ); Extended Tokens PHP_CodeSniffer extends and augments some of the tokens created by token_get_all(). A full list of these tokens can be seen in the Tokens.php file.
Author: Greg Sherwood (gsherwood@squiz.net)
Author: Marc McIntyre (mmcintyre@squiz.net)
Example #1
0
 /**
  * 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
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $content = $tokens[$stackPtr]["content"];
     $recommendations = array("!=" => "!==", "==" => "===");
     $phpcsFile->addWarning($this->getReqPrefix("WRN.JS.3.13.3") . "Use '" . $recommendations[$content] . "' instead of '{$content}'", $stackPtr);
 }
 /**
  * Processes this sniff, 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)
 {
     $fileName = $phpcsFile->getFilename();
     $matches = array();
     if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) {
         // Not an actions file.
         return;
     }
     $ownClass = $matches[2];
     $tokens = $phpcsFile->getTokens();
     $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, $stackPtr + 2, null, false, true);
     $typeName = trim($tokens[$typeName]['content'], " '");
     switch (strtolower($tokens[$stackPtr + 1]['content'])) {
         case 'includesystem':
             $included = strtolower($typeName);
             break;
         case 'includeasset':
             $included = strtolower($typeName) . 'assettype';
             break;
         case 'includewidget':
             $included = strtolower($typeName) . 'widgettype';
             break;
         default:
             return;
     }
     if ($included === strtolower($ownClass)) {
         $error = "You do not need to include \"%s\" from within the system's own actions file";
         $data = array($ownClass);
         $phpcsFile->addError($error, $stackPtr, 'NotRequired', $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();
     $token = $tokens[$stackPtr];
     // Skip invalid statement.
     if (isset($token['parenthesis_opener']) === false) {
         return;
     }
     $next = ++$token['parenthesis_opener'];
     $end = --$token['parenthesis_closer'];
     $parts = array(0, 0, 0);
     $index = 0;
     for (; $next <= $end; ++$next) {
         $code = $tokens[$next]['code'];
         if ($code === T_SEMICOLON) {
             ++$index;
         } else {
             if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                 ++$parts[$index];
             }
         }
     }
     if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) {
         $error = 'This FOR loop can be simplified to a WHILE loop';
         $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify');
     }
 }
Example #4
0
 /**
  * Processes this sniff, 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)
 {
     // We are only interested if this is the first open tag.
     if ($stackPtr !== 0) {
         if ($phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1) !== false) {
             return;
         }
     }
     $found = $phpcsFile->eolChar;
     $found = str_replace("\n", '\\n', $found);
     $found = str_replace("\r", '\\r', $found);
     if ($found !== $this->eolChar) {
         // Check for single line files without an EOL. This is a very special
         // case and the EOL char is set to \n when this happens.
         if ($found === '\\n') {
             $tokens = $phpcsFile->getTokens();
             $lastToken = $phpcsFile->numTokens - 1;
             if ($tokens[$lastToken]['line'] === 1 && $tokens[$lastToken]['content'] !== "\n") {
                 return;
             }
         }
         $error = 'End of line character is invalid; expected "%s" but found "%s"';
         $expected = $this->eolChar;
         $expected = str_replace("\n", '\\n', $expected);
         $expected = str_replace("\r", '\\r', $expected);
         $data = array($expected, $found);
         $phpcsFile->addError($error, $stackPtr, 'InvalidEOLChar', $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();
     if (isset($tokens[$stackPtr]['scope_opener']) === false) {
         // Probably an interface method.
         return;
     }
     $openBrace = $tokens[$stackPtr]['scope_opener'];
     $nextContent = $phpcsFile->findNext(T_WHITESPACE, $openBrace + 1, null, true);
     if ($nextContent === $tokens[$stackPtr]['scope_closer']) {
         // The next bit of content is the closing brace, so this
         // is an empty function and should have a blank line
         // between the opening and closing braces.
         return;
     }
     $braceLine = $tokens[$openBrace]['line'];
     $nextLine = $tokens[$nextContent]['line'];
     $found = $nextLine - $braceLine - 1;
     if ($found > 0) {
         $error = 'Expected 0 blank lines after opening function brace; %s found';
         $data = array($found);
         $fix = $phpcsFile->addFixableError($error, $openBrace, 'SpacingAfter', $data);
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             for ($i = $openBrace + 1; $i < $nextContent; $i++) {
                 if ($tokens[$i]['line'] === $nextLine) {
                     break;
                 }
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->addNewline($openBrace);
             $phpcsFile->fixer->endChangeset();
         }
     }
 }
 /**
  * Processes this function call.
  *
  * @param PHP_CodeSniffer_File $phpcsFile
  *   The file being scanned.
  * @param int $stackPtr
  *   The position of the function call in the stack.
  * @param int $openBracket
  *   The position of the opening parenthesis in the stack.
  * @param int $closeBracket
  *   The position of the closing parenthesis in the stack.
  * @param Drupal_Sniffs_Semantics_FunctionCallSniff $sniff
  *   Can be used to retreive the function's arguments with the getArgument()
  *   method.
  *
  * @return void
  */
 public function processFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $closeBracket, Drupal_Sniffs_Semantics_FunctionCallSniff $sniff)
 {
     $tokens = $phpcsFile->getTokens();
     // We assume that the sequence '#default_value' => variable_get(...)
     // indicates a variable that the module owns.
     $arrow = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true);
     if ($arrow === false || $tokens[$arrow]['code'] !== T_DOUBLE_ARROW) {
         return;
     }
     $arrayKey = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrow - 1, null, true);
     if ($arrayKey === false || $tokens[$arrayKey]['code'] !== T_CONSTANT_ENCAPSED_STRING || substr($tokens[$arrayKey]['content'], 1, -1) !== '#default_value') {
         return;
     }
     $argument = $sniff->getArgument(1);
     // Variable name is not a literal string, so we return early.
     if ($argument === false || $tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
         return;
     }
     $moduleName = DrupalPractice_Project::getName($phpcsFile);
     if ($moduleName === false) {
         return;
     }
     $variableName = substr($tokens[$argument['start']]['content'], 1, -1);
     if (strpos($variableName, $moduleName) !== 0) {
         $warning = 'All variables defined by your module must be prefixed with your module\'s name to avoid name collisions with others. Expected start with "%s" but found "%s"';
         $data = array($moduleName, $variableName);
         $phpcsFile->addWarning($warning, $argument['start'], 'VariableName', $data);
     }
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The current file being processed.
  * @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();
     $start = $tokens[$stackPtr]['scope_opener'];
     $end = $tokens[$stackPtr]['scope_closer'];
     $properties = array();
     $wantedTokens = array(T_PROPERTY, T_OPEN_CURLY_BRACKET);
     $next = $phpcsFile->findNext($wantedTokens, $start + 1, $end);
     while ($next !== false && $next < $end) {
         // Skip nested objects.
         if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) {
             $next = $tokens[$next]['bracket_closer'];
         } else {
             $propName = $tokens[$next]['content'];
             if (isset($properties[$propName]) === true) {
                 $line = $tokens[$properties[$propName]]['line'];
                 $error = "Duplicate property definition found for \"{$propName}\"; previously defined on line {$line}";
                 $phpcsFile->addError($error, $next);
             }
             $properties[$propName] = $next;
         }
         //end if
         $next = $phpcsFile->findNext($wantedTokens, $next + 1, $end);
     }
     //end while
 }
 /**
  * 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
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $utils = Security_Sniffs_UtilsFactory::getInstance();
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr]['content'] == 'preg_replace') {
         $s = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr);
         $closer = $tokens[$s]['parenthesis_closer'];
         $s = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $s + 1, $closer, true);
         if ($tokens[$s]['code'] == T_CONSTANT_ENCAPSED_STRING) {
             $pattern = $tokens[$s]['content'];
             if (substr($pattern, 1, 1) === '/') {
                 // $pattern is a regex
                 if (preg_match('/(\\/|\\))\\w*e\\w*"$/', $pattern)) {
                     $phpcsFile->addWarning("Usage of preg_replace with /e modifier is not recommended.", $stackPtr, 'PregReplaceE');
                     $s = $phpcsFile->findNext(array(T_COMMA, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT), $s + 1, $closer, true);
                     if ($utils::is_token_user_input($tokens[$s])) {
                         $phpcsFile->addError("User input and /e modifier found in preg_replace, remote code execution possible.", $stackPtr, 'PregReplaceUserInputE');
                     }
                 }
             } else {
                 $phpcsFile->addWarning("Weird usage of preg_replace, please check manually for /e modifier.", $stackPtr, 'PregReplaceWeird');
             }
         } elseif ($tokens[$s]['code'] == T_VARIABLE && $utils::is_token_user_input($tokens[$s])) {
             $phpcsFile->addError("User input found in preg_replace, /e modifier could be used for malicious intent.", $stackPtr, 'PregReplaceUserInput');
         } else {
             $phpcsFile->addWarning("Dynamic usage of preg_replace, please check manually for /e modifier or user input.", $stackPtr, 'PregReplaceDyn');
         }
     }
 }
 /**
  * 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();
     $token = $tokens[$stackPtr];
     // Skip for-loop without body.
     if (isset($token['parenthesis_opener']) === false) {
         return;
     }
     $next = ++$token['parenthesis_opener'];
     $end = --$token['parenthesis_closer'];
     $goodCondition = false;
     for (; $next <= $end; ++$next) {
         $code = $tokens[$next]['code'];
         if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$code]) === true) {
             continue;
         } else {
             if ($code !== T_TRUE && $code !== T_FALSE) {
                 $goodCondition = true;
             }
         }
     }
     if ($goodCondition === false) {
         $error = 'Avoid IF statements that are always true or false';
         $phpcsFile->addWarning($error, $stackPtr, 'Found');
     }
 }
 /**
  * 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 (isset($tokens[$stackPtr]['scope_opener']) === false) {
         // Ignore the ELSE in ELSE IF. We'll process the IF part later.
         if ($tokens[$stackPtr]['code'] === T_ELSE && $tokens[$stackPtr + 2]['code'] === T_IF) {
             return;
         }
         if ($tokens[$stackPtr]['code'] === T_WHILE) {
             // This could be from a DO WHILE, which doesn't have an opening brace.
             $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
             if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
                 $brace = $tokens[$lastContent];
                 if (isset($brace['scope_condition']) === true) {
                     $condition = $tokens[$brace['scope_condition']];
                     if ($condition['code'] === T_DO) {
                         return;
                     }
                 }
             }
         }
         // This is a control structure without an opening brace,
         // so it is an inline statement.
         if ($this->error === true) {
             $phpcsFile->addError('Inline control structures are not allowed', $stackPtr);
         } else {
             $phpcsFile->addWarning('Inline control structures are discouraged', $stackPtr);
         }
         return;
     }
     //end if
 }
Example #11
0
 /**
  * Processes this sniff, 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();
     // Make sure this file only contains PHP code.
     for ($i = 0; $i < $phpcsFile->numTokens; $i++) {
         if ($tokens[$i]['code'] === T_INLINE_HTML && trim($tokens[$i]['content']) !== '') {
             return $phpcsFile->numTokens;
         }
     }
     // Find the last non-empty token.
     for ($last = $phpcsFile->numTokens - 1; $last > 0; $last--) {
         if (trim($tokens[$last]['content']) !== '') {
             break;
         }
     }
     if ($tokens[$last]['code'] === T_CLOSE_TAG) {
         $error = 'A closing tag is not permitted at the end of a PHP file';
         $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed');
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($last, '');
         }
         $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'yes');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'no');
     }
     // Ignore the rest of the file.
     return $phpcsFile->numTokens;
 }
 /**
  * Processes the tokens that this sniff is interested in.
  *
  * @param PHP_CodeSniffer_File $phpcsFile File where the token was found
  * @param int $stackPtr Position in the stack where the token was found
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr, null, false, null, true);
     if ($open !== false && $phpcsFile->getTokensAsString($open, 2) == '()') {
         $phpcsFile->addError('Parentheses should not be used in calls to class constructors without parameters', $stackPtr);
     }
 }
 /**
  * Run whenever a '.' is encountered
  *
  * @param PHP_CodeSniffer_File $file The file being scanned.
  * @param int $stack_ix The position of the current token in the stack
  */
 public function process(PHP_CodeSniffer_File $file, $stack_ix)
 {
     $tokens = $file->getTokens();
     if ($tokens[$stack_ix - 1]['code'] !== T_WHITESPACE || $tokens[$stack_ix + 1]['code'] !== T_WHITESPACE) {
         $file->addError('Concat operator must be surrounded by spaces', $stack_ix, 'ConcatUnspaced');
     }
 }
Example #14
0
 /**
  * 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
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $lastLine = $tokens[$stackPtr]['line'];
     $end = $tokens[$stackPtr]['bracket_closer'];
     $endLine = $tokens[$end]['line'];
     // Do not check nested style definitions as, for example, in @media style rules.
     $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr + 1, $end);
     if ($nested !== false) {
         return;
     }
     $foundColon = false;
     $foundString = false;
     for ($i = $stackPtr + 1; $i <= $end; $i++) {
         if ($tokens[$i]['line'] !== $lastLine) {
             // We changed lines.
             if ($foundColon === false && $foundString !== false) {
                 // We didn't find a colon on the previous line.
                 $error = 'No style definition found on line; check for missing colon';
                 $phpcsFile->addError($error, $foundString, 'Found');
             }
             $foundColon = false;
             $foundString = false;
             $lastLine = $tokens[$i]['line'];
         }
         if ($tokens[$i]['code'] === T_STRING) {
             $foundString = $i;
         } else {
             if ($tokens[$i]['code'] === T_COLON) {
                 $foundColon = $i;
             }
         }
     }
     //end for
 }
 /**
  * Processes class member variables.
  *
  * @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
  */
 protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $memberProps = $phpcsFile->getMemberProperties($stackPtr);
     if (empty($memberProps) === true) {
         return;
     }
     $memberName = ltrim($tokens[$stackPtr]['content'], '$');
     $isPublic = $memberProps['scope'] === 'private' ? false : true;
     $scope = $memberProps['scope'];
     $scopeSpecified = $memberProps['scope_specified'];
     // If it's a private member, it must have an underscore on the front.
     if ($isPublic === false && $memberName[0] !== '_') {
         $error = 'Private member variable "%s" must be prefixed with an underscore';
         $data = array($memberName);
         $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data);
         return;
     }
     // If it's not a private member, it must not have an underscore on the front.
     if ($isPublic === true && $scopeSpecified === true && $memberName[0] === '_') {
         $error = '%s member variable "%s" must not be prefixed with an underscore';
         $data = array(ucfirst($scope), $memberName);
         $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data);
         return;
     }
 }
 /**
  * @inheritdoc
  */
 public function process(\PHP_CodeSniffer_File $phpCsFile, $stackPointer)
 {
     $tokens = $phpCsFile->getTokens();
     $level = $tokens[$stackPointer]['level'];
     if ($level < 1) {
         return;
     }
     $openingBraceIndex = $phpCsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPointer + 1);
     if (!$openingBraceIndex) {
         $openingParenthesisIndex = $phpCsFile->findNext(T_OPEN_PARENTHESIS, $stackPointer + 1);
         $closingParenthesisIndex = $tokens[$openingParenthesisIndex]['parenthesis_closer'];
         $semicolonIndex = $phpCsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $closingParenthesisIndex + 1, null, true);
         $nextContentIndex = $phpCsFile->findNext(T_WHITESPACE, $semicolonIndex + 1, null, true);
         if ($tokens[$nextContentIndex]['line'] - $tokens[$semicolonIndex]['line'] <= 1) {
             $fix = $phpCsFile->addFixableError('Every function/method needs a newline afterwards', $closingParenthesisIndex, 'Abstract');
             if ($fix) {
                 $phpCsFile->fixer->addNewline($semicolonIndex);
             }
         }
         return;
     }
     $closingBraceIndex = $tokens[$openingBraceIndex]['scope_closer'];
     // Ignore closures
     $nextIndex = $phpCsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $closingBraceIndex + 1, null, true);
     if (in_array($tokens[$nextIndex]['content'], [';', ',', ')'])) {
         return;
     }
     $nextContentIndex = $phpCsFile->findNext(T_WHITESPACE, $closingBraceIndex + 1, null, true);
     if (!$nextContentIndex || $tokens[$nextContentIndex]['line'] - $tokens[$closingBraceIndex]['line'] <= 1) {
         $fix = $phpCsFile->addFixableError('Every function/method needs a newline afterwards', $closingBraceIndex, 'Concrete');
         if ($fix) {
             $phpCsFile->fixer->addNewline($closingBraceIndex);
         }
     }
 }
 /**
  * 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();
     $operator = $tokens[$stackPtr]['content'];
     $previousToken = $tokens[$stackPtr - 1];
     $nextToken = $tokens[$stackPtr + 1];
     $previousSpaces = $previousToken['code'] === T_WHITESPACE ? strlen($previousToken['content']) : 0;
     $nextSpaces = $nextToken['code'] === T_WHITESPACE ? strlen($nextToken['content']) : 0;
     $previousNonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
     $previousSplitsLine = $tokens[$previousNonEmpty]['line'] !== $tokens[$stackPtr]['line'];
     $nextNonEmpty = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     $nextSplitsLine = $tokens[$nextNonEmpty]['line'] !== $tokens[$stackPtr]['line'];
     if (DWS_Helpers_Operator::isUnary($phpcsFile, $stackPtr)) {
         if (!$previousSplitsLine && $previousSpaces !== 1 && !in_array($tokens[$previousNonEmpty]['code'], [T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY])) {
             $phpcsFile->addError('Expected 1 space before "%s"; %s found', $stackPtr, 'SpacingBefore', [$operator, $previousSpaces]);
         }
         if ($nextSpaces !== 0) {
             $phpcsFile->addError('Expected 0 spaces after "%s"; %s found', $stackPtr, 'SpacingAfterUnary', [$operator, $nextSpaces]);
         }
     } else {
         if ($tokens[$stackPtr]['code'] === T_INLINE_ELSE && $tokens[$previousNonEmpty]['code'] === T_INLINE_THEN) {
             if ($previousSpaces !== 0) {
                 $phpcsFile->addError('Expected 0 spaces inside "?:"; %s found', $stackPtr, 'SpacingInTernary', [$previousSpaces]);
             }
         } elseif (!$previousSplitsLine && $previousSpaces !== 1) {
             $phpcsFile->addError('Expected 1 space before "%s"; %s found', $stackPtr, 'SpacingBefore', [$operator, $previousSpaces]);
         }
         $isTernaryShortcut = $tokens[$stackPtr]['code'] === T_INLINE_THEN && $tokens[$nextNonEmpty]['code'] === T_INLINE_ELSE;
         if (!$isTernaryShortcut && !$nextSplitsLine && $nextSpaces !== 1) {
             $phpcsFile->addError('Expected 1 space after "%s"; %s found', $stackPtr, 'SpacingAfter', [$operator, $nextSpaces]);
         }
     }
 }
 /**
  * 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();
     $firstContent = $phpcsFile->findNext(array(T_WHITESPACE), $stackPtr + 1, null, true);
     // If the first non-whitespace token is not an opening parenthesis, then we are not concerned.
     if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) {
         $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no');
         return;
     }
     $end = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_TAG), $stackPtr, null, false);
     // If the token before the semi-colon is not a closing parenthesis, then we are not concerned.
     $prev = $phpcsFile->findPrevious(T_WHITESPACE, $end - 1, null, true);
     if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) {
         $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no');
         return;
     }
     $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes');
     if ($phpcsFile->findNext(PHP_CodeSniffer_Tokens::$operators, $stackPtr, $end, false) === false) {
         // There are no arithmetic operators in this.
         $error = 'Echoed strings should not be bracketed';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->replaceToken($firstContent, '');
             $phpcsFile->fixer->replaceToken($end - 1, '');
             $phpcsFile->fixer->endChangeset();
         }
     }
 }
Example #19
0
 /**
  * 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();
     // Ignore abstract methods.
     if (isset($tokens[$stackPtr]['scope_opener']) === false) {
         return;
     }
     // Detect start and end of this function definition.
     $start = $tokens[$stackPtr]['scope_opener'];
     $end = $tokens[$stackPtr]['scope_closer'];
     $nestingLevel = 0;
     // Find the maximum nesting level of any token in the function.
     for ($i = $start + 1; $i < $end; $i++) {
         $level = $tokens[$i]['level'];
         if ($nestingLevel < $level) {
             $nestingLevel = $level;
         }
     }
     // We subtract the nesting level of the function itself.
     $nestingLevel = $nestingLevel - $tokens[$stackPtr]['level'] - 1;
     if ($nestingLevel > $this->absoluteNestingLevel) {
         $error = "Function's nesting level ({$nestingLevel}) exceeds allowed maximum of " . $this->absoluteNestingLevel;
         $phpcsFile->addError($error, $stackPtr);
     } else {
         if ($nestingLevel > $this->nestingLevel) {
             $warning = "Function's nesting level ({$nestingLevel}) exceeds " . $this->nestingLevel . '; consider refactoring the function';
             $phpcsFile->addWarning($warning, $stackPtr);
         }
     }
 }
Example #20
0
 /**
  * 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();
     $ignore = array(T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_FUNCTION, T_CONST);
     $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
     if (in_array($tokens[$prevToken]['code'], $ignore) === true) {
         // Not a call to a PHP function.
         return;
     }
     $function = strtolower($tokens[$stackPtr]['content']);
     if ($function != 'ini_get' && $function != 'ini_set') {
         return;
     }
     $iniToken = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, $stackPtr, null);
     $filteredToken = str_replace(array('"', "'"), array("", ""), $tokens[$iniToken]['content']);
     if (in_array($filteredToken, array_keys($this->newIniDirectives)) === false) {
         return;
     }
     $error = '';
     foreach ($this->newIniDirectives[$filteredToken] as $version => $present) {
         if (!is_null(PHP_CodeSniffer::getConfigData('testVersion')) && version_compare(PHP_CodeSniffer::getConfigData('testVersion'), $version) <= 0) {
             if ($present === true) {
                 $error .= " not available before version " . $version;
             }
         }
     }
     if (strlen($error) > 0) {
         $error = "INI directive '" . $filteredToken . "' is" . $error;
         $phpcsFile->addWarning($error, $stackPtr);
     }
 }
Example #21
0
 /**
  * Process the package tag.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  * @param array $tags The tokens for these tags.
  *
  */
 protected function processPackage(PHP_CodeSniffer_File $phpcsFile, array $tags)
 {
     $tokens = $phpcsFile->getTokens();
     foreach ($tags as $tag) {
         if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) {
             // No content.
             continue;
         }
         $namespace = $this->extractNamespace($phpcsFile);
         $content = $tokens[$tag + 2]['content'];
         if ($namespace !== $content) {
             $phpcsFile->addError('Package name "%s" should be "%s"', $tag, 'InvalidPackage', [$content, $namespace]);
             continue;
         }
         if (PHP_CodeSniffer::isUnderscoreName($content) === true) {
             continue;
         }
         $newContent = str_replace(' ', '_', $content);
         $newContent = trim($newContent, '_');
         $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent);
         $nameBits = explode('_', $newContent);
         $firstBit = array_shift($nameBits);
         $newName = strtoupper($firstBit[0]) . substr($firstBit, 1) . '_';
         foreach ($nameBits as $bit) {
             if ($bit !== '') {
                 $newName .= strtoupper($bit[0]) . substr($bit, 1) . '_';
             }
         }
         $error = 'Package name "%s" is not valid; consider "%s" instead';
         $validName = trim($newName, '_');
         $data = [$content, $validName];
         $phpcsFile->addError($error, $tag, 'InvalidPackage', $data);
     }
 }
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     // do nothing if opening tag is the first character
     if ($stackPtr == 0) {
         return;
     }
     $tokens = $phpcsFile->getTokens();
     $isNotFirstOpenTag = $phpcsFile->findPrevious(array(T_OPEN_TAG), $stackPtr - 1, null, false);
     // some other character beginning file
     if ($isNotFirstOpenTag === false) {
         $validShebang = false;
         // a shebang is allowed on first line only if
         // it is followed by a php open tag on next line
         if ($stackPtr == 1 && $tokens[1]['line'] == 2) {
             // the php tag is the second token and it is on second line
             // so the first token is on the first line
             // check if it is valid shebang
             // T_HASHBANG is a token used in HHVM >=3.5, <3.7 (T103119)
             if (in_array($tokens[0]['type'], array('T_INLINE_HTML', 'T_HASHBANG')) && substr($tokens[0]['content'], 0, 2) == '#!') {
                 $validShebang = true;
             }
         }
         if (!$validShebang) {
             $error = 'Extra character found before first <?';
             $phpcsFile->addError($error, $stackPtr, 'Found');
         }
     }
 }
 /**
  * Processes this sniff, 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 (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') {
         return;
     }
     $commentLine = $tokens[$stackPtr]['line'];
     $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
     if ($tokens[$lastContent]['line'] !== $commentLine) {
         return;
     }
     if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
         return;
     }
     // Special case for JS files.
     if ($tokens[$lastContent]['code'] === T_COMMA || $tokens[$lastContent]['code'] === T_SEMICOLON) {
         $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $lastContent - 1, null, true);
         if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
             return;
         }
     }
     $error = 'Comments may not appear after statements';
     $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found');
     if ($fix === true) {
         $phpcsFile->fixer->addNewlineBefore($stackPtr);
     }
 }
 /**
  * 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
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Find the content of each style definition name.
     $end = $tokens[$stackPtr]['bracket_closer'];
     $next = $phpcsFile->findNext(T_STYLE, $stackPtr + 1, $end);
     if ($next === false) {
         // Class definition is empty.
         return;
     }
     $styleNames = array();
     while ($next !== false) {
         $name = $tokens[$next]['content'];
         if (isset($styleNames[$name]) === true) {
             $first = $styleNames[$name];
             $error = 'Duplicate style definition found; first defined on line %s';
             $data = array($tokens[$first]['line']);
             $phpcsFile->addError($error, $next, 'Found', $data);
         } else {
             $styleNames[$name] = $next;
         }
         $next = $phpcsFile->findNext(T_STYLE, $next + 1, $end);
     }
     //end while
 }
 /**
  * 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();
     $prev = $phpcsFile->findPrevious(T_SEMICOLON, $stackPtr - 1);
     if ($prev === false) {
         return;
     }
     // Ignore multiple statements in a FOR condition.
     if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
         foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) {
             if (isset($tokens[$bracket]['parenthesis_owner']) === false) {
                 // Probably a closure sitting inside a function call.
                 continue;
             }
             $owner = $tokens[$bracket]['parenthesis_owner'];
             if ($tokens[$owner]['code'] === T_FOR) {
                 return;
             }
         }
     }
     if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
         $error = 'Each PHP statement must be on a line by itself';
         $phpcsFile->addError($error, $stackPtr, 'SameLine');
         return;
     }
 }
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $var = $phpcsFile->getTokens()[$stackPtr]['content'];
     if (in_array($var, $this->superglobals)) {
         $phpcsFile->addError('Direct use of %s Superglobal detected.', $stackPtr, 'SuperglobalUsage', array($var));
     }
 }
 /**
  * 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();
     $token = $tokens[$stackPtr];
     // Skip for-statements without body.
     if (isset($token['scope_opener']) === false) {
         return;
     }
     $next = ++$token['scope_opener'];
     $end = --$token['scope_closer'];
     $emptyBody = true;
     for (; $next <= $end; ++$next) {
         if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
             $emptyBody = false;
             break;
         }
     }
     if ($emptyBody === true) {
         // Get token identifier.
         $name = $phpcsFile->getTokensAsString($stackPtr, 1);
         $error = sprintf('Empty %s statement detected', strtoupper($name));
         if ($this->_tokens[$token['code']] === true) {
             $phpcsFile->addError($error, $stackPtr);
         } else {
             $phpcsFile->addWarning($error, $stackPtr);
         }
     }
 }
 /**
  * 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
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $start = $stackPtr + 1;
     $end = $tokens[$stackPtr]['bracket_closer'] - 1;
     $inStyle = null;
     for ($i = $start; $i <= $end; $i++) {
         // Skip nested definitions as they are checked individually.
         if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
             $i = $tokens[$i]['bracket_closer'];
             continue;
         }
         if ($tokens[$i]['code'] === T_STYLE) {
             $inStyle = $tokens[$i]['content'];
         }
         if ($tokens[$i]['code'] === T_SEMICOLON) {
             $inStyle = null;
         }
         if ($inStyle === 'progid') {
             // Special case for IE filters.
             continue;
         }
         if ($tokens[$i]['code'] === T_STYLE || $inStyle !== null && $tokens[$i]['code'] === T_STRING) {
             $expected = strtolower($tokens[$i]['content']);
             if ($expected !== $tokens[$i]['content']) {
                 $error = 'Style definitions must be lowercase; expected %s but found %s';
                 $data = array($expected, $tokens[$i]['content']);
                 $phpcsFile->addError($error, $i, 'FoundUpper', $data);
             }
         }
     }
     //end for
 }
 /**
  * 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 ($tokens[$stackPtr]['content'] === 'ob_end_flush') {
         $phpcsFile->addError('Use of ob_end_flush() is not allowed; use ob_get_contents() and ob_end_clean() instead', $stackPtr, 'Found');
     }
 }
 /**
  * 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();
     // Check for global input variable
     if (!in_array($tokens[$stackPtr]['content'], array('$_GET', '$_POST', '$_REQUEST'))) {
         return;
     }
     $varName = $tokens[$stackPtr]['content'];
     // If we're overriding a superglobal with an assignment, no need to test
     $semicolon_position = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr + 1, null, null, null, true);
     $assignment_position = $phpcsFile->findNext(array(T_EQUAL), $stackPtr + 1, null, null, null, true);
     if ($semicolon_position !== false && $assignment_position !== false && $assignment_position < $semicolon_position) {
         return;
     }
     // Check for whitelisting comment
     $currentLine = $tokens[$stackPtr]['line'];
     $nextPtr = $stackPtr;
     while (isset($tokens[$nextPtr + 1]['line']) && $tokens[$nextPtr + 1]['line'] == $currentLine) {
         $nextPtr++;
         // Do nothing, we just want the last token of the line
     }
     $is_whitelisted = $tokens[$nextPtr]['code'] === T_COMMENT && preg_match('#input var okay#i', $tokens[$nextPtr]['content']) > 0;
     if (!$is_whitelisted) {
         $phpcsFile->addWarning('Detected access of super global var %s, probably need manual inspection.', $stackPtr, null, array($varName));
     }
 }