/**
  * 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) {
         $error = 'possible parse error: ';
         $error .= $tokens[$stackptr]['content'];
         $error .= ' missing opening or closing brace';
         $phpcsfile->addwarning($error, $stackptr);
         return;
     }
     $curlybrace = $tokens[$stackptr]['scope_opener'];
     $lastcontent = $phpcsfile->findprevious(T_WHITESPACE, $curlybrace - 1, $stackptr, true);
     $classline = $tokens[$lastcontent]['line'];
     $braceline = $tokens[$curlybrace]['line'];
     if ($braceline != $classline) {
         $error = 'Opening brace of a ';
         $error .= $tokens[$stackptr]['content'];
         $error .= ' must be on the same line as the definition';
         $phpcsfile->adderror($error, $curlybrace);
         return;
     }
     if ($tokens[$curlybrace - 1]['code'] === T_WHITESPACE) {
         $prevcontent = $tokens[$curlybrace - 1]['content'];
         if ($prevcontent !== $phpcsfile->eolChar) {
             $blankspace = substr($prevcontent, strpos($prevcontent, $phpcsfile->eolChar));
             $spaces = strlen($blankspace);
             if ($spaces !== 1) {
                 $error = "Expected 1 space before opening brace; {$spaces} found";
                 $phpcsfile->adderror($error, $curlybrace);
             }
         }
     }
 }
 /**
  * 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();
     // Find the next non-empty token.
     $next = $phpcsfile->findnext(PHP_CodeSniffer_tokens::$emptyTokens, $stackptr + 1, null, true);
     if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
         // Not a function call.
         return;
     }
     if (isset($tokens[$next]['parenthesis_closer']) === false) {
         // Not a function call.
         return;
     }
     // Find the previous non-empty token.
     $previous = $phpcsfile->findprevious(PHP_CodeSniffer_tokens::$emptyTokens, $stackptr - 1, null, true);
     if ($tokens[$previous]['code'] === T_FUNCTION) {
         // It's a function definition, not a function call.
         return;
     }
     if ($tokens[$previous]['code'] === T_NEW) {
         // We are creating an object, not calling a function.
         return;
     }
     if ($stackptr + 1 !== $next) {
         // Checking this: $value = my_function[*](...).
         $error = 'Space before opening parenthesis of function call prohibited';
         $phpcsfile->adderror($error, $stackptr);
     }
     if ($tokens[$next + 1]['code'] === T_WHITESPACE) {
         // Checking this: $value = my_function([*]...).
         $error = 'Space after opening parenthesis of function call prohibited';
         $phpcsfile->adderror($error, $stackptr);
     }
     $closer = $tokens[$next]['parenthesis_closer'];
     if ($tokens[$closer - 1]['code'] === T_WHITESPACE) {
         // Checking this: $value = my_function(...[*]).
         $between = $phpcsfile->findnext(T_WHITESPACE, $next + 1, null, true);
         // Only throw an error if there is some content between the parenthesis.
         // IE. Checking for this: $value = my_function().
         // If there is no content, then we would have thrown an error in the
         // previous IF statement because it would look like this:
         // $value = my_function( ).
         if ($between !== $closer) {
             $error = 'Space before closing parenthesis of function call prohibited';
             $phpcsfile->adderror($error, $closer);
         }
     }
     $next = $phpcsfile->findnext(T_WHITESPACE, $closer + 1, null, true);
     if ($tokens[$next]['code'] === T_SEMICOLON) {
         if (in_array($tokens[$closer + 1]['code'], PHP_CodeSniffer_tokens::$emptyTokens) === true) {
             $error = 'Space after closing parenthesis of function call prohibited';
             $phpcsfile->adderror($error, $closer);
         }
     }
 }
Example #3
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();
     if ($tokens[$stackptr + 1]['code'] !== T_WHITESPACE) {
         $error = 'A cast statement must be followed by a single space';
         $phpcsfile->adderror($error, $stackptr);
         return;
     }
     if ($tokens[$stackptr + 1]['content'] !== ' ') {
         $error = 'A cast statement must be followed by a single space';
         $phpcsfile->adderror($error, $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)
 {
     $tokens = $phpcsfile->gettokens();
     $keyword = $tokens[$stackptr]['content'];
     if (strtolower($keyword) !== $keyword) {
         $error = 'TRUE, FALSE and NULL must be lowercase; expected "' . strtolower($keyword) . '" but found "' . $keyword . '"';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
Example #5
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();
     if ($tokens[$stackptr]['content'][0] === '#') {
         $error = 'Perl-style comments are not allowed. Use "// Comment."';
         $error .= ' or "/* comment */" instead.';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
 /**
  * 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();
     $content = $tokens[$stackptr]['content'];
     if ($content !== strtolower($content)) {
         $type = strtoupper($content);
         $expected = strtolower($content);
         $error = "{$type} keyword must be lowercase; expected \"{$expected}\" but found \"{$content}\"";
         $phpcsfile->adderror($error, $stackptr);
     }
 }
Example #7
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(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     $classname = $phpcsfile->findnext(T_STRING, $stackptr);
     $name = trim($tokens[$classname]['content']);
     // Make sure that the word is all lowercase
     if (!preg_match('/[a-z]?/', $name)) {
         $error = ucfirst($tokens[$stackptr]['content']) . ' name is not valid, must be all lower-case';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
 /**
  * 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(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     // Make sure this is whitespace used for indentation.
     $line = $tokens[$stackptr]['line'];
     if ($stackptr > 0 && $tokens[$stackptr - 1]['line'] === $line) {
         return;
     }
     if (strpos($tokens[$stackptr]['content'], "\t") !== false) {
         $error = 'Spaces must be used to indent lines; tabs are not allowed';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
 /**
  * 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(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     // If this is an inline condition (ie. there is no scope opener), then
     // return, as this is not a new scope.
     if (isset($tokens[$stackptr]['scope_closer']) === false) {
         return;
     }
     // We need to actually find the first piece of content on this line,
     // as if this is a method with tokens before it (public, static etc)
     // or an if with an else before it, then we need to start the scope
     // checking from there, rather than the current token.
     $linestart = $stackptr - 1;
     for ($linestart; $linestart > 0; $linestart--) {
         if (strpos($tokens[$linestart]['content'], $phpcsfile->eolChar) !== false) {
             break;
         }
     }
     // We found a new line, now go forward and find the first non-whitespace
     // token.
     $linestart = $phpcsfile->findnext(array(T_WHITESPACE), $linestart + 1, null, true);
     $startcolumn = $tokens[$linestart]['column'];
     $scopestart = $tokens[$stackptr]['scope_opener'];
     $scopeend = $tokens[$stackptr]['scope_closer'];
     // Check that the closing brace is on its own line.
     $lastcontent = $phpcsfile->findprevious(array(T_WHITESPACE), $scopeend - 1, $scopestart, true);
     if ($tokens[$lastcontent]['line'] === $tokens[$scopeend]['line']) {
         $error = 'Closing brace must be on a line by itself';
         $phpcsfile->adderror($error, $scopeend);
         return;
     }
     // Check now that the closing brace is lined up correctly.
     $braceindent = $tokens[$scopeend]['column'];
     $isbreakcloser = $tokens[$scopeend]['code'] === T_BREAK;
     if (in_array($tokens[$stackptr]['code'], array(T_CASE, T_DEFAULT)) === true && $isbreakcloser === true) {
         // BREAK statements should be indented 4 spaces from the
         // CASE or DEFAULT statement.
         if ($braceindent !== $startcolumn + 4) {
             $error = 'Break statement indented incorrectly; expected ' . ($startcolumn + 3) . ' spaces, found ' . ($braceindent - 1);
             $phpcsfile->adderror($error, $scopeend);
         }
     } else {
         if (in_array($tokens[$stackptr]['code'], array(T_CASE, T_DEFAULT))) {
             $startcolumn -= 4;
         }
         if ($braceindent !== $startcolumn) {
             $error = 'Closing brace indented incorrectly; expected ' . ($startcolumn - 1) . ' spaces, found ' . ($braceindent - 1);
             $phpcsfile->adderror($error, $scopeend);
         }
     }
 }
 /**
  * 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]['code'] !== T_STRING) {
         $content = $tokens[$stackptr]['content'];
         if ($content !== strtolower($content)) {
             $type = strtoupper($content);
             $expected = strtolower($content);
             $error = "{$type} keyword must be lowercase; expected \"{$expected}\" but found \"{$content}\"";
             $phpcsfile->adderror($error, $stackptr);
         }
         return;
     }
     // Make sure this is a function call.
     $next = $phpcsfile->findnext(T_WHITESPACE, $stackptr + 1, null, true);
     if ($next === false) {
         // Not a function call.
         return;
     }
     if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
         // Not a function call.
         return;
     }
     $prev = $phpcsfile->findprevious(T_WHITESPACE, $stackptr - 1, null, true);
     if ($tokens[$prev]['code'] === T_FUNCTION) {
         // Function declaration, not a function call.
         return;
     }
     if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR) {
         // Not an inbuilt function.
         return;
     }
     if ($tokens[$prev]['code'] === T_DOUBLE_COLON) {
         // Not an inbuilt function.
         return;
     }
     // Make sure it is an inbuilt PHP function.
     // PHP_CodeSniffer doesn't include/require any files, so no
     // user defined global functions can exist, except for
     // PHP_CodeSniffer ones.
     $content = $tokens[$stackptr]['content'];
     if (function_exists($content) === false) {
         return;
     }
     if ($content !== strtolower($content)) {
         $expected = strtolower($content);
         $error = "Calls to inbuilt PHP functions must be lowercase; expected \"{$expected}\" but found \"{$content}\"";
         $phpcsfile->adderror($error, $stackptr);
     }
 }
 /**
  * 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)
 {
     // If short open tags are off, then any short open tags will be converted
     // to inline_html tags so we can just ignore them.
     // If its on, then we want to ban the use of them.
     $option = ini_get('short_open_tag');
     // Ini_get returns a string "0" if short open tags is off.
     if ($option === '0') {
         return;
     }
     $tokens = $phpcsfile->gettokens();
     $opentag = $tokens[$stackptr];
     if ($opentag['content'] === '<?') {
         $error = 'Short PHP opening tag used. Found "' . $opentag['content'] . '" Expected "<?php".';
         $phpcsfile->adderror($error, $stackptr);
     }
     if ($opentag['code'] === T_OPEN_TAG_WITH_ECHO) {
         $nextvar = $tokens[$phpcsfile->findnext(PHP_CodeSniffer_tokens::$emptyTokens, $stackptr + 1, null, true)];
         $error = 'Short PHP opening tag used with echo. Found "';
         $error .= $opentag['content'] . ' ' . $nextvar['content'] . ' ..." but expected "<?php echo ' . $nextvar['content'] . ' ...".';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
Example #12
0
 /**
  * Process the version tag.
  *
  * @param int $errorpos The line number where the error occurs.
  *
  * @return void
  */
 protected function processversion($errorpos)
 {
     $version = $this->commentparser->getVersion();
     if ($version !== null) {
         $content = $version->getcontent();
         $matches = array();
         if (empty($content) === true) {
             $error = 'content missing for @version tag in file comment';
             $this->currentfile->adderror($error, $errorpos);
         } else {
             if (strstr($content, 'CVS:') === false && strstr($content, 'SVN:') === false) {
                 $error = "Invalid version \"{$content}\" in file comment; consider \"CVS: <cvs_id>\" or \"SVN: <svn_id>\" instead";
                 $this->currentfile->addwarning($error, $errorpos);
             }
         }
     }
 }
