Example #1
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $firstContent = $phpcsFile->findNext(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;
     }
     // If the parenthesis don't match, then we are not concerned.
     if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) {
         $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no');
         return;
     }
     $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes');
     if ($phpcsFile->findNext(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 #2
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(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->beginChangeset();
             $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar);
             $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $last - 1, null, true);
             if ($tokens[$prev]['code'] !== T_SEMICOLON && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET) {
                 $phpcsFile->fixer->addContent($prev, ';');
             }
             $phpcsFile->fixer->endChangeset();
         }
         $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 within the scope.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
  * @param int                  $stackPtr  The position where this token was
  *                                        found.
  * @param int                  $currScope The position of the current scope.
  *
  * @return void
  */
 protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope)
 {
     $methodName = $phpcsFile->getDeclarationName($stackPtr);
     if ($methodName === null) {
         // Ignore closures.
         return;
     }
     // Ignore magic methods.
     if (preg_match('|^__|', $methodName) !== 0) {
         $magicPart = strtolower(substr($methodName, 2));
         if (isset($this->magicMethods[$magicPart]) === true || isset($this->methodsDoubleUnderscore[$magicPart]) === true) {
             return;
         }
     }
     $testName = ltrim($methodName, '_');
     if ($testName !== '' && Common::isCamelCaps($testName, false, true, false) === false) {
         $error = 'Method name "%s" is not in camel caps format';
         $className = $phpcsFile->getDeclarationName($currScope);
         $errorData = array($className . '::' . $methodName);
         $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
         $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes');
     }
 }
Example #4
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) {
         $phpcsFile->addError('Missing class doc comment', $stackPtr, 'Missing');
         $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no');
         return;
     }
     $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes');
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle');
         return;
     }
     if ($tokens[$commentEnd]['line'] !== $tokens[$stackPtr]['line'] - 1) {
         $error = 'There must be no blank lines after the class comment';
         $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
     }
     $commentStart = $tokens[$commentEnd]['comment_opener'];
     foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
         $error = '%s tag is not allowed in class comment';
         $data = array($tokens[$tag]['content']);
         $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $openTag = $tokens[$stackPtr];
     if ($openTag['content'] === '<?') {
         $error = 'Short PHP opening tag used; expected "<?php" but found "%s"';
         $data = array($openTag['content']);
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found', $data);
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr, '<?php');
         }
         $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'yes');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'no');
     }
     if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO) {
         $nextVar = $tokens[$phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true)];
         $error = 'Short PHP opening tag used with echo; expected "<?php echo %s ..." but found "%s %s ..."';
         $data = array($nextVar['content'], $openTag['content'], $nextVar['content']);
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EchoFound', $data);
         if ($fix === true) {
             if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
                 $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo ');
             } else {
                 $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo');
             }
         }
     }
 }
Example #6
0
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['scope_opener']) === false) {
         $error = 'Possible parse error: %s missing opening or closing brace';
         $data = array($tokens[$stackPtr]['content']);
         $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data);
         return;
     }
     // Determine the name of the class or interface. Note that we cannot
     // simply look for the first T_STRING because a class name
     // starting with the number will be multiple tokens.
     $opener = $tokens[$stackPtr]['scope_opener'];
     $nameStart = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, $opener, true);
     $nameEnd = $phpcsFile->findNext(T_WHITESPACE, $nameStart, $opener);
     if ($nameEnd === false) {
         $name = $tokens[$nameStart]['content'];
     } else {
         $name = trim($phpcsFile->getTokensAsString($nameStart, $nameEnd - $nameStart));
     }
     // Check for camel caps format.
     $valid = Common::isCamelCaps($name, true, true, false);
     if ($valid === false) {
         $type = ucfirst($tokens[$stackPtr]['content']);
         $error = '%s name "%s" is not in camel caps format';
         $data = array($type, $name);
         $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data);
         $phpcsFile->recordMetric($stackPtr, 'CamelCase class name', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'CamelCase class name', 'yes');
     }
 }
