addFixableWarning() public method

Returns true if the warning was recorded and should be fixed.
public addFixableWarning ( string $warning, integer $stackPtr, string $code = '', array $data = [], integer $severity ) : boolean
$warning string The error message.
$stackPtr integer The stack position where the error occurred.
$code string A violation code unique to the sniff message.
$data array Replacements for the warning message.
$severity integer The severity level for this warning. A value of 0 will be converted into the default severity level.
return boolean
 /**
  * Processes the tokens that this sniff is interested in.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
  * @param int                  $stackPtr  The position in the stack where
  *                                        the token was found.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $token = $tokens[$stackPtr];
     $comment = $token['content'];
     $isDoubleSlashComment = substr($comment, 0, 2) === '//';
     if ($isDoubleSlashComment) {
         $hasLeadingSpace = $tokens[$stackPtr]['content'][2] === ' ';
         if ($hasLeadingSpace) {
             $hasMoreThanOneLeadingSpace = $tokens[$stackPtr]['content'][3] === ' ';
             if ($hasMoreThanOneLeadingSpace) {
                 $fix = $phpcsFile->addFixableWarning('Double slash comments must start with a single space', $stackPtr, 'SingleLeadingSpaceNeeded');
                 if ($fix) {
                     $fixedComment = preg_replace('/[ ]+/', ' ', $comment);
                     $phpcsFile->fixer->replaceToken($stackPtr, $fixedComment);
                 }
             }
         } else {
             $fix = $phpcsFile->addFixableWarning('Double slash comments must start with a space', $stackPtr, 'LeadingSpaceNeeded');
             if ($fix) {
                 $fixedComment = substr_replace($comment, '// ', 0, 2);
                 $phpcsFile->fixer->replaceToken($stackPtr, $fixedComment);
             }
         }
     }
 }
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $currToken = $tokens[$stackPtr];
     if ($currToken['code'] === T_COMMENT) {
         // Accounting for multiple line comments, as single line comments
         // use only '//' and '#'
         // Also ignoring phpdoc comments starting with '///',
         // as there are no coding standards documented for these
         if (substr($currToken['content'], 0, 2) === '/*' || substr($currToken['content'], 0, 3) === '///') {
             return;
         }
         // Checking whether the comment is an empty one
         if (substr($currToken['content'], 0, 2) === '//' && rtrim($currToken['content']) === '//' || $currToken['content'][0] === '#' && rtrim($currToken['content']) === '#') {
             $phpcsFile->addWarning('Unnecessary empty comment found', $stackPtr, 'EmptyComment');
             // Checking whether there is a space between the comment delimiter
             // and the comment
         } elseif (substr($currToken['content'], 0, 2) === '//' && $currToken['content'][2] !== ' ') {
             $error = 'Single space expected between "//" and comment';
             $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'SingleSpaceBeforeSingleLineComment');
             if ($fix === true) {
                 $content = $currToken['content'];
                 $newContent = preg_replace('/^\\/\\/\\t?/', '// ', $content);
                 $phpcsFile->fixer->replaceToken($stackPtr, $newContent);
             }
             // Finding what the comment delimiter is and checking whether there is a space
             // between the comment delimiter and the comment.
         } elseif ($currToken['content'][0] === '#') {
             // Find number of `#` used.
             $startComment = 0;
             while ($currToken['content'][$startComment] === '#') {
                 $startComment += 1;
             }
             if ($currToken['content'][$startComment] !== ' ') {
                 $error = 'Single space expected between "#" and comment';
                 $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'SingleSpaceBeforeSingleLineComment');
                 if ($fix === true) {
                     $content = $currToken['content'];
                     $delimiter = substr($currToken['content'], 0, $startComment);
                     if ($content[$startComment + 1] === '\\t') {
                         $newContent = preg_replace('/^' . $delimiter . '\\t/', $delimiter . ' ', $content);
                     } else {
                         $newContent = preg_replace('/^' . $delimiter . '/', $delimiter . ' ', $content);
                     }
                     $phpcsFile->fixer->replaceToken($stackPtr, $newContent);
                 }
             }
         }
     }
 }
 /**
  * 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();
     $commentStart = $stackPtr;
     $commentEnd = $tokens[$stackPtr]['comment_closer'];
     $empty = array(T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR);
     $short = $phpcsFile->findNext($empty, $stackPtr + 1, $commentEnd, true);
     if ($short === false) {
         // No content at all.
         $error = 'Doc comment is empty';
         $phpcsFile->addError($error, $stackPtr, 'Empty');
         return;
     }
     // The first line of the comment should have /** comment openning and short description.
     if ($tokens[$short]['line'] !== $tokens[$stackPtr]['line']) {
         $error = 'Short description must follow doc comment open tag immediatelly';
         $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'DescriptionOnAnotherLine');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             for ($ptr = $stackPtr + 1; $ptr < $short; ++$ptr) {
                 $phpcsFile->fixer->replaceToken($ptr, '');
             }
             $phpcsFile->fixer->addContentBefore($short, ' ');
             $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Only check use statements in the global scope.
     if (empty($tokens[$stackPtr]['conditions']) === false) {
         return;
     }
     // Seek to the end of the statement and get the string before the semi colon.
     $semiColon = $phpcsFile->findEndOfStatement($stackPtr);
     if ($tokens[$semiColon]['code'] !== T_SEMICOLON) {
         return;
     }
     $classPtr = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $semiColon - 1, null, true);
     // Seek along the statement to get the last part, which is the
     // class/interface name.
     while (isset($tokens[$classPtr + 1]) === true && in_array($tokens[$classPtr + 1]['code'], array(T_STRING, T_NS_SEPARATOR)) === true) {
         $classPtr++;
     }
     if ($tokens[$classPtr]['code'] !== T_STRING) {
         return;
     }
     $classUsed = $phpcsFile->findNext(T_STRING, $classPtr + 1, null, false, $tokens[$classPtr]['content']);
     while ($classUsed !== false) {
         $beforeUsage = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $classUsed - 1, null, true);
         // If a backslash is used before the class name then this is some other
         // use statement.
         if ($tokens[$beforeUsage]['code'] !== T_USE && $tokens[$beforeUsage]['code'] !== T_NS_SEPARATOR) {
             return;
         }
         // Trait use statement within a class.
         if ($tokens[$beforeUsage]['code'] === T_USE && empty($tokens[$beforeUsage]['conditions']) === false) {
             return;
         }
         $classUsed = $phpcsFile->findNext(T_STRING, $classUsed + 1, null, false, $tokens[$classPtr]['content']);
     }
     //end while
     $warning = 'Unused use statement';
     $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse');
     if ($fix === true) {
         // Remove the whole use statement line.
         $phpcsFile->fixer->beginChangeset();
         for ($i = $stackPtr; $i <= $semiColon; $i++) {
             $phpcsFile->fixer->replaceToken($i, '');
         }
         // Also remove whitespace after the semicolon (new lines).
         while (isset($tokens[$i]) === true && $tokens[$i]['code'] === T_WHITESPACE) {
             $phpcsFile->fixer->replaceToken($i, '');
             if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) {
                 break;
             }
             $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     if ($tokens[$next]['code'] === T_IF) {
         $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead';
         $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed');
         if ($fix === true && $phpcsFile->fixer->enabled === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->replaceToken($stackPtr, 'elseif');
             for ($i = $stackPtr + 1; $i <= $next; $i++) {
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->endChangeset();
         }
     }
 }
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $nextToken = $tokens[$stackPtr + 1];
     if ($nextToken['code'] !== T_WHITESPACE || $nextToken['content'] !== ' ') {
         $error = 'Control structure "%s" must be followed by a single space';
         $data = array($tokens[$stackPtr]['content']);
         $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'Incorrect', $data);
         if ($fix === true) {
             if ($nextToken['code'] !== T_WHITESPACE) {
                 $phpcsFile->fixer->addContent($stackPtr, ' ');
             } else {
                 // Too many spaces
                 $phpcsFile->fixer->replaceToken($stackPtr + 1, ' ');
             }
         }
     }
 }
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $prevToken = $tokens[$stackPtr - 1];
     if ($prevToken['code'] !== T_WHITESPACE || $prevToken['content'] !== " ") {
         $fix = $phpcsFile->addFixableWarning('Single space expected before "%s"', $stackPtr + 1, 'SpaceBeforeElse', array($tokens[$stackPtr]['content']));
         if ($fix === true) {
             if ($prevToken['code'] === T_CLOSE_CURLY_BRACKET) {
                 $phpcsFile->fixer->addContentBefore($stackPtr, ' ');
             } else {
                 // Replace all previous whitespace with a space
                 $phpcsFile->fixer->replaceToken($stackPtr - 1, ' ');
                 for ($i = 2; $tokens[$stackPtr - $i]['code'] === T_WHITESPACE; $i++) {
                     $phpcsFile->fixer->replaceToken($stackPtr - $i, '');
                 }
             }
         }
     }
 }
 /**
  * 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();
     $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');
         return;
     }
     if ($tokens[$stackPtr]['code'] === T_ELSEIF) {
         $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'elseif');
         $error = 'Usage of ELSEIF is discouraged; use ELSE IF instead';
         $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->replaceToken($stackPtr, 'else if');
             $phpcsFile->fixer->endChangeset();
         }
     }
 }
 /**
  * Processes the tokens that this sniff is interested in.
  *
  * @todo Handle multiple todos in a single comment token.
  *
  * @param PHP_CodeSniffer_File $phpcsFile  The file where the token was found.
  * @param int                  $stackPtr  The position in the stack where
  *                                        the token was found.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $token = $tokens[$stackPtr];
     $comment = $token['content'];
     $todoPos = stripos($comment, 'todo');
     // Is there a todo tag?
     if ($todoPos === false) {
         return;
     }
     // Is there something next to the todo tag that can't be trimmed?
     $hasSomethingBefore = isset($comment[$todoPos - 1]) && !in_array(trim($comment[$todoPos - 1]), array('', '@', '/'));
     $hasSomethingAfter = isset($comment[$todoPos + 4]) && trim($comment[$todoPos + 4]) !== '';
     // If not, then it's really a todo tag!
     if (!$hasSomethingBefore && !$hasSomethingAfter) {
         // Lowercase?
         $todoKeyword = substr($comment, $todoPos, 4);
         if (!preg_match('/todo/', $todoKeyword)) {
             $fix = $phpcsFile->addFixableWarning('Todo should be lowercase', $stackPtr, 'UppercaseForbidden');
             if ($fix) {
                 $fixedComment = str_ireplace('todo', 'todo', $comment);
                 $phpcsFile->fixer->replaceToken($stackPtr, $fixedComment);
             }
         }
         // @ prefix?
         if ($todoPos === 0 || $comment[$todoPos - 1] !== '@') {
             $fix = $phpcsFile->addFixableError('Todo is missing @ prefix', $stackPtr, 'MissingAtSignPrefix');
             if ($fix) {
                 $fixedComment = str_ireplace('todo', '@todo', $comment);
                 $phpcsFile->fixer->replaceToken($stackPtr, $fixedComment);
             }
         }
         // Developer's trigram?
         $todo = '@' . substr($comment, $todoPos, 9);
         if (!preg_match('/@(todo|TODO) [A-Z]{3}\\s/', $todo)) {
             $phpcsFile->addWarning('Todo should be followed by the uppercased developer\'s trigram. Expected something like "@todo ABC" where ABC is the trigram, but found "%s"', $stackPtr, 'TrigramSuffix', array($todo));
         }
     }
 }
Example #10
0
 /**
  * Generates the error or warning for this sniff.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  * @param int                  $stackPtr  The position of the forbidden style
  *                                        in the token array.
  * @param string               $style     The name of the forbidden style.
  * @param string               $pattern   The pattern used for the match.
  *
  * @return void
  */
 protected function addError($phpcsFile, $stackPtr, $style, $pattern = null)
 {
     $data = array($style);
     $error = 'The use of style %s is ';
     if ($this->error === true) {
         $type = 'Found';
         $error .= 'forbidden';
     } else {
         $type = 'Discouraged';
         $error .= 'discouraged';
     }
     if ($pattern === null) {
         $pattern = $style;
     }
     if ($this->forbiddenStyles[$pattern] !== null) {
         $data[] = $this->forbiddenStyles[$pattern];
         if ($this->error === true) {
             $fix = $phpcsFile->addFixableError($error . '; use %s instead', $stackPtr, $type . 'WithAlternative', $data);
         } else {
             $fix = $phpcsFile->addFixableWarning($error . '; use %s instead', $stackPtr, $type . 'WithAlternative', $data);
         }
         if ($fix === true) {
             $phpcsFile->fixer->replaceToken($stackPtr, $this->forbiddenStyles[$pattern]);
         }
     } else {
         if ($this->error === true) {
             $phpcsFile->addError($error, $stackPtr, $type, $data);
         } else {
             $phpcsFile->addWarning($error, $stackPtr, $type, $data);
         }
     }
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  * @param int                  $stackPtr  The position of the current token in the
  *                                        stack passed in $tokens.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['scope_opener']) === true) {
         $scopeOpener = $tokens[$tokens[$stackPtr]['scope_opener']];
         if (!isset($tokens[$stackPtr]['parenthesis_closer'])) {
             return;
         }
         $parenthesisCloser = $tokens[$tokens[$stackPtr]['parenthesis_closer']];
         if ($scopeOpener['line'] === $parenthesisCloser['line']) {
             return;
         }
         //FIXME!
         $fix = $phpcsFile->addFixableError('Opening curly brace must open on the same line as parentheses closer.', $tokens[$stackPtr]['scope_opener'], 'NotAllowed');
         if ($fix === true && $phpcsFile->fixer->enabled === true) {
             $next = $phpcsFile->findNext(T_WHITESPACE, $tokens[$stackPtr]['parenthesis_closer'] + 1, $tokens[$stackPtr]['scope_opener'] - 1, true);
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->addContent($tokens[$stackPtr]['parenthesis_closer'], ' w');
             for ($i = $tokens[$stackPtr]['parenthesis_closer'] + 1; $i < $next; $i++) {
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->endChangeset();
         }
         return;
     }
     // 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) {
         $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed');
     } else {
         $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged');
     }
     if ($fix === true && $phpcsFile->fixer->enabled === true) {
         $phpcsFile->fixer->beginChangeset();
         if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) {
             $closer = $tokens[$stackPtr]['parenthesis_closer'];
         } else {
             $closer = $stackPtr;
         }
         $phpcsFile->fixer->addContent($closer, ' { ');
         $semicolon = $phpcsFile->findNext(T_SEMICOLON, $closer + 1);
         $next = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, $semicolon + 1, true);
         // Account for a comment on the end of the line.
         for ($endLine = $semicolon; $endLine < $phpcsFile->numTokens; $endLine++) {
             if (isset($tokens[$endLine + 1]) === false || $tokens[$endLine]['line'] !== $tokens[$endLine + 1]['line']) {
                 break;
             }
         }
         if ($tokens[$endLine]['code'] !== T_COMMENT) {
             $endLine = $semicolon;
         }
         // Put the closing one a line further down
         $indentation = str_repeat("\t", $tokens[$stackPtr]['level']);
         if ($next !== $semicolon) {
             if ($endLine !== $semicolon) {
                 //$n = $phpcsFile->fixer->getTokenContent($next);
                 //$phpcsFile->fixer->replaceToken($next, "\n" . str_repeat("\t", $tokens[$next]['level'] - 1) . $n);
                 $phpcsFile->fixer->addContent($endLine, '}');
             } else {
                 $n = $phpcsFile->fixer->getTokenContent($next);
                 if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
                     $phpcsFile->fixer->replaceToken($next, "\n" . str_repeat("\t", $tokens[$next]['level'] + 1) . $n);
                 }
                 $indentation = "\n" . $indentation;
                 $phpcsFile->fixer->addContent($semicolon, $indentation . '}');
             }
         } else {
             if ($endLine !== $semicolon) {
                 $phpcsFile->fixer->replaceToken($semicolon, '');
                 $phpcsFile->fixer->addNewlineBefore($endLine);
                 $phpcsFile->fixer->addContent($endLine, '}');
             } else {
                 $phpcsFile->fixer->replaceToken($semicolon, '}');
             }
         }
         $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['scope_opener']) === true) {
         $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no');
         return;
     }
     // Ignore the ELSE in ELSE IF. We'll process the IF part later.
     if ($tokens[$stackPtr]['code'] === T_ELSE) {
         $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
         if ($tokens[$next]['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;
                 }
             }
         }
         // In Javascript DO WHILE loops without curly braces are legal. This
         // is only valid if a single statement is present between the DO and
         // the WHILE. We can detect this by checking only a single semicolon
         // is present between them.
         if ($phpcsFile->tokenizerType === 'JS') {
             $lastDo = $phpcsFile->findPrevious(T_DO, $stackPtr - 1);
             $lastSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, $stackPtr - 1);
             if ($lastDo !== false && $lastSemicolon !== false && $lastDo < $lastSemicolon) {
                 $precedingSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, $lastSemicolon - 1);
                 if ($precedingSemicolon === false || $precedingSemicolon < $lastDo) {
                     return;
                 }
             }
         }
     }
     //end if
     // This is a control structure without an opening brace,
     // so it is an inline statement.
     if ($this->error === true) {
         $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed');
     } else {
         $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged');
     }
     $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'yes');
     // Stop here if we are not fixing the error.
     if ($fix !== true) {
         return;
     }
     $phpcsFile->fixer->beginChangeset();
     if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) {
         $closer = $tokens[$stackPtr]['parenthesis_closer'];
     } else {
         $closer = $stackPtr;
     }
     if ($tokens[$closer + 1]['code'] === T_WHITESPACE || $tokens[$closer + 1]['code'] === T_SEMICOLON) {
         $phpcsFile->fixer->addContent($closer, ' {');
     } else {
         $phpcsFile->fixer->addContent($closer, ' { ');
     }
     $lastNonEmpty = $closer;
     for ($end = $closer + 1; $end < $phpcsFile->numTokens; $end++) {
         if ($tokens[$end]['code'] === T_SEMICOLON) {
             break;
         }
         if ($tokens[$end]['code'] === T_CLOSE_TAG) {
             $end = $lastNonEmpty;
             break;
         }
         if (isset($tokens[$end]['scope_opener']) === true) {
             $type = $tokens[$end]['code'];
             $end = $tokens[$end]['scope_closer'];
             if ($type === T_DO || $type === T_IF || $type === T_ELSEIF) {
                 $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $end + 1, null, true);
                 if ($next === false) {
                     break;
                 }
                 $nextType = $tokens[$next]['code'];
                 // Let additional conditions loop and find their ending.
                 if (($type === T_IF || $type === T_ELSEIF) && ($nextType === T_ELSEIF || $nextType === T_ELSE)) {
                     continue;
                 }
                 // Account for DO... WHILE conditions.
                 if ($type === T_DO && $nextType === T_WHILE) {
                     $end = $phpcsFile->findNext(T_SEMICOLON, $next + 1);
                 }
             }
             //end if
             break;
         }
         //end if
         if ($tokens[$end]['code'] !== T_WHITESPACE) {
             $lastNonEmpty = $end;
         }
     }
     //end for
     $next = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, $end + 1, true);
     // Account for a comment on the end of the line.
     for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) {
         if (isset($tokens[$endLine + 1]) === false || $tokens[$endLine]['line'] !== $tokens[$endLine + 1]['line']) {
             break;
         }
     }
     if ($tokens[$endLine]['code'] !== T_COMMENT) {
         $endLine = $end;
     }
     if ($next !== $end) {
         if ($endLine !== $end) {
             $phpcsFile->fixer->addContent($endLine, '}');
         } else {
             if ($tokens[$end]['code'] !== T_SEMICOLON && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET) {
                 $phpcsFile->fixer->addContent($end, ';');
             }
             $phpcsFile->fixer->addContent($end, ' }');
         }
     } else {
         if ($endLine !== $end) {
             $phpcsFile->fixer->replaceToken($end, '');
             $phpcsFile->fixer->addNewlineBefore($endLine);
             $phpcsFile->fixer->addContent($endLine, '}');
         } else {
             $phpcsFile->fixer->replaceToken($end, '}');
         }
     }
     //end if
     $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Ignore assignments used in a condition, like an IF or FOR.
     if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
         foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) {
             if (isset($tokens[$start]['parenthesis_owner']) === true) {
                 return;
             }
         }
     }
     /*
         By this stage, it is known that there is an assignment on this line.
         We only want to process the block once we reach the last assignment,
         so we need to determine if there are more to follow.
     */
     // The assignment may span over multiple lines, so look for the
     // end of the assignment so we can check assignment blocks correctly.
     $lineEnd = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1);
     $nextAssign = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$assignmentTokens, $lineEnd + 1);
     if ($nextAssign !== false) {
         $isAssign = true;
         if ($tokens[$nextAssign]['line'] === $tokens[$lineEnd]['line'] + 1) {
             // Assignment may be in the same block as this one. Just make sure
             // it is not used in a condition, like an IF or FOR.
             if (isset($tokens[$nextAssign]['nested_parenthesis']) === true) {
                 foreach ($tokens[$nextAssign]['nested_parenthesis'] as $start => $end) {
                     if (isset($tokens[$start]['parenthesis_owner']) === true) {
                         // Not an assignment.
                         $isAssign = false;
                         break;
                     }
                 }
             }
             if ($isAssign === true) {
                 return;
             }
         }
     }
     // Getting here means that this is the last in a block of statements.
     $assignments = array();
     $assignments[] = $stackPtr;
     $prevAssignment = $stackPtr;
     $lastLine = $tokens[$stackPtr]['line'];
     while (($prevAssignment = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $prevAssignment - 1)) !== false) {
         // We are not interested in double arrows as they assign values inside
         // arrays and loops and do not use the same indentation rules.
         if ($tokens[$prevAssignment]['code'] === T_DOUBLE_ARROW) {
             continue;
         }
         // The assignment's end token must be on the line directly
         // above the current one to be in the same assignment block.
         $lineEnd = $phpcsFile->findNext(T_SEMICOLON, $prevAssignment + 1);
         // And the end token must actually belong to this assignment.
         $nextOpener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$scopeOpeners, $prevAssignment + 1);
         if ($nextOpener !== false && $nextOpener < $lineEnd) {
             break;
         }
         if ($tokens[$lineEnd]['line'] !== $lastLine - 1) {
             break;
         }
         // Make sure it is not assigned inside a condition (eg. IF, FOR).
         if (isset($tokens[$prevAssignment]['nested_parenthesis']) === true) {
             foreach ($tokens[$prevAssignment]['nested_parenthesis'] as $start => $end) {
                 if (isset($tokens[$start]['parenthesis_owner']) === true) {
                     break 2;
                 }
             }
         }
         $assignments[] = $prevAssignment;
         $lastLine = $tokens[$prevAssignment]['line'];
     }
     //end while
     $assignmentData = array();
     $maxAssignmentLength = 0;
     $maxVariableLength = 0;
     foreach ($assignments as $assignment) {
         $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $assignment - 1, null, true);
         $endColumn = $tokens[$prev + 1]['column'];
         if ($maxVariableLength < $endColumn) {
             $maxVariableLength = $endColumn;
         }
         if ($maxAssignmentLength < strlen($tokens[$assignment]['content'])) {
             $maxAssignmentLength = strlen($tokens[$assignment]['content']);
         }
         $assignmentData[$assignment] = array('variable_length' => $endColumn, 'assignment_length' => strlen($tokens[$assignment]['content']));
     }
     //end foreach
     foreach ($assignmentData as $assignment => $data) {
         if ($data['assignment_length'] === $maxAssignmentLength) {
             if ($data['variable_length'] === $maxVariableLength) {
                 // The assignment is the longest possible, so the column that
                 // everything has to align to is based on it.
                 $column = $maxVariableLength + 1;
                 break;
             } else {
                 // The assignment token is the longest out of all of the
                 // assignments, but the variable name is not, so the column
                 // the start at can go back more to cover the space
                 // between the variable name and the assignment operator.
                 $column = $maxVariableLength - ($maxAssignmentLength - 1) + 1;
             }
         }
     }
     // Determine the actual position that each equals sign should be in.
     foreach ($assignments as $assignment) {
         // Actual column takes into account the length of the assignment operator.
         $actualColumn = $column + $maxAssignmentLength - strlen($tokens[$assignment]['content']);
         if ($tokens[$assignment]['column'] !== $actualColumn) {
             $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $assignment - 1, null, true);
             $expected = $actualColumn - $tokens[$prev + 1]['column'];
             if ($tokens[$assignment]['line'] !== $tokens[$prev]['line']) {
                 // Instead of working out how many spaces there are
                 // across new lines, the error message becomes more
                 // generic below.
                 $found = null;
             } else {
                 $found = $tokens[$assignment]['column'] - $tokens[$prev + 1]['column'];
             }
             // If the expected number of spaces for alignment exceeds the
             // maxPadding rule, we just check for a single space as no
             // alignment is required.
             if ($expected > $this->maxPadding) {
                 if ($found === 1) {
                     continue;
                 } else {
                     $expected = 1;
                 }
             }
             // Skip multi-line assignments if required.
             if ($found === null && $this->ignoreMultiLine === true) {
                 continue;
             }
             $expectedText = $expected;
             $expectedText .= $expected === 1 ? ' space' : ' spaces';
             $foundText = $found;
             if ($foundText === null) {
                 $foundText = 'a new line';
             } else {
                 $foundText .= $foundText === 1 ? ' space' : ' spaces';
             }
             if (count($assignments) === 1) {
                 $type = 'Incorrect';
                 $error = 'Equals sign not aligned correctly; expected %s but found %s';
             } else {
                 $type = 'NotSame';
                 $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s';
             }
             $errorData = array($expectedText, $foundText);
             if ($this->error === true) {
                 $fix = $phpcsFile->addFixableError($error, $assignment, $type, $errorData);
             } else {
                 $fix = $phpcsFile->addFixableWarning($error, $assignment, $type . 'Warning', $errorData);
             }
             if ($fix === true && $phpcsFile->fixer->enabled === true && $found !== null) {
                 $newContent = str_repeat(' ', $expected);
                 if ($found === 0) {
                     $phpcsFile->fixer->addContentBefore($assignment, $newContent);
                 } else {
                     $phpcsFile->fixer->replaceToken($assignment - 1, $newContent);
                 }
             }
         }
         //end if
     }
     //end foreach
 }
 /**
  * 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();
     $arrayStart = $tokens[$stackPtr]['bracket_opener'];
     $arrayEnd = $tokens[$arrayStart]['bracket_closer'];
     // Check for empty arrays.
     $content = $phpcsFile->findNext([T_WHITESPACE], $arrayStart + 1, $arrayEnd + 1, true);
     if ($content === $arrayEnd) {
         // Empty array, but if the brackets aren't together, there's a problem.
         if ($arrayEnd - $arrayStart !== 1) {
             $error = 'Empty array declaration must have no space between the brackets.';
             $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceInEmptyArray');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 for ($i = $arrayStart + 1; $i < $arrayEnd; $i++) {
                     $phpcsFile->fixer->replaceToken($i, '');
                 }
                 $phpcsFile->fixer->endChangeset();
             }
             // We can return here because there is nothing else to check. All code
             // below can assume that the array is not empty.
             return;
         }
     }
     $lastItem = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrayEnd - 1, $stackPtr, true);
     // Empty array.
     if ($lastItem === $arrayStart) {
         return;
     }
     // Inline array.
     $isInlineArray = $tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line'];
     // Check if the last item in a multiline array has a "closing" comma.
     if ($tokens[$lastItem]['code'] !== T_COMMA && $isInlineArray === false) {
         $error = 'A comma must follow the last multiline array item.';
         $fix = $phpcsFile->addFixableError($error, $lastItem, 'NoLastComma');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             $phpcsFile->fixer->addContent($lastItem, ',');
             $phpcsFile->fixer->endChangeset();
         }
         return;
     }
     if ($isInlineArray === true) {
         if ($tokens[$lastItem]['code'] === T_COMMA) {
             $error = 'Comma not allowed after last value in single-line array declaration';
             $fix = $phpcsFile->addFixableWarning($error, $lastItem, 'LastComma');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 $phpcsFile->fixer->replaceToken($lastItem, '');
                 $phpcsFile->fixer->endChangeset();
             }
             return;
         }
         // Inline array must not have spaces within brackets.
         if ($content !== $arrayStart + 1) {
             $error = 'Space found after opening bracket of array';
             $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpen');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 for ($i = $arrayStart + 1; $i < $content; $i++) {
                     $phpcsFile->fixer->replaceToken($i, '');
                 }
                 $phpcsFile->fixer->endChangeset();
             }
         }
         if ($lastItem !== $arrayEnd - 1) {
             $error = 'Space found before closing bracket of array';
             $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose');
             if ($fix === true) {
                 $phpcsFile->fixer->beginChangeset();
                 for ($i = $lastItem + 1; $i < $arrayEnd; $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (isset($tokens[$stackPtr]['scope_opener']) === true) {
         $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no');
         return;
     }
     // 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) {
         $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed');
     } else {
         $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged');
     }
     $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'yes');
     if ($fix === true) {
         $phpcsFile->fixer->beginChangeset();
         if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) {
             $closer = $tokens[$stackPtr]['parenthesis_closer'];
         } else {
             $closer = $stackPtr;
         }
         if ($tokens[$closer + 1]['code'] === T_WHITESPACE || $tokens[$closer + 1]['code'] === T_SEMICOLON) {
             $phpcsFile->fixer->addContent($closer, ' {');
         } else {
             $phpcsFile->fixer->addContent($closer, ' { ');
         }
         for ($end = $closer + 1; $end < $phpcsFile->numTokens; $end++) {
             if ($tokens[$end]['code'] === T_SEMICOLON) {
                 break;
             }
             if (isset($tokens[$end]['scope_opener']) === true) {
                 $end = $tokens[$end]['scope_closer'];
                 break;
             }
         }
         $next = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, $end + 1, true);
         // Account for a comment on the end of the line.
         for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) {
             if (isset($tokens[$endLine + 1]) === false || $tokens[$endLine]['line'] !== $tokens[$endLine + 1]['line']) {
                 break;
             }
         }
         if ($tokens[$endLine]['code'] !== T_COMMENT) {
             $endLine = $end;
         }
         if ($next !== $end) {
             if ($endLine !== $end) {
                 $phpcsFile->fixer->addContent($endLine, '}');
             } else {
                 $phpcsFile->fixer->addContent($end, ' }');
             }
         } else {
             if ($endLine !== $end) {
                 $phpcsFile->fixer->replaceToken($end, '');
                 $phpcsFile->fixer->addNewlineBefore($endLine);
                 $phpcsFile->fixer->addContent($endLine, '}');
             } else {
                 $phpcsFile->fixer->replaceToken($end, '}');
             }
         }
         $phpcsFile->fixer->endChangeset();
     }
     //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 int
  */
 public function checkAlignment(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $assignments = array();
     $prevAssign = null;
     $lastLine = $tokens[$stackPtr]['line'];
     $maxPadding = null;
     $stopped = null;
     $lastCode = $stackPtr;
     $lastSemi = null;
     $find = PHP_CodeSniffer_Tokens::$assignmentTokens;
     unset($find[T_DOUBLE_ARROW]);
     for ($assign = $stackPtr; $assign < $phpcsFile->numTokens; $assign++) {
         if (isset($find[$tokens[$assign]['code']]) === false) {
             // A blank line indicates that the assignment block has ended.
             if (isset(PHP_CodeSniffer_tokens::$emptyTokens[$tokens[$assign]['code']]) === false) {
                 if ($tokens[$assign]['line'] - $tokens[$lastCode]['line'] > 1) {
                     break;
                 }
                 $lastCode = $assign;
                 if ($tokens[$assign]['code'] === T_SEMICOLON) {
                     if ($tokens[$assign]['conditions'] === $tokens[$stackPtr]['conditions']) {
                         if ($lastSemi !== null && $prevAssign !== null && $lastSemi > $prevAssign) {
                             // This statement did not have an assignment operator in it.
                             break;
                         } else {
                             $lastSemi = $assign;
                         }
                     } else {
                         // Statement is in a different context, so the block is over.
                         break;
                     }
                 }
             }
             //end if
             continue;
         }
         //end if
         if ($assign !== $stackPtr) {
             // Has to be nested inside the same conditions as the first assignment.
             if ($tokens[$assign]['conditions'] !== $tokens[$stackPtr]['conditions']) {
                 break;
             }
             // The assignment's end token must be on the line directly
             // below the current one to be in the same assignment block.
             $lineEnd = $phpcsFile->findNext(T_SEMICOLON, $assign + 1);
             // And the end token must actually belong to this assignment.
             $nextOpener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$scopeOpeners, $assign + 1);
             if ($nextOpener !== false && $nextOpener < $lineEnd) {
                 break;
             }
             // Make sure it is not assigned inside a condition (eg. IF, FOR).
             if (isset($tokens[$assign]['nested_parenthesis']) === true) {
                 foreach ($tokens[$assign]['nested_parenthesis'] as $start => $end) {
                     if (isset($tokens[$start]['parenthesis_owner']) === true) {
                         break 2;
                     }
                 }
             }
         }
         //end if
         $var = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $assign - 1, null, true);
         // Make sure we wouldn't break our max padding length if we
         // aligned with this statement, or they wouldn't break the max
         // padding length if they aligned with us.
         $varEnd = $tokens[$var + 1]['column'];
         $assignLen = $tokens[$assign]['length'];
         if ($assign !== $stackPtr) {
             if ($varEnd + 1 > $assignments[$prevAssign]['assign_col']) {
                 $padding = 1;
                 $assignColumn = $varEnd + 1;
             } else {
                 $padding = $assignments[$prevAssign]['assign_col'] - $varEnd + $assignments[$prevAssign]['assign_len'] - $assignLen;
                 if ($padding === 0) {
                     $padding = 1;
                 }
                 if ($padding > $this->maxPadding) {
                     $stopped = $assign;
                     break;
                 }
                 $assignColumn = $varEnd + $padding;
             }
             //end if
             if ($assignColumn + $assignLen > $assignments[$maxPadding]['assign_col'] + $assignments[$maxPadding]['assign_len']) {
                 $newPadding = $varEnd - $assignments[$maxPadding]['var_end'] + $assignLen - $assignments[$maxPadding]['assign_len'] + 1;
                 if ($newPadding > $this->maxPadding) {
                     $stopped = $assign;
                     break;
                 } else {
                     // New alignment settings for previous assignments.
                     foreach ($assignments as $i => $data) {
                         if ($i === $assign) {
                             break;
                         }
                         $newPadding = $varEnd - $data['var_end'] + $assignLen - $data['assign_len'] + 1;
                         $assignments[$i]['expected'] = $newPadding;
                         $assignments[$i]['assign_col'] = $data['var_end'] + $newPadding;
                     }
                     $padding = 1;
                     $assignColumn = $varEnd + 1;
                 }
             } else {
                 if ($padding > $assignments[$maxPadding]['expected']) {
                     $maxPadding = $assign;
                 }
             }
             //end if
         } else {
             $padding = 1;
             $assignColumn = $varEnd + 1;
             $maxPadding = $assign;
         }
         //end if
         $found = 0;
         if ($tokens[$var + 1]['code'] === T_WHITESPACE) {
             $found = $tokens[$var + 1]['length'];
             if ($found === 0) {
                 // This means a newline was found.
                 $found = 1;
             }
         }
         $assignments[$assign] = array('var_end' => $varEnd, 'assign_len' => $assignLen, 'assign_col' => $assignColumn, 'expected' => $padding, 'found' => $found);
         $lastLine = $tokens[$assign]['line'];
         $prevAssign = $assign;
     }
     //end for
     if (empty($assignments) === true) {
         return $stackPtr;
     }
     $errorGenerated = false;
     foreach ($assignments as $assignment => $data) {
         if ($data['found'] === $data['expected']) {
             continue;
         }
         $expectedText = $data['expected'];
         $expectedText .= $data['expected'] === 1 ? ' space' : ' spaces';
         $foundText = $data['found'];
         if ($foundText === null) {
             $foundText = 'a new line';
         } else {
             $foundText .= $foundText === 1 ? ' space' : ' spaces';
         }
         if (count($assignments) === 1) {
             $type = 'Incorrect';
             $error = 'Equals sign not aligned correctly; expected %s but found %s';
         } else {
             $type = 'NotSame';
             $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s';
         }
         $errorData = array($expectedText, $foundText);
         if ($this->error === true) {
             $fix = $phpcsFile->addFixableError($error, $assignment, $type, $errorData);
         } else {
             $fix = $phpcsFile->addFixableWarning($error, $assignment, $type . 'Warning', $errorData);
         }
         $errorGenerated = true;
         if ($fix === true && $phpcsFile->fixer->enabled === true && $data['found'] !== null) {
             $newContent = str_repeat(' ', $data['expected']);
             if ($data['found'] === 0) {
                 $phpcsFile->fixer->addContentBefore($assignment, $newContent);
             } else {
                 $phpcsFile->fixer->replaceToken($assignment - 1, $newContent);
             }
         }
     }
     //end foreach
     if ($errorGenerated === true) {
         $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'no');
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'yes');
     }
     if ($stopped !== null) {
         return $this->checkAlignment($phpcsFile, $stopped);
     } else {
         return $assignment;
     }
 }
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)
 {
     $tokens = $phpcsFile->getTokens();
     // Support long and short syntax.
     $parenthesis_opener = 'parenthesis_opener';
     $parenthesis_closer = 'parenthesis_closer';
     if ($tokens[$stackPtr]['code'] === T_OPEN_SHORT_ARRAY) {
         $parenthesis_opener = 'bracket_opener';
         $parenthesis_closer = 'bracket_closer';
     }
     $lastItem = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $tokens[$stackPtr][$parenthesis_closer] - 1, $stackPtr, true);
     // Empty array.
     if ($lastItem === $tokens[$stackPtr][$parenthesis_opener]) {
         return;
     }
     // Inline array.
     $isInlineArray = $tokens[$tokens[$stackPtr][$parenthesis_opener]]['line'] === $tokens[$tokens[$stackPtr][$parenthesis_closer]]['line'];
     // Check if the last item in a multiline array has a "closing" comma.
     if ($tokens[$lastItem]['code'] !== T_COMMA && $isInlineArray === false && $tokens[$lastItem + 1]['code'] !== T_CLOSE_PARENTHESIS && $tokens[$lastItem + 1]['code'] !== T_CLOSE_SHORT_ARRAY) {
         $data = array($tokens[$lastItem]['content']);
         $fix = $phpcsFile->addFixableWarning('A comma should follow the last multiline array item. Found: %s', $lastItem, 'CommaLastItem', $data);
         if ($fix === true) {
             $phpcsFile->fixer->addContent($lastItem, ',');
         }
         return;
     }
     if ($isInlineArray === true) {
         // Check if this array contains at least 3 elements and exceeds the 80
         // character line length.
         if ($tokens[$tokens[$stackPtr][$parenthesis_closer]]['column'] > 80) {
             $comma1 = $phpcsFile->findNext(T_COMMA, $stackPtr + 1, $tokens[$stackPtr][$parenthesis_closer]);
             if ($comma1 !== false) {
                 $comma2 = $phpcsFile->findNext(T_COMMA, $comma1 + 1, $tokens[$stackPtr][$parenthesis_closer]);
                 if ($comma2 !== false) {
                     $error = 'If the line declaring an array spans longer than 80 characters, each element should be broken into its own line';
                     $phpcsFile->addError($error, $stackPtr, 'LongLineDeclaration');
                 }
             }
         }
         // Only continue for multi line arrays.
         return;
     }
     // Special case: Opening two multi line structures in one line is ugly.
     if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
         end($tokens[$stackPtr]['nested_parenthesis']);
         $outerNesting = key($tokens[$stackPtr]['nested_parenthesis']);
         if ($tokens[$outerNesting]['line'] === $tokens[$stackPtr]['line']) {
             // We could throw a warning here that the start of the array
             // definition should be on a new line by itself, but we just ignore
             // it for now as this is not defined as standard.
             return;
         }
     }
     // Find the first token on this line.
     $firstLineColumn = $tokens[$stackPtr]['column'];
     for ($i = $stackPtr; $i >= 0; $i--) {
         // Record the first code token on the line.
         if ($tokens[$i]['code'] !== T_WHITESPACE) {
             $firstLineColumn = $tokens[$i]['column'];
             // This could be a multi line string or comment beginning with white
             // spaces.
             $trimmed = ltrim($tokens[$i]['content']);
             if ($trimmed !== $tokens[$i]['content']) {
                 $firstLineColumn = $firstLineColumn + strpos($tokens[$i]['content'], $trimmed);
             }
         }
         // It's the start of the line, so we've found our first php token.
         if ($tokens[$i]['column'] === 1) {
             break;
         }
     }
     $lineStart = $stackPtr;
     // Iterate over all lines of this array.
     while ($lineStart < $tokens[$stackPtr][$parenthesis_closer]) {
         // Find next line start.
         $newLineStart = $lineStart;
         $current_line = $tokens[$newLineStart]['line'];
         while ($current_line == $tokens[$newLineStart]['line']) {
             $newLineStart = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $newLineStart + 1, $tokens[$stackPtr][$parenthesis_closer] + 1, true);
             // Skip nested arrays, they are checked in a next run.
             if ($newLineStart !== false && $tokens[$newLineStart]['code'] === T_OPEN_SHORT_ARRAY) {
                 // Skip the whole line.
                 $current_line++;
                 $newLineStart = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $tokens[$newLineStart][$parenthesis_closer] + 2, $tokens[$stackPtr][$parenthesis_closer] + 1, true);
             }
             if ($newLineStart === false) {
                 break 2;
             }
         }
         //end while
         if ($newLineStart === $tokens[$stackPtr][$parenthesis_closer]) {
             // End of the array reached.
             if ($tokens[$newLineStart]['column'] !== $firstLineColumn) {
                 $error = 'Array closing indentation error, expected %s spaces but found %s';
                 $data = array($firstLineColumn - 1, $tokens[$newLineStart]['column'] - 1);
                 $fix = $phpcsFile->addFixableError($error, $newLineStart, 'ArrayClosingIndentation', $data);
                 if ($fix === true) {
                     $phpcsFile->fixer->replaceToken($newLineStart - 1, str_repeat(' ', $firstLineColumn - 1));
                 }
             }
             break;
         }
         // Skip lines in nested structures.
         // Long array syntax.
         if (isset($tokens[$newLineStart]['nested_parenthesis']) === true) {
             $innerNesting = end($tokens[$newLineStart]['nested_parenthesis']);
             // Skip lines that are part of a multi-line string.
             $isMultiLineString = $tokens[$newLineStart - 1]['code'] === T_CONSTANT_ENCAPSED_STRING && substr($tokens[$newLineStart - 1]['content'], -1) === $phpcsFile->eolChar;
             if ($innerNesting === $tokens[$stackPtr][$parenthesis_closer] && $tokens[$newLineStart]['column'] !== $firstLineColumn + 2 && $isMultiLineString === false) {
                 $error = 'Array indentation error, expected %s spaces but found %s';
                 $data = array($firstLineColumn + 1, $tokens[$newLineStart]['column'] - 1);
                 $fix = $phpcsFile->addFixableError($error, $newLineStart, 'ArrayIndentation', $data);
                 if ($fix === true) {
                     if ($tokens[$newLineStart]['column'] === 1) {
                         $phpcsFile->fixer->addContentBefore($newLineStart, str_repeat(' ', $firstLineColumn + 1));
                     } else {
                         $phpcsFile->fixer->replaceToken($newLineStart - 1, str_repeat(' ', $firstLineColumn + 1));
                     }
                 }
             }
         } else {
             if ($tokens[$newLineStart]['column'] - 1 !== $firstLineColumn + 1) {
                 // Short array syntax.
                 // Skip lines that are part of a multi-line string.
                 $isMultiLineString = $tokens[$newLineStart - 1]['code'] === T_CONSTANT_ENCAPSED_STRING && substr($tokens[$newLineStart - 1]['content'], -1) === $phpcsFile->eolChar;
                 if ($isMultiLineString === false) {
                     $error = 'Array indentation error, expected %s spaces but found %s';
                     $data = array($firstLineColumn + 1, $tokens[$newLineStart]['column'] - 1);
                     $fix = $phpcsFile->addFixableError($error, $newLineStart, 'ArrayIndentation', $data);
                     if ($fix === true) {
                         if ($tokens[$newLineStart]['column'] === 1) {
                             $phpcsFile->fixer->addContentBefore($newLineStart, str_repeat(' ', $firstLineColumn + 1));
                         } else {
                             $phpcsFile->fixer->replaceToken($newLineStart - 1, str_repeat(' ', $firstLineColumn + 1));
                         }
                     }
                 }
             }
         }
         //end if
         $lineStart = $newLineStart;
     }
     //end while
 }