Example #13
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();
     $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) {
         return;
     }
     $endofstatement = $phpcsfile->findnext(array(T_SEMICOLON), $stackptr, null, false);
     // If the token before the semi-colon is not a closing parenthesis, then we are not concerned.
     if ($tokens[$endofstatement - 1]['code'] !== T_CLOSE_PARENTHESIS) {
         return;
     }
     if ($phpcsfile->findnext(PHP_CodeSniffer_tokens::$operators, $stackptr, $endofstatement, false) === false) {
         // There are no arithmetic operators in this.
         $error = 'Echoed strings should not be bracketed';
         $phpcsfile->adderror($error, $stackptr);
     }
 }
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(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;
         }
     }
     if ($phpcsfile->eolChar !== $this->eolChar) {
         $expected = $this->eolChar;
         $expected = str_replace("\n", '\\n', $expected);
         $expected = str_replace("\r", '\\r', $expected);
         $found = $phpcsfile->eolChar;
         $found = str_replace("\n", '\\n', $found);
         $found = str_replace("\r", '\\r', $found);
         $error = "end of line character is invalid; expected \"{$expected}\" but found \"{$found}\"";
         $phpcsfile->adderror($error, $stackptr);
     }
 }
 /**
  * Processes the tokens outside the scope.
  *
  * @param PHP_CodeSniffer_File $phpcsfile The file being processed.
  * @param int                  $stackptr  The position where this token was
  *                                        found.
  *
  * @return void
  */
 protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $functionname = $phpcsfile->getDeclarationName($stackptr);
     // Is this a magic function. IE. is prefixed with "__".
     if (preg_match('|^__|', $functionname) !== 0) {
         $magicpart = substr($functionname, 2);
         if (in_array($magicpart, $this->magicfunctions) === false) {
             $error = "Function name \"{$functionname}\" is invalid; " . 'only PHP magic methods should be prefixed with a double underscore';
             $phpcsfile->adderror($error, $stackptr);
         }
         return;
     }
     // Only lower-case accepted
     if (preg_match('/[A-Z]+/', $functionname)) {
         $error = "function name \"{$functionname}\" must be lower-case letters only";
         $phpcsfile->addError($error, $stackptr);
         return;
     }
 }
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(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);
         }
     }
 }