Example #7
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 int
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     $found = $phpcsFile->eolChar;
     $found = str_replace("\n", '\\n', $found);
     $found = str_replace("\r", '\\r', $found);
     $phpcsFile->recordMetric($stackPtr, 'EOL char', $found);
     if ($found === $this->eolChar) {
         // Ignore the rest of the file.
         return $phpcsFile->numTokens + 1;
     }
     // 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);
     // Errors are always reported on line 1, no matter where the first PHP tag is.
     $fix = $phpcsFile->addFixableError($error, 0, 'InvalidEOLChar', $data);
     if ($fix === true) {
         $tokens = $phpcsFile->getTokens();
         switch ($this->eolChar) {
             case '\\n':
                 $eolChar = "\n";
                 break;
             case '\\r':
                 $eolChar = "\r";
                 break;
             case '\\r\\n':
                 $eolChar = "\r\n";
                 break;
             default:
                 $eolChar = $this->eolChar;
                 break;
         }
         for ($i = 0; $i < $phpcsFile->numTokens; $i++) {
             if (isset($tokens[$i + 1]) === false || $tokens[$i + 1]['line'] > $tokens[$i]['line']) {
                 // Token is the last on a line.
                 if (isset($tokens[$i]['orig_content']) === true) {
                     $tokenContent = $tokens[$i]['orig_content'];
                 } else {
                     $tokenContent = $tokens[$i]['content'];
                 }
                 $newContent = rtrim($tokenContent, "\r\n");
                 $newContent .= $eolChar;
                 $phpcsFile->fixer->replaceToken($i, $newContent);
             }
         }
     }
     //end if
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
  * @param int                  $stackPtr  The position of the current token in
  *                                        the stack passed in $tokens.
  *
  * @return void
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     if ($this->tabWidth === null) {
         if (isset($phpcsFile->config->tabWidth) === false || $phpcsFile->config->tabWidth === 0) {
             // We have no idea how wide tabs are, so assume 4 spaces for fixing.
             // It shouldn't really matter because indent checks elsewhere in the
             // standard should fix things up.
             $this->tabWidth = 4;
         } else {
             $this->tabWidth = $phpcsFile->config->tabWidth;
         }
     }
     $checkTokens = array(T_WHITESPACE => true, T_INLINE_HTML => true, T_DOC_COMMENT_WHITESPACE => true);
     $tokens = $phpcsFile->getTokens();
     for ($i = $stackPtr + 1; $i < $phpcsFile->numTokens; $i++) {
         if ($tokens[$i]['column'] !== 1 || isset($checkTokens[$tokens[$i]['code']]) === false) {
             continue;
         }
         // If tabs are being converted to spaces, the original content
         // should be used instead of the converted content.
         if (isset($tokens[$i]['orig_content']) === true) {
             $content = $tokens[$i]['orig_content'];
         } else {
             $content = $tokens[$i]['content'];
         }
         if ($content[0] === ' ') {
             if ($tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE && $content === ' ') {
                 // Ignore file/class-level DocBlock.
                 continue;
             }
             // Space are considered ok if they are proceeded by tabs and not followed
             // by tabs, as is the case with standard docblock comments.
             $phpcsFile->recordMetric($i, 'Line indent', 'spaces');
             $error = 'Tabs must be used to indent lines; spaces are not allowed';
             $fix = $phpcsFile->addFixableError($error, $i, 'SpacesUsed');
             if ($fix === true) {
                 $trimmed = ltrim($content, ' ');
                 $numSpaces = strlen($content) - strlen($trimmed);
                 if ($numSpaces < $this->tabWidth) {
                     $numTabs = 1;
                     $padding = "\t";
                 } else {
                     $numTabs = floor($numSpaces / $this->tabWidth);
                     $remaining = $numSpaces - $numTabs * $this->tabWidth;
                     $padding = str_repeat("\t", $numTabs) . ($padding = str_repeat(' ', $remaining));
                 }
                 $phpcsFile->fixer->replaceToken($i, $padding . $trimmed);
             }
         } else {
             if ($content[0] === "\t") {
                 $phpcsFile->recordMetric($i, 'Line indent', 'tabs');
             }
         }
         //end if
     }
     //end for
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
Example #9
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(File $phpcsFile, $stackPtr)
 {
     if ($phpcsFile->findNext(T_INLINE_HTML, $stackPtr + 1) !== false) {
         return $phpcsFile->numTokens + 1;
     }
     // Skip to the end of the file.
     $tokens = $phpcsFile->getTokens();
     $lastToken = $phpcsFile->numTokens - 1;
     // Hard-coding the expected \n in this sniff as it is PSR-2 specific and
     // PSR-2 enforces the use of unix style newlines.
     if (substr($tokens[$lastToken]['content'], -1) !== "\n") {
         $error = 'Expected 1 newline at end of file; 0 found';
         $fix = $phpcsFile->addFixableError($error, $lastToken, 'NoneFound');
         if ($fix === true) {
             $phpcsFile->fixer->addNewline($lastToken);
         }
         $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', '0');
         return $phpcsFile->numTokens + 1;
     }
     // Go looking for the last non-empty line.
     $lastLine = $tokens[$lastToken]['line'];
     if ($tokens[$lastToken]['code'] === T_WHITESPACE) {
         $lastCode = $phpcsFile->findPrevious(T_WHITESPACE, $lastToken - 1, null, true);
     } else {
         $lastCode = $lastToken;
     }
     $lastCodeLine = $tokens[$lastCode]['line'];
     $blankLines = $lastLine - $lastCodeLine + 1;
     $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', $blankLines);
     if ($blankLines > 1) {
         $error = 'Expected 1 blank line at end of file; %s found';
         $data = array($blankLines);
         $fix = $phpcsFile->addFixableError($error, $lastCode, 'TooMany', $data);
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->replaceToken($lastCode, rtrim($tokens[$lastCode]['content']));
             for ($i = $lastCode + 1; $i < $lastToken; $i++) {
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->replaceToken($lastToken, $phpcsFile->eolChar);
             $phpcsFile->fixer->endChangeset();
         }
     }
     // Skip the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
Example #10
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         // Inline comments might just be closing comments for
         // control structures or functions instead of function comments
         // using the wrong comment type. If there is other code on the line,
         // assume they relate to that code.
         $prev = $phpcsFile->findPrevious($find, $commentEnd - 1, null, true);
         if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
             $commentEnd = $prev;
         }
     }
     if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) {
         $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
         $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no');
         return;
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes');
     }
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle');
         return;
     }
     if ($tokens[$commentEnd]['line'] !== $tokens[$stackPtr]['line'] - 1) {
         $error = 'There must be no blank lines after the function comment';
         $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
     }
     $commentStart = $tokens[$commentEnd]['comment_opener'];
     foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
         if ($tokens[$tag]['content'] === '@see') {
             // Make sure the tag isn't empty.
             $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
             if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
                 $error = 'Content missing for @see tag in function comment';
                 $phpcsFile->addError($error, $tag, 'EmptySees');
             }
         }
     }
     $this->processReturn($phpcsFile, $stackPtr, $commentStart);
     $this->processThrows($phpcsFile, $stackPtr, $commentStart);
     $this->processParams($phpcsFile, $stackPtr, $commentStart);
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen;
     $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose;
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['parenthesis_opener']) === false || isset($tokens[$stackPtr]['parenthesis_closer']) === false) {
         return;
     }
     $parenOpener = $tokens[$stackPtr]['parenthesis_opener'];
     $parenCloser = $tokens[$stackPtr]['parenthesis_closer'];
     $spaceAfterOpen = 0;
     if ($tokens[$parenOpener + 1]['code'] === T_WHITESPACE) {
         if (strpos($tokens[$parenOpener + 1]['content'], $phpcsFile->eolChar) !== false) {
             $spaceAfterOpen = 'newline';
         } else {
             $spaceAfterOpen = strlen($tokens[$parenOpener + 1]['content']);
         }
     }
     $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $spaceAfterOpen);
     if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) {
         $error = 'Expected %s spaces after opening bracket; %s found';
         $data = array($this->requiredSpacesAfterOpen, $spaceAfterOpen);
         $fix = $phpcsFile->addFixableError($error, $parenOpener + 1, 'SpacingAfterOpenBrace', $data);
         if ($fix === true) {
             $padding = str_repeat(' ', $this->requiredSpacesAfterOpen);
             if ($spaceAfterOpen === 0) {
                 $phpcsFile->fixer->addContent($parenOpener, $padding);
             } else {
                 if ($spaceAfterOpen === 'newline') {
                     $phpcsFile->fixer->replaceToken($parenOpener + 1, '');
                 } else {
                     $phpcsFile->fixer->replaceToken($parenOpener + 1, $padding);
                 }
             }
         }
     }
     if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) {
         $spaceBeforeClose = 0;
         if ($tokens[$parenCloser - 1]['code'] === T_WHITESPACE) {
             $spaceBeforeClose = strlen(ltrim($tokens[$parenCloser - 1]['content'], $phpcsFile->eolChar));
         }
         $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $spaceBeforeClose);
         if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) {
             $error = 'Expected %s spaces before closing bracket; %s found';
             $data = array($this->requiredSpacesBeforeClose, $spaceBeforeClose);
             $fix = $phpcsFile->addFixableError($error, $parenCloser - 1, 'SpaceBeforeCloseBrace', $data);
             if ($fix === true) {
                 $padding = str_repeat(' ', $this->requiredSpacesBeforeClose);
                 if ($spaceBeforeClose === 0) {
                     $phpcsFile->fixer->addContentBefore($parenCloser, $padding);
                 } else {
                     $phpcsFile->fixer->replaceToken($parenCloser - 1, $padding);
                 }
             }
         }
     }
     //end if
 }
Example #12
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 int
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     $filename = $phpcsFile->getFilename();
     if ($filename === 'STDIN') {
         return;
     }
     $filename = basename($filename);
     $lowercaseFilename = strtolower($filename);
     if ($filename !== $lowercaseFilename) {
         $data = array($filename, $lowercaseFilename);
         $error = 'Filename "%s" doesn\'t match the expected filename "%s"';
         $phpcsFile->addError($error, $stackPtr, 'NotFound', $data);
         $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'yes');
     }
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
Example #13
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(File $phpcsFile, $stackPtr)
 {
     // The BOM will be the very first token in the file.
     if ($stackPtr !== 0) {
         return;
     }
     $tokens = $phpcsFile->getTokens();
     foreach ($this->bomDefinitions as $bomName => $expectedBomHex) {
         $bomByteLength = strlen($expectedBomHex) / 2;
         $htmlBomHex = bin2hex(substr($tokens[$stackPtr]['content'], 0, $bomByteLength));
         if ($htmlBomHex === $expectedBomHex) {
             $errorData = array($bomName);
             $error = 'File contains %s byte order mark, which may corrupt your application';
             $phpcsFile->addError($error, $stackPtr, 'Found', $errorData);
             $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'yes');
             return;
         }
     }
     $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'no');
 }