Example #17
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)
 {
     // Modify array of required tags
     $this->tags['package']['required'] = false;
     $this->tags['copyright']['required'] = false;
     $this->tags['author']['required'] = false;
     $this->currentfile = $phpcsfile;
     $tokens = $phpcsfile->gettokens();
     $type = strtolower($tokens[$stackptr]['content']);
     $find = array(T_ABSTRACT, T_WHITESPACE, T_FINAL);
     // Extract the class comment docblock.
     $commentend = $phpcsfile->findprevious($find, $stackptr - 1, null, true);
     if ($commentend !== false && $tokens[$commentend]['code'] === T_COMMENT) {
         $phpcsfile->adderror("You must use \"/**\" style comments for a {$type} comment", $stackptr);
         return;
     } else {
         if ($commentend === false || $tokens[$commentend]['code'] !== T_DOC_COMMENT) {
             $phpcsfile->adderror("Missing {$type} doc comment", $stackptr);
             return;
         }
     }
     $commentstart = $phpcsfile->findprevious(T_DOC_COMMENT, $commentend - 1, null, true) + 1;
     $commentnext = $phpcsfile->findprevious(T_WHITESPACE, $commentend + 1, $stackptr, false, $phpcsfile->eolChar);
     // Distinguish file and class comment.
     $prevclasstoken = $phpcsfile->findprevious(T_CLASS, $stackptr - 1);
     if ($prevclasstoken === false) {
         // This is the first class token in this file, need extra checks.
         $prevnoncomment = $phpcsfile->findprevious(T_DOC_COMMENT, $commentstart - 1, null, true);
         if ($prevnoncomment !== false) {
             $prevcomment = $phpcsfile->findprevious(T_DOC_COMMENT, $prevnoncomment - 1);
             if ($prevcomment === false) {
                 // There is only 1 doc comment between open tag and class token.
                 $newlinetoken = $phpcsfile->findnext(T_WHITESPACE, $commentend + 1, $stackptr, false, $phpcsfile->eolChar);
                 if ($newlinetoken !== false) {
                     $newlinetoken = $phpcsfile->findnext(T_WHITESPACE, $newlinetoken + 1, $stackptr, false, $phpcsfile->eolChar);
                     if ($newlinetoken !== false) {
                         // Blank line between the class and the doc block.
                         // The doc block is most likely a file comment.
                         $phpcsfile->adderror("Missing {$type} doc comment", $stackptr + 1);
                         return;
                     }
                 }
             }
         }
     }
     $comment = $phpcsfile->gettokensAsString($commentstart, $commentend - $commentstart + 1);
     // Parse the class comment.docblock.
     try {
         $this->commentparser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($comment, $phpcsfile);
         $this->commentparser->parse();
     } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
         $line = $e->getlinewithinComment() + $commentstart;
         $phpcsfile->adderror($e->getMessage(), $line);
         return;
     }
     $comment = $this->commentparser->getComment();
     if (is_null($comment) === true) {
         $error = ucfirst($type) . ' doc comment is empty';
         $phpcsfile->adderror($error, $commentstart);
         return;
     }
     // No extra newline before short description.
     $short = $comment->getShortComment();
     $newlinecount = 0;
     $newlinespan = strspn($short, $phpcsfile->eolChar);
     if ($short !== '' && $newlinespan > 0) {
         $line = $newlinespan > 1 ? 'newlines' : 'newline';
         $error = "Extra {$line} found before {$type} comment short description";
         $phpcsfile->adderror($error, $commentstart + 1);
     }
     $newlinecount = substr_count($short, $phpcsfile->eolChar) + 1;
     // Exactly one blank line between short and long description.
     $long = $comment->getlongcomment();
     if (empty($long) === false) {
         $between = $comment->getWhiteSpacebetween();
         $newlinebetween = substr_count($between, $phpcsfile->eolChar);
         if ($newlinebetween !== 2) {
             $error = "There must be exactly one blank line between descriptions in {$type} comments";
             $phpcsfile->adderror($error, $commentstart + $newlinecount + 1);
         }
         $newlinecount += $newlinebetween;
     }
     // Exactly one blank line before tags.
     $tags = $this->commentparser->gettagOrders();
     if (count($tags) > 1) {
         $newlinespan = $comment->getNewlineAfter();
         if ($newlinespan !== 2) {
             $error = "There must be exactly one blank line before the tags in {$type} comments";
             if ($long !== '') {
                 $newlinecount += substr_count($long, $phpcsfile->eolChar) - $newlinespan + 1;
             }
             $phpcsfile->addwarning($error, $commentstart + $newlinecount);
             $short = rtrim($short, $phpcsfile->eolChar . ' ');
         }
     }
     // Check each tag.
     $this->processtags($commentstart, $commentend);
 }
Example #18
0
 /**
  * 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(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     // If this is an inline condition (ie. there is no scope opener), then
     // return, as this is not a new scope.
     if (isset($tokens[$stackptr]['scope_opener']) === false) {
         return;
     }
     if ($tokens[$stackptr]['code'] === T_ELSE) {
         $next = $phpcsfile->findnext(PHP_CodeSniffer_tokens::$emptyTokens, $stackptr + 1, null, true);
         // We will handle the T_IF token in another call to process.
         if ($tokens[$next]['code'] === T_IF) {
             return;
         }
     }
     // Find the first token on this line.
     $firsttoken = $stackptr;
     for ($i = $stackptr; $i >= 0; $i--) {
         // Record the first code token on the line.
         if (in_array($tokens[$i]['code'], PHP_CodeSniffer_tokens::$emptyTokens) === false) {
             $firsttoken = $i;
         }
         // It's the start of the line, so we've found our first php token.
         if ($tokens[$i]['column'] === 1) {
             break;
         }
     }
     // Based on the conditions that surround this token, determine the
     // indent that we expect this current content to be.
     $expectedindent = $this->calculateexpectedindent($tokens, $firsttoken);
     if ($tokens[$firsttoken]['column'] !== $expectedindent) {
         $error = 'line indented incorrectly; expected ';
         $error .= $expectedindent - 1 . ' spaces, found ';
         $error .= $tokens[$firsttoken]['column'] - 1;
         $phpcsfile->adderror($error, $stackptr);
     }
     $scopeopener = $tokens[$stackptr]['scope_opener'];
     $scopecloser = $tokens[$stackptr]['scope_closer'];
     // Some scopes are expected not to have indents.
     if (in_array($tokens[$firsttoken]['code'], $this->nonindentingscopes) === false) {
         $indent = $expectedindent + $this->indent;
     } else {
         $indent = $expectedindent;
     }
     $newline = false;
     $commentopen = false;
     $inheredoc = false;
     // Only loop over the content beween the opening and closing brace, not
     // the braces themselves.
     for ($i = $scopeopener + 1; $i < $scopecloser; $i++) {
         // If this token is another scope, skip it as it will be handled by
         // another call to this sniff.
         if (in_array($tokens[$i]['code'], PHP_CodeSniffer_tokens::$scopeOpeners) === true) {
             if (isset($tokens[$i]['scope_opener']) === true) {
                 $i = $tokens[$i]['scope_closer'];
             } else {
                 // If this token does not have a scope_opener indice, then
                 // it's probably an inline scope, so let's skip to the next
                 // semicolon. Inline scopes include inline if's, abstract methods etc.
                 $nexttoken = $phpcsfile->findnext(T_SEMICOLON, $i, $scopecloser);
                 if ($nexttoken !== false) {
                     $i = $nexttoken;
                 }
             }
             continue;
         }
         // If this is a HEREDOC then we need to ignore it as the whitespace
         // before the contents within the HEREDOC are considered part of the content.
         if ($tokens[$i]['code'] === T_START_HEREDOC) {
             $inheredoc = true;
             continue;
         } else {
             if ($inheredoc === true) {
                 if ($tokens[$i]['code'] === T_END_HEREDOC) {
                     $inheredoc = false;
                 }
                 continue;
             }
         }
         if ($tokens[$i]['column'] === 1) {
             // We started a newline.
             $newline = true;
         }
         if ($newline === true && $tokens[$i]['code'] !== T_WHITESPACE) {
             // If we started a newline and we find a token that is not
             // whitespace, then this must be the first token on the line that
             // must be indented.
             $newline = false;
             $firsttoken = $i;
             $column = $tokens[$firsttoken]['column'];
             // Special case for non-PHP code.
             if ($tokens[$firsttoken]['code'] === T_INLINE_HTML) {
                 $trimmedcontentlength = strlen(ltrim($tokens[$firsttoken]['content']));
                 if ($trimmedcontentlength === 0) {
                     continue;
                 }
                 $contentlength = strlen($tokens[$firsttoken]['content']);
                 $column = $contentlength - $trimmedcontentlength + 1;
             }
             // Check to see if this constant string spans multiple lines.
             // If so, then make sure that the strings on lines other than the
             // first line are indented appropriately, based on their whitespace.
             if (in_array($tokens[$firsttoken]['code'], PHP_CodeSniffer_tokens::$stringTokens) === true) {
                 if (in_array($tokens[$firsttoken - 1]['code'], PHP_CodeSniffer_tokens::$stringTokens) === true) {
                     // If we find a string that directly follows another string
                     // then its just a string that spans multiple lines, so we
                     // don't need to check for indenting.
                     continue;
                 }
             }
             // This is a special condition for T_DOC_COMMENT and C-style
             // comments, which contain whitespace between each line.
             if (in_array($tokens[$firsttoken]['code'], array(T_COMMENT, T_DOC_COMMENT)) === true) {
                 $content = trim($tokens[$firsttoken]['content']);
                 if (preg_match('|^/\\*|', $content) !== 0) {
                     // Check to see if the end of the comment is on the same line
                     // as the start of the comment. If it is, then we don't
                     // have to worry about opening a comment.
                     if (preg_match('|\\*/$|', $content) === 0) {
                         // We don't have to calculate the column for the start
                         // of the comment as there is a whitespace token before it.
                         $commentopen = true;
                     }
                 } else {
                     if ($commentopen === true) {
                         if ($content === '') {
                             // We are in a comment, but this line has nothing on it
                             // so let's skip it.
                             continue;
                         }
                         $contentlength = strlen($tokens[$firsttoken]['content']);
                         $trimmedcontentlength = strlen(ltrim($tokens[$firsttoken]['content']));
                         $column = $contentlength - $trimmedcontentlength + 1;
                         if (preg_match('|\\*/$|', $content) !== 0) {
                             $commentopen = false;
                         }
                     }
                 }
             }
             // The token at the start of the line, needs to have its' column
             // greater than the relative indent we set above. If it is less,
             // an error should be shown.
             if ($column !== $indent) {
                 if ($this->exact === true || $column < $indent) {
                     $error = 'line indented incorrectly; expected ';
                     if ($this->exact === false) {
                         $error .= 'at least ';
                     }
                     $error .= $indent - 1 . ' spaces, found ';
                     $error .= $column - 1;
                     $phpcsfile->adderror($error, $firsttoken);
                 }
             }
         }
     }
 }
 /**
  * Processes variables in double quoted strings.
  *
  * @param PHP_CodeSniffer_File $phpcsfile The file where this token was found.
  * @param int                  $stackptr  The position where the token was found.
  *
  * @return void
  */
 protected function processvariableinstring(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     if (preg_match('/\\$([A-Za-z0-9_]+)(\\-\\>([A-Za-z0-9_]+))?/i', $tokens[$stackptr]['content'], $matches)) {
         $firstvar = $matches[1];
         $objectvar = empty($matches[3]) ? null : $matches[3];
         $membername = $firstvar . $objectvar;
         if (preg_match('/[A-Z]+/', $firstvar, $matches)) {
             if (!in_array($firstvar, $this->allowed_global_vars)) {
                 $error = "Member variable \"{$firstvar}\" must be all lower-case";
                 $phpcsfile->adderror($error, $stackptr);
                 return;
             }
         }
         if (!empty($objectvar) && preg_match('/[A-Z]+/', $objectvar, $matches)) {
             $error = "Member variable \"{$objectvar}\" must be all lower-case";
             $phpcsfile->adderror($error, $stackptr);
             return;
         }
     }
     return;
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsfile The file being scanned.
  * @param int                  $stackptr  The position of the current token in the
  *                                        stack passed in $tokens.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsfile, $stackptr)
 {
     $tokens = $phpcsfile->gettokens();
     $constname = $tokens[$stackptr]['content'];
     // If this token is in a heredoc, ignore it.
     if ($phpcsfile->hasCondition($stackptr, T_START_HEREDOC) === true) {
         return;
     }
     // If the next non-whitespace token after this token
     // is not an opening parenthesis then it is not a function call.
     $openbracket = $phpcsfile->findnext(array(T_WHITESPACE), $stackptr + 1, null, true);
     if ($tokens[$openbracket]['code'] !== T_OPEN_PARENTHESIS) {
         $functionkeyword = $phpcsfile->findprevious(array(T_WHITESPACE, T_COMMA, T_COMMENT, T_STRING), $stackptr - 1, null, true);
         $declarations = array(T_FUNCTION, T_CLASS, T_INTERFACE, T_IMPLEMENTS, T_EXTENDS, T_INSTANCEOF, T_NEW);
         if (in_array($tokens[$functionkeyword]['code'], $declarations) === true) {
             // This is just a declaration; no constants here.
             return;
         }
         if ($tokens[$functionkeyword]['code'] === T_CONST) {
             // This is a class constant.
             if (strtoupper($constname) !== $constname) {
                 $error = 'Class constants must be uppercase; expected ' . strtoupper($constname) . " but found {$constname}";
                 $phpcsfile->adderror($error, $stackptr);
             }
             return;
         }
         // Is this a class name?
         $nextptr = $phpcsfile->findnext(array(T_WHITESPACE), $stackptr + 1, null, true);
         if ($tokens[$nextptr]['code'] === T_DOUBLE_COLON) {
             return;
         }
         // Is this a type hint?
         if ($tokens[$nextptr]['code'] === T_VARIABLE) {
             return;
         } else {
             if ($phpcsfile->isReference($nextptr) === true) {
                 return;
             }
         }
         // Is this a member var name?
         $prevptr = $phpcsfile->findprevious(array(T_WHITESPACE), $stackptr - 1, null, true);
         if ($tokens[$prevptr]['code'] === T_OBJECT_OPERATOR) {
             return;
         }
         // Is this an instance of declare()
         $prevptr = $phpcsfile->findprevious(array(T_WHITESPACE, T_OPEN_PARENTHESIS), $stackptr - 1, null, true);
         if ($tokens[$prevptr]['code'] === T_DECLARE) {
             return;
         }
         // This is a real constant.
         if (strtoupper($constname) !== $constname) {
             $error = 'Constants must be uppercase; expected ' . strtoupper($constname) . " but found {$constname}";
             $phpcsfile->adderror($error, $stackptr);
         }
     } else {
         if (strtolower($constname) === 'define' || strtolower($constname) === 'constant') {
             /*
                 This may be a "define" or "constant" function call.
             */
             // The next non-whitespace token must be the constant name.
             $constptr = $phpcsfile->findnext(array(T_WHITESPACE), $openbracket + 1, null, true);
             if ($tokens[$constptr]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
                 return;
             }
             $constname = $tokens[$constptr]['content'];
             if (strtoupper($constname) !== $constname) {
                 $error = 'Constants must be uppercase; expected ' . strtoupper($constname) . " but found {$constname}";
                 $phpcsfile->adderror($error, $stackptr);
             }
         }
     }
 }