Example #14
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $keyword = $tokens[$stackPtr]['content'];
     if (strtolower($keyword) !== $keyword) {
         if ($keyword === strtoupper($keyword)) {
             $phpcsFile->recordMetric($stackPtr, 'PHP keyword case', 'upper');
         } else {
             $phpcsFile->recordMetric($stackPtr, 'PHP keyword case', 'mixed');
         }
         $error = 'PHP keywords must be lowercase; expected "%s" but found "%s"';
         $data = array(strtolower($keyword), $keyword);
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found', $data);
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr, strtolower($keyword));
         }
     } else {
         $phpcsFile->recordMetric($stackPtr, 'PHP keyword case', 'lower');
     }
 }
Example #15
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
         $error = 'A cast statement must be followed by a single space';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpace');
         if ($fix === true) {
             $phpcsFile->fixer->addContent($stackPtr, ' ');
         }
         $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0);
         return;
     }
     $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $tokens[$stackPtr + 1]['length']);
     if ($tokens[$stackPtr + 1]['length'] !== 1) {
         $error = 'A cast statement must be followed by a single space';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpace');
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr + 1, ' ');
         }
     }
 }
Example #16
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(File $phpcsFile, $stackPtr)
 {
     $this->currentFile = $phpcsFile;
     $tokens = $phpcsFile->getTokens();
     $type = strtolower($tokens[$stackPtr]['content']);
     $errorData = array($type);
     $find = Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) {
         $phpcsFile->addError('Missing class doc comment', $stackPtr, 'Missing');
         $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no');
         return;
     }
     $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes');
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle');
         return;
     }
     // Check each tag.
     $this->processTags($phpcsFile, $stackPtr, $tokens[$commentEnd]['comment_opener']);
 }
Example #17
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(File $phpcsFile, $stackPtr)
 {
     // Find the last non-empty token.
     $tokens = $phpcsFile->getTokens();
     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 EOF', 'yes');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'no');
     }
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
Example #18
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr]['code'] === T_ELSEIF) {
         $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'elseif');
         return;
     }
     $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     if ($tokens[$next]['code'] === T_IF) {
         $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'else if');
         $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead';
         $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->replaceToken($stackPtr, 'elseif');
             for ($i = $stackPtr + 1; $i <= $next; $i++) {
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->endChangeset();
         }
     }
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) {
         $before = 0;
     } else {
         if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) {
             $before = 'newline';
         } else {
             $before = $tokens[$stackPtr - 1]['length'];
         }
     }
     if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
         $after = 0;
     } else {
         if ($tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) {
             $after = 'newline';
         } else {
             $after = $tokens[$stackPtr + 1]['length'];
         }
     }
     $phpcsFile->recordMetric($stackPtr, 'Spacing before object operator', $before);
     $phpcsFile->recordMetric($stackPtr, 'Spacing after object operator', $after);
     if ($before !== 0 && ($before !== 'newline' || $this->ignoreNewlines === false)) {
         $error = 'Space found before object operator';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before');
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr - 1, '');
         }
     }
     if ($after !== 0 && ($after !== 'newline' || $this->ignoreNewlines === false)) {
         $error = 'Space found after object operator';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After');
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr + 1, '');
         }
     }
 }
Example #20
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 int
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     // Skip to the end of the file.
     $tokens = $phpcsFile->getTokens();
     $stackPtr = $phpcsFile->numTokens - 1;
     if ($phpcsFile->tokenizerType !== 'PHP') {
         $stackPtr--;
     }
     $eolCharLen = strlen($phpcsFile->eolChar);
     $lastChars = substr($tokens[$stackPtr]['content'], $eolCharLen * -1);
     if ($lastChars !== $phpcsFile->eolChar) {
         $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'no');
         $error = 'File must end with a newline character';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotFound');
         if ($fix === true) {
             $phpcsFile->fixer->addNewline($stackPtr);
         }
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'yes');
     }
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
Example #21
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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr]['content'][0] === '#') {
         $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '# ...');
         $error = 'Perl-style comments are not allowed. Use "// Comment."';
         $error .= ' or "/* comment */" instead.';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle');
         if ($fix === true) {
             $newComment = ltrim($tokens[$stackPtr]['content'], '# ');
             $newComment = '// ' . $newComment;
             $phpcsFile->fixer->replaceToken($stackPtr, $newComment);
         }
     } else {
         if ($tokens[$stackPtr]['content'][0] === '/' && $tokens[$stackPtr]['content'][1] === '/') {
             $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '// ...');
         } else {
             if ($tokens[$stackPtr]['content'][0] === '/' && $tokens[$stackPtr]['content'][1] === '*') {
                 $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '/* ... */');
             }
         }
     }
 }