Example #21
0
 /**
  * Checks if a line is too long.
  *
  * @param PHP_CodeSniffer_File $phpcsfile   The file being scanned.
  * @param int                  $stackptr    The token at the end of the line.
  * @param string               $linecontent The content of the line.
  *
  * @return void
  */
 protected function checklinelength(PHP_CodeSniffer_File $phpcsfile, $stackptr, $linecontent)
 {
     // If the content is a CVS or SVN id in a version tag, or it is
     // a license tag with a name and URL, there is nothing the
     // developer can do to shorten the line, so don't throw errors.
     if (preg_match('|@version[^\\$]+\\$Id|', $linecontent) === 0 && preg_match('|@license|', $linecontent) === 0) {
         $linelength = strlen($linecontent);
         if ($this->absolutelinelimit > 0 && $linelength > $this->absolutelinelimit) {
             $error = 'line exceeds maximum limit of ' . $this->absolutelinelimit . " characters; contains {$linelength} characters";
             $phpcsfile->adderror($error, $stackptr);
         } else {
             if ($linelength > $this->linelimit) {
                 $warning = 'line exceeds ' . $this->linelimit . " characters; contains {$linelength} characters";
                 $phpcsfile->addwarning($warning, $stackptr);
             }
         }
     }
 }
 /**
  * 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)
 {
     $error = 'Usage of ELSEIF not allowed. Use ELSE IF instead.';
     $phpcsfile->adderror($error, $stackptr);
 }
Example #23
0
 /**
  * Process the function parameter comments.
  *
  * @param int $commentstart The position in the stack where
  *                          the comment started.
  *
  * @return void
  */
 protected function processparams($commentstart)
 {
     $realparams = $this->currentfile->getmethodparameters($this->_functiontoken);
     $params = $this->commentparser->getparams();
     $foundparams = array();
     if (empty($params) === false) {
         $lastparm = count($params) - 1;
         if (substr_count($params[$lastparm]->getwhitespaceafter(), $this->currentfile->eolChar) !== 2) {
             $error = 'Last parameter comment requires a blank newline after it';
             $errorpos = $params[$lastparm]->getline() + $commentstart;
             $this->currentfile->addwarning($error, $errorpos);
         }
         $previousparam = null;
         $spacebeforevar = 10000;
         $spacebeforecomment = 10000;
         $longesttype = 0;
         $longestvar = 0;
         foreach ($params as $param) {
             $paramcomment = trim($param->getcomment());
             $errorpos = $param->getline() + $commentstart;
             // Make sure that there is only one space before the var type.
             if ($param->getwhitespacebeforetype() !== ' ') {
                 $error = 'Expected 1 space before variable type';
                 $this->currentfile->addwarning($error, $errorpos);
             }
             $spacecount = substr_count($param->getwhitespacebeforevarname(), ' ');
             if ($spacecount < $spacebeforevar) {
                 $spacebeforevar = $spacecount;
                 $longesttype = $errorpos;
             }
             $spacecount = substr_count($param->getwhitespacebeforecomment(), ' ');
             if ($spacecount < $spacebeforecomment && $paramcomment !== '') {
                 $spacebeforecomment = $spacecount;
                 $longestvar = $errorpos;
             }
             // Make sure they are in the correct order,
             // and have the correct name.
             $pos = $param->getposition();
             $paramname = $param->getvarname() !== '' ? $param->getvarname() : '[ UNKNOWN ]';
             if ($previousparam !== null) {
                 $previousname = $previousparam->getvarname() !== '' ? $previousparam->getvarname() : 'UNKNOWN';
                 // Check to see if the parameters align properly.
                 if ($param->alignsvariablewith($previousparam) === false) {
                     $error = 'The variable names for parameters ' . $previousname . ' (' . ($pos - 1) . ') and ' . $paramname . ' (' . $pos . ') do not align';
                     $this->currentfile->addwarning($error, $errorpos);
                 }
                 if ($param->alignsCommentWith($previousparam) === false) {
                     $error = 'The comments for parameters ' . $previousname . ' (' . ($pos - 1) . ') and ' . $paramname . ' (' . $pos . ') do not align';
                     $this->currentfile->addwarning($error, $errorpos);
                 }
             }
             // Make sure the names of the parameter comment matches the
             // actual parameter.
             if (isset($realparams[$pos - 1]) === true) {
                 $realname = $realparams[$pos - 1]['name'];
                 $foundparams[] = $realname;
                 // Append ampersand to name if passing by reference.
                 if ($realparams[$pos - 1]['pass_by_reference'] === true) {
                     $realname = '&' . $realname;
                 }
                 if ($realname !== $param->getvarname()) {
                     $error = 'Doc comment var "' . $paramname;
                     $error .= '" does not match actual variable name "' . $realname;
                     $error .= '" at position ' . $pos;
                     $this->currentfile->adderror($error, $errorpos);
                 }
             } else {
                 // We must have an extra parameter comment.
                 $error = 'Superfluous doc comment at position ' . $pos;
                 $this->currentfile->adderror($error, $errorpos);
             }
             if ($param->getvarname() === '') {
                 $error = 'Missing parameter name at position ' . $pos;
                 $this->currentfile->adderror($error, $errorpos);
             }
             if ($param->gettype() === '') {
                 $error = 'Missing type at position ' . $pos;
                 $this->currentfile->adderror($error, $errorpos);
             }
             if ($paramcomment === '') {
                 $error = 'Missing comment for param "' . $paramname . '" at position ' . $pos;
                 $this->currentfile->adderror($error, $errorpos);
             }
             $previousparam = $param;
         }
         if ($spacebeforevar !== 1 && $spacebeforevar !== 10000 && $spacebeforecomment !== 10000) {
             $error = 'Expected 1 space after the longest type';
             $this->currentfile->adderror($error, $longesttype);
         }
         if ($spacebeforecomment !== 1 && $spacebeforecomment !== 10000) {
             $error = 'Expected 1 space after the longest variable name';
             $this->currentfile->adderror($error, $longestvar);
         }
     }
     $realnames = array();
     foreach ($realparams as $realparam) {
         $realnames[] = $realparam['name'];
     }
     // Report and missing comments.
     $diff = array_diff($realnames, $foundparams);
     foreach ($diff as $neededparam) {
         if (count($params) !== 0) {
             $errorpos = $params[count($params) - 1]->getline() + $commentstart;
         } else {
             $errorpos = $commentstart;
         }
         $error = 'Doc comment for "' . $neededparam . '" missing';
         $this->currentfile->adderror($error, $errorpos);
     }
 }
Example #24
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();
     //$nexttoken = $phpcsfile->findnext(PHP_CodeSniffer_tokens::$emptyTokens, ($stackptr + 1), null, true);
     //if ($tokens[$nexttoken]['code'] === T_OPEN_PARENTHESIS) {
     //    $error  = '"'.$tokens[$stackptr]['content'].'"';
     //    $error .= ' is a statement, not a function; ';
     //    $error .= 'no parentheses are required';
     //    $phpcsfile->adderror($error, $stackptr);
     //}
     $incondition = count($tokens[$stackptr]['conditions']) !== 0 ? true : false;
     // Check to see if this including statement is within the parenthesis of a condition.
     // If that's the case then we need to process it as being within a condition, as they
     // are checking the return value.
     if (isset($tokens[$stackptr]['nested_parenthesis']) === true) {
         foreach ($tokens[$stackptr]['nested_parenthesis'] as $left => $right) {
             if (isset($tokens[$left]['parenthesis_owner']) === true) {
                 $incondition = true;
             }
         }
     }
     // Check to see if they are assigning the return value of this including call.
     // If they are then they are probably checking it, so its conditional.
     $previous = $phpcsfile->findprevious(PHP_CodeSniffer_tokens::$emptyTokens, $stackptr - 1, null, true);
     if (in_array($tokens[$previous]['code'], PHP_CodeSniffer_tokens::$assignmentTokens) === true) {
         // The have assigned the return value to it, so its conditional.
         $incondition = true;
     }
     $tokencode = $tokens[$stackptr]['code'];
     if ($incondition === true) {
         // We are inside a conditional statement. We need an include_once.
         if ($tokencode === T_REQUIRE_ONCE) {
             $error = 'File is being conditionally included; ';
             $error .= 'use "include_once" instead';
             $phpcsfile->adderror($error, $stackptr);
         } else {
             if ($tokencode === T_REQUIRE) {
                 $error = 'File is being conditionally included; ';
                 $error .= 'use "include" instead';
                 $phpcsfile->adderror($error, $stackptr);
             }
         }
     } else {
         // We are unconditionally including, we need a require_once.
         if ($tokencode === T_INCLUDE_ONCE) {
             $error = 'File is being unconditionally included; ';
             $error .= 'use "require_once" instead';
             $phpcsfile->adderror($error, $stackptr);
         } else {
             if ($tokencode === T_INCLUDE) {
                 $error = 'File is being unconditionally included; ';
                 $error .= 'use "require" instead';
                 $phpcsfile->adderror($error, $stackptr);
             }
         }
     }
 }
 /**
  * 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;
     }
 }