Example #22
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 int
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $fileName = $phpcsFile->getFileName();
     $extension = substr($fileName, strrpos($fileName, '.'));
     $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_TRAIT), $stackPtr);
     if ($nextClass !== false) {
         $phpcsFile->recordMetric($stackPtr, 'File extension for class files', $extension);
         if ($extension === '.php') {
             $error = '%s found in ".php" file; use ".inc" extension instead';
             $data = array(ucfirst($tokens[$nextClass]['content']));
             $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data);
         }
     } else {
         $phpcsFile->recordMetric($stackPtr, 'File extension for non-class files', $extension);
         if ($extension === '.inc') {
             $error = 'No interface or class found in ".inc" file; use ".php" extension instead';
             $phpcsFile->addError($error, $stackPtr, 'NoClass');
         }
     }
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $prev = $phpcsFile->findPrevious(array(T_SEMICOLON, T_OPEN_TAG), $stackPtr - 1);
     if ($prev === false || $tokens[$prev]['code'] === T_OPEN_TAG) {
         $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no');
         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']) {
         $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'yes');
         $error = 'Each PHP statement must be on a line by itself';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SameLine');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->addNewline($prev);
             if ($tokens[$prev + 1]['code'] === T_WHITESPACE) {
                 $phpcsFile->fixer->replaceToken($prev + 1, '');
             }
             $phpcsFile->fixer->endChangeset();
         }
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no');
     }
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes');
     $error = 'Short array syntax is not allowed';
     $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found');
     if ($fix === true) {
         $tokens = $phpcsFile->getTokens();
         $opener = $tokens[$stackPtr]['bracket_opener'];
         $closer = $tokens[$stackPtr]['bracket_closer'];
         $phpcsFile->fixer->beginChangeset();
         $phpcsFile->fixer->replaceToken($opener, 'array(');
         $phpcsFile->fixer->replaceToken($closer, ')');
         $phpcsFile->fixer->endChangeset();
     }
 }
Example #25
0
 /**
  * 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 token stack.
  *
  * @return void
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['scope_closer']) === false) {
         return;
     }
     $errorData = array(strtolower($tokens[$stackPtr]['content']));
     $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_TRAIT), $tokens[$stackPtr]['scope_closer'] + 1);
     if ($nextClass !== false) {
         $error = 'Each %s must be in a file by itself';
         $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData);
         $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes');
     }
     $namespace = $phpcsFile->findNext(array(T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT), 0);
     if ($tokens[$namespace]['code'] !== T_NAMESPACE) {
         $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)';
         $phpcsFile->addError($error, $stackPtr, 'MissingNamespace', $errorData);
         $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes');
     }
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no');
     $error = 'Short array syntax must be used to define arrays';
     $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found');
     if ($fix === true) {
         $tokens = $phpcsFile->getTokens();
         $opener = $tokens[$stackPtr]['parenthesis_opener'];
         $closer = $tokens[$stackPtr]['parenthesis_closer'];
         $phpcsFile->fixer->beginChangeset();
         if ($opener === null) {
             $phpcsFile->fixer->replaceToken($stackPtr, '[]');
         } else {
             $phpcsFile->fixer->replaceToken($stackPtr, '');
             $phpcsFile->fixer->replaceToken($opener, '[');
             $phpcsFile->fixer->replaceToken($closer, ']');
         }
         $phpcsFile->fixer->endChangeset();
     }
 }
Example #27
0
 /**
  * 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(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 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
                 $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 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
                 $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 || $tokens[$stackPtr]['code'] === T_PLUS) {
         // 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(Tokens::$operators[$tokens[$prev]['code']]) === true) {
             // Just trying to operate on a negative value; eg. ($var * -1).
             return;
         }
         if (isset(Tokens::$comparisonTokens[$tokens[$prev]['code']]) === true) {
             // Just trying to compare a negative value; eg. ($var === -1).
             return;
         }
         if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) {
             // Just trying to compare a negative value; eg. ($var || -1 === $b).
             return;
         }
         if (isset(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_OPEN_SHORT_ARRAY => 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(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 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
                 $error = 'Expected 1 space before "%s"; %s found';
                 $data = array($operator, $found);
                 $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data);
                 if ($fix === true) {
                     $phpcsFile->fixer->beginChangeset();
                     if ($found === 'newline') {
                         $i = $stackPtr - 2;
                         while ($tokens[$i]['code'] === T_WHITESPACE) {
                             $phpcsFile->fixer->replaceToken($i, '');
                             $i--;
                         }
                     }
                     $phpcsFile->fixer->replaceToken($stackPtr - 1, ' ');
                     $phpcsFile->fixer->endChangeset();
                 }
             }
             //end if
         }
     }
     //end if
     if (isset($tokens[$stackPtr + 1]) === false) {
         return;
     }
     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 (isset($tokens[$stackPtr + 2]) === true && $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 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
             $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(File $phpcsFile, $stackPtr)
 {
     $this->spacing = (int) $this->spacing;
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) {
         $before = 0;
     } else {
         if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) {
             $before = 'newline';
         } else {
             $before = $tokens[$stackPtr - 1]['length'];
         }
     }
     if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
         $after = 0;
     } else {
         if ($tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) {
             $after = 'newline';
         } else {
             $after = $tokens[$stackPtr + 1]['length'];
         }
     }
     $phpcsFile->recordMetric($stackPtr, 'Spacing before string concat', $before);
     $phpcsFile->recordMetric($stackPtr, 'Spacing after string concat', $after);
     if (($before === $this->spacing || $before === 'newline' && $this->ignoreNewlines === true) && ($after === $this->spacing || $after === 'newline' && $this->ignoreNewlines === true)) {
         return;
     }
     if ($this->spacing === 0) {
         $message = 'Concat operator must not be surrounded by spaces';
         $data = array();
     } else {
         if ($this->spacing > 1) {
             $message = 'Concat operator must be surrounded by %s spaces';
         } else {
             $message = 'Concat operator must be surrounded by a single space';
         }
         $data = array($this->spacing);
     }
     $fix = $phpcsFile->addFixableError($message, $stackPtr, 'PaddingFound', $data);
     if ($fix === true) {
         $padding = str_repeat(' ', $this->spacing);
         if ($before !== 'newline' || $this->ignoreNewlines === false) {
             if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) {
                 $phpcsFile->fixer->replaceToken($stackPtr - 1, $padding);
             } else {
                 if ($this->spacing > 0) {
                     $phpcsFile->fixer->addContent($stackPtr - 1, $padding);
                 }
             }
         }
         if ($after !== 'newline' || $this->ignoreNewlines === false) {
             if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) {
                 $phpcsFile->fixer->replaceToken($stackPtr + 1, $padding);
             } else {
                 if ($this->spacing > 0) {
                     $phpcsFile->fixer->addContent($stackPtr, $padding);
                 }
             }
         }
     }
 }
 /**
  * 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(File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['parenthesis_opener']) === true && isset($tokens[$stackPtr]['parenthesis_closer']) === true) {
         $parenOpener = $tokens[$stackPtr]['parenthesis_opener'];
         $parenCloser = $tokens[$stackPtr]['parenthesis_closer'];
         if ($tokens[$parenOpener + 1]['code'] === T_WHITESPACE) {
             $gap = $tokens[$parenOpener + 1]['length'];
             if ($gap === 0) {
                 $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 'newline');
                 $gap = 'newline';
             } else {
                 $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $gap);
             }
             $error = 'Expected 0 spaces after opening bracket; %s found';
             $data = array($gap);
             $fix = $phpcsFile->addFixableError($error, $parenOpener + 1, 'SpacingAfterOpenBrace', $data);
             if ($fix === true) {
                 $phpcsFile->fixer->replaceToken($parenOpener + 1, '');
             }
         } else {
             $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 0);
         }
         if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line'] && $tokens[$parenCloser - 1]['code'] === T_WHITESPACE) {
             $gap = $tokens[$parenCloser - 1]['length'];
             $error = 'Expected 0 spaces before closing bracket; %s found';
             $data = array($gap);
             $fix = $phpcsFile->addFixableError($error, $parenCloser - 1, 'SpaceBeforeCloseBrace', $data);
             if ($fix === true) {
                 $phpcsFile->fixer->replaceToken($parenCloser - 1, '');
             }
             if ($gap === 0) {
                 $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 'newline');
             } else {
                 $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $gap);
             }
         } else {
             $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 0);
         }
     }
     //end if
     if (isset($tokens[$stackPtr]['scope_closer']) === false) {
         return;
     }
     $scopeOpener = $tokens[$stackPtr]['scope_opener'];
     $scopeCloser = $tokens[$stackPtr]['scope_closer'];
     for ($firstContent = $scopeOpener + 1; $firstContent < $phpcsFile->numTokens; $firstContent++) {
         if ($tokens[$firstContent]['code'] !== T_WHITESPACE) {
             break;
         }
     }
     // We ignore spacing for some structures that tend to have their own rules.
     $ignore = array(T_FUNCTION => true, T_CLASS => true, T_INTERFACE => true, T_TRAIT => true, T_DOC_COMMENT_OPEN_TAG => true);
     if (isset($ignore[$tokens[$firstContent]['code']]) === false && $tokens[$firstContent]['line'] >= $tokens[$scopeOpener]['line'] + 2) {
         $error = 'Blank line found at start of control structure';
         $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpacingAfterOpen');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $i = $scopeOpener + 1;
             while ($tokens[$i]['line'] !== $tokens[$firstContent]['line']) {
                 $phpcsFile->fixer->replaceToken($i, '');
                 $i++;
             }
             $phpcsFile->fixer->addNewline($scopeOpener);
             $phpcsFile->fixer->endChangeset();
         }
     }
     if ($firstContent !== $scopeCloser) {
         $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $scopeCloser - 1, null, true);
         $lastNonEmptyContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, $scopeCloser - 1, null, true);
         $checkToken = $lastContent;
         if (isset($tokens[$lastNonEmptyContent]['scope_condition']) === true) {
             $checkToken = $tokens[$lastNonEmptyContent]['scope_condition'];
         }
         if (isset($ignore[$tokens[$checkToken]['code']]) === false && $tokens[$lastContent]['line'] <= $tokens[$scopeCloser]['line'] - 2) {
             $errorToken = $scopeCloser;
             for ($i = $scopeCloser - 1; $i > $lastContent; $i--) {
                 if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line']) {
                     $errorToken = $i;
                     break;
                 }
             }
             $error = 'Blank line found at end of control structure';
             $fix = $phpcsFile->addFixableError($error, $errorToken, 'SpacingBeforeClose');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 $i = $scopeCloser - 1;
                 for ($i = $scopeCloser - 1; $i > $lastContent; $i--) {
                     if ($tokens[$i]['line'] === $tokens[$scopeCloser]['line']) {
                         continue;
                     }
                     if ($tokens[$i]['line'] === $tokens[$lastContent]['line']) {
                         break;
                     }
                     $phpcsFile->fixer->replaceToken($i, '');
                 }
                 $phpcsFile->fixer->endChangeset();
             }
         }
         //end if
     }
     //end if
     $trailingContent = $phpcsFile->findNext(T_WHITESPACE, $scopeCloser + 1, null, true);
     if ($tokens[$trailingContent]['code'] === T_COMMENT) {
         // Special exception for code where the comment about
         // an ELSE or ELSEIF is written between the control structures.
         $nextCode = $phpcsFile->findNext(Tokens::$emptyTokens, $scopeCloser + 1, null, true);
         if ($tokens[$nextCode]['code'] === T_ELSE || $tokens[$nextCode]['code'] === T_ELSEIF) {
             $trailingContent = $nextCode;
         }
     }
     //end if
     if ($tokens[$trailingContent]['code'] === T_ELSE) {
         if ($tokens[$stackPtr]['code'] === T_IF) {
             // IF with ELSE.
             return;
         }
     }
     if ($tokens[$trailingContent]['code'] === T_WHILE && $tokens[$stackPtr]['code'] === T_DO) {
         // DO with WHILE.
         return;
     }
     if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) {
         // At the end of the script or embedded code.
         return;
     }
     if (isset($tokens[$trailingContent]['scope_condition']) === true && $tokens[$trailingContent]['scope_condition'] !== $trailingContent && isset($tokens[$trailingContent]['scope_opener']) === true && $tokens[$trailingContent]['scope_opener'] !== $trailingContent) {
         // Another control structure's closing brace.
         $owner = $tokens[$trailingContent]['scope_condition'];
         if ($tokens[$owner]['code'] === T_FUNCTION) {
             // The next content is the closing brace of a function
             // so normal function rules apply and we can ignore it.
             return;
         }
         if ($tokens[$owner]['code'] === T_CLOSURE && ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true || $phpcsFile->hasCondition($stackPtr, T_CLOSURE) === true || isset($tokens[$stackPtr]['nested_parenthesis']) === true)) {
             return;
         }
         if ($tokens[$trailingContent]['line'] !== $tokens[$scopeCloser]['line'] + 1) {
             $error = 'Blank line found after control structure';
             $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'LineAfterClose');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 $i = $scopeCloser + 1;
                 while ($tokens[$i]['line'] !== $tokens[$trailingContent]['line']) {
                     $phpcsFile->fixer->replaceToken($i, '');
                     $i++;
                 }
                 $phpcsFile->fixer->addNewline($scopeCloser);
                 $phpcsFile->fixer->endChangeset();
             }
         }
     } else {
         if ($tokens[$trailingContent]['code'] !== T_ELSE && $tokens[$trailingContent]['code'] !== T_ELSEIF && $tokens[$trailingContent]['code'] !== T_CATCH && $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + 1) {
             $error = 'No blank line found after control structure';
             $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'NoLineAfterClose');
             if ($fix === true) {
                 $phpcsFile->fixer->addNewline($scopeCloser);
             }
         }
     }
     //end if
 }
Example #30
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 int
  */
 public function process(File $phpcsFile, $stackPtr)
 {
     $this->currentFile = $phpcsFile;
     $tokens = $phpcsFile->getTokens();
     $commentStart = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     if ($tokens[$commentStart]['code'] === T_COMMENT) {
         $phpcsFile->addError('You must use "/**" style comments for a file comment', $commentStart, 'WrongStyle');
         $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes');
         return $phpcsFile->numTokens + 1;
     } else {
         if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG) {
             $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing');
             $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no');
             return $phpcsFile->numTokens + 1;
         }
     }
     $commentEnd = $tokens[$commentStart]['comment_closer'];
     $nextToken = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true);
     $ignore = array(T_CLASS, T_INTERFACE, T_TRAIT, T_FUNCTION, T_CLOSURE, T_PUBLIC, T_PRIVATE, T_PROTECTED, T_FINAL, T_STATIC, T_ABSTRACT, T_CONST, T_PROPERTY, T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE);
     if (in_array($tokens[$nextToken]['code'], $ignore) === true) {
         $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing');
         $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no');
         return $phpcsFile->numTokens + 1;
     }
     $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes');
     // No blank line between the open tag and the file comment.
     if ($tokens[$commentStart]['line'] > $tokens[$stackPtr]['line'] + 1) {
         $error = 'There must be no blank lines before the file comment';
         $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen');
     }
     // Exactly one blank line after the file comment.
     $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true);
     if ($tokens[$next]['line'] !== $tokens[$commentEnd]['line'] + 2) {
         $error = 'There must be exactly one blank line after the file comment';
         $phpcsFile->addError($error, $commentEnd, 'SpacingAfterComment');
     }
     // Required tags in correct order.
     $required = array('@package' => true, '@subpackage' => true, '@author' => true, '@copyright' => true);
     $foundTags = array();
     foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
         $name = $tokens[$tag]['content'];
         $isRequired = isset($required[$name]);
         if ($isRequired === true && in_array($name, $foundTags) === true) {
             $error = 'Only one %s tag is allowed in a file comment';
             $data = array($name);
             $phpcsFile->addError($error, $tag, 'Duplicate' . ucfirst(substr($name, 1)) . 'Tag', $data);
         }
         $foundTags[] = $name;
         if ($isRequired === false) {
             continue;
         }
         $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
         if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
             $error = 'Content missing for %s tag in file comment';
             $data = array($name);
             $phpcsFile->addError($error, $tag, 'Empty' . ucfirst(substr($name, 1)) . 'Tag', $data);
             continue;
         }
         if ($name === '@author') {
             if ($tokens[$string]['content'] !== 'Squiz Pty Ltd <*****@*****.**>') {
                 $error = 'Expected "Squiz Pty Ltd <*****@*****.**>" for author tag';
                 $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectAuthor');
                 if ($fix === true) {
                     $expected = 'Squiz Pty Ltd <*****@*****.**>';
                     $phpcsFile->fixer->replaceToken($string, $expected);
                 }
             }
         } else {
             if ($name === '@copyright') {
                 if (preg_match('/^([0-9]{4})(-[0-9]{4})? (Squiz Pty Ltd \\(ABN 77 084 670 600\\))$/', $tokens[$string]['content']) === 0) {
                     $error = 'Expected "xxxx-xxxx Squiz Pty Ltd (ABN 77 084 670 600)" for copyright declaration';
                     $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectCopyright');
                     if ($fix === true) {
                         $matches = array();
                         preg_match('/^(([0-9]{4})(-[0-9]{4})?)?.*$/', $tokens[$string]['content'], $matches);
                         if (isset($matches[1]) === false) {
                             $matches[1] = date('Y');
                         }
                         $expected = $matches[1] . ' Squiz Pty Ltd (ABN 77 084 670 600)';
                         $phpcsFile->fixer->replaceToken($string, $expected);
                     }
                 }
             }
         }
         //end if
     }
     //end foreach
     // Check if the tags are in the correct position.
     $pos = 0;
     foreach ($required as $tag => $true) {
         if (in_array($tag, $foundTags) === false) {
             $error = 'Missing %s tag in file comment';
             $data = array($tag);
             $phpcsFile->addError($error, $commentEnd, 'Missing' . ucfirst(substr($tag, 1)) . 'Tag', $data);
         }
         if (isset($foundTags[$pos]) === false) {
             break;
         }
         if ($foundTags[$pos] !== $tag) {
             $error = 'The tag in position %s should be the %s tag';
             $data = array($pos + 1, $tag);
             $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)) . 'TagOrder', $data);
         }
         $pos++;
     }
     //end foreach
     // Ignore the rest of the file.
     return $phpcsFile->numTokens + 1;
 }