findStartOfStatement() public method

Returns the position of the first non-whitespace token in a statement.
public findStartOfStatement ( integer $start, integer | array $ignore = null ) : integer
$start integer The position to start searching from in the token stack.
$ignore integer | array Token types that should not be considered stop points.
return integer
 /**
  * Processes multi-line calls.
  *
  * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
  * @param int                  $stackPtr    The position of the current token
  *                                          in the stack passed in $tokens.
  * @param int                  $openBracket The position of the opening bracket
  *                                          in the stack passed in $tokens.
  * @param array                $tokens      The stack of tokens that make up
  *                                          the file.
  *
  * @return void
  */
 public function processMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
 {
     // We need to work out how far indented the function
     // call itself is, so we can work out how far to
     // indent the arguments.
     $start = $phpcsFile->findStartOfStatement($stackPtr);
     foreach (array('stackPtr', 'start') as $checkToken) {
         $x = ${$checkToken};
         for ($i = $x - 1; $i >= 0; $i--) {
             if ($tokens[$i]['line'] !== $tokens[$x]['line']) {
                 $i++;
                 break;
             }
         }
         if ($i <= 0) {
             $functionIndent = 0;
         } else {
             if ($tokens[$i]['code'] === T_WHITESPACE) {
                 $functionIndent = strlen($tokens[$i]['content']);
             } else {
                 if ($tokens[$i]['code'] === T_CONSTANT_ENCAPSED_STRING) {
                     $functionIndent = 0;
                 } else {
                     $trimmed = ltrim($tokens[$i]['content']);
                     if ($trimmed === '') {
                         if ($tokens[$i]['code'] === T_INLINE_HTML) {
                             $functionIndent = strlen($tokens[$i]['content']);
                         } else {
                             $functionIndent = $tokens[$i]['column'] - 1;
                         }
                     } else {
                         $functionIndent = strlen($tokens[$i]['content']) - strlen($trimmed);
                     }
                 }
             }
         }
         $varName = $checkToken . 'Indent';
         ${$varName} = $functionIndent;
     }
     //end foreach
     $functionIndent = max($startIndent, $stackPtrIndent);
     $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $openBracket + 1, null, true);
     if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) {
         $error = 'Opening parenthesis of a multi-line function call must be the last content on the line';
         $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpenBracket');
         if ($fix === true) {
             $phpcsFile->fixer->addContent($openBracket, $phpcsFile->eolChar . str_repeat(' ', $functionIndent + $this->indent));
         }
     }
     $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
     $prev = $phpcsFile->findPrevious(T_WHITESPACE, $closeBracket - 1, null, true);
     if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
         $error = 'Closing parenthesis of a multi-line function call must be on a line by itself';
         $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine');
         if ($fix === true) {
             $phpcsFile->fixer->addContentBefore($closeBracket, $phpcsFile->eolChar . str_repeat(' ', $functionIndent + $this->indent));
         }
     }
     // Each line between the parenthesis should be indented n spaces.
     $lastLine = $tokens[$openBracket]['line'];
     $argStart = null;
     $argEnd = null;
     $inArg = false;
     for ($i = $openBracket + 1; $i < $closeBracket; $i++) {
         if ($i > $argStart && $i < $argEnd) {
             $inArg = true;
         } else {
             $inArg = false;
         }
         if ($tokens[$i]['line'] !== $lastLine) {
             $lastLine = $tokens[$i]['line'];
             // Ignore heredoc indentation.
             if (isset(PHP_CodeSniffer_Tokens::$heredocTokens[$tokens[$i]['code']]) === true) {
                 continue;
             }
             // Ignore multi-line string indentation.
             if (isset(PHP_CodeSniffer_Tokens::$stringTokens[$tokens[$i]['code']]) === true && $tokens[$i]['code'] === $tokens[$i - 1]['code']) {
                 continue;
             }
             // Ignore inline HTML.
             if ($tokens[$i]['code'] === T_INLINE_HTML) {
                 continue;
             }
             // We changed lines, so this should be a whitespace indent token, but first make
             // sure it isn't a blank line because we don't need to check indent unless there
             // is actually some code to indent.
             if ($tokens[$i]['code'] === T_WHITESPACE) {
                 $nextCode = $phpcsFile->findNext(T_WHITESPACE, $i + 1, $closeBracket + 1, true);
                 if ($tokens[$nextCode]['line'] !== $lastLine) {
                     if ($inArg === false) {
                         $error = 'Empty lines are not allowed in multi-line function calls';
                         $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine');
                         if ($fix === true) {
                             $phpcsFile->fixer->replaceToken($i, '');
                         }
                     }
                     continue;
                 }
             } else {
                 $nextCode = $i;
             }
             if ($tokens[$nextCode]['line'] === $tokens[$closeBracket]['line']) {
                 // Closing brace needs to be indented to the same level
                 // as the function call.
                 $inArg = false;
                 $expectedIndent = $functionIndent;
             } else {
                 $expectedIndent = $functionIndent + $this->indent;
             }
             if ($tokens[$i]['code'] !== T_WHITESPACE && $tokens[$i]['code'] !== T_DOC_COMMENT_WHITESPACE) {
                 // Just check if it is a multi-line block comment. If so, we can
                 // calculate the indent from the whitespace before the content.
                 if ($tokens[$i]['code'] === T_COMMENT && $tokens[$i - 1]['code'] === T_COMMENT) {
                     $trimmed = ltrim($tokens[$i]['content']);
                     $foundIndent = strlen($tokens[$i]['content']) - strlen($trimmed);
                 } else {
                     $foundIndent = 0;
                 }
             } else {
                 $foundIndent = strlen($tokens[$i]['content']);
             }
             if ($foundIndent < $expectedIndent || $inArg === false && $expectedIndent !== $foundIndent) {
                 $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s';
                 $data = array($expectedIndent, $foundIndent);
                 $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data);
                 if ($fix === true) {
                     $padding = str_repeat(' ', $expectedIndent);
                     if ($foundIndent === 0) {
                         $phpcsFile->fixer->addContentBefore($i, $padding);
                     } else {
                         if ($tokens[$i]['code'] === T_COMMENT) {
                             $comment = $padding . ltrim($tokens[$i]['content']);
                             $phpcsFile->fixer->replaceToken($i, $comment);
                         } else {
                             $phpcsFile->fixer->replaceToken($i, $padding);
                         }
                     }
                 }
             }
             //end if
             if ($inArg === false) {
                 $argStart = $nextCode;
                 $argEnd = $phpcsFile->findEndOfStatement($nextCode);
             }
         }
         //end if
         // If we are within an argument we should be ignoring commas
         // as these are not signaling the end of an argument.
         if ($inArg === false && $tokens[$i]['code'] === T_COMMA) {
             $next = $phpcsFile->findNext(array(T_WHITESPACE, T_COMMENT), $i + 1, $closeBracket, true);
             if ($next === false) {
                 continue;
             }
             if ($this->allowMultipleArguments === false) {
                 // Comma has to be the last token on the line.
                 if ($tokens[$i]['line'] === $tokens[$next]['line']) {
                     $error = 'Only one argument is allowed per line in a multi-line function call';
                     $fix = $phpcsFile->addFixableError($error, $next, 'MultipleArguments');
                     if ($fix === true) {
                         $phpcsFile->fixer->beginChangeset();
                         for ($x = $next - 1; $x > $i; $x--) {
                             if ($tokens[$x]['code'] !== T_WHITESPACE) {
                                 break;
                             }
                             $phpcsFile->fixer->replaceToken($x, '');
                         }
                         $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar . str_repeat(' ', $functionIndent + $this->indent));
                         $phpcsFile->fixer->endChangeset();
                     }
                 }
             }
             //end if
             $argStart = $next;
             $argEnd = $phpcsFile->findEndOfStatement($next);
         }
         //end if
     }
     //end for
 }
 /**
  * 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)
 {
     if ($this->_tabWidth === null) {
         $cliValues = $phpcsFile->phpcs->cli->getCommandLineValues();
         if (isset($cliValues['tabWidth']) === false || $cliValues['tabWidth'] === 0) {
             // We have no idea how wide tabs are, so assume 4 spaces for fixing.
             // It shouldn't really matter because indent checks elsewhere in the
             // standard should fix things up.
             $this->_tabWidth = 4;
         } else {
             $this->_tabWidth = $cliValues['tabWidth'];
         }
     }
     $currentIndent = 0;
     $lastOpenTag = $stackPtr;
     $lastCloseTag = null;
     $openScopes = array();
     $adjustments = array();
     $tokens = $phpcsFile->getTokens();
     $currentIndent = $tokens[$stackPtr]['column'] - 1;
     if (empty($this->_ignoreIndentationTokens) === true) {
         $this->_ignoreIndentationTokens = array(T_INLINE_HTML => true);
         foreach ($this->ignoreIndentationTokens as $token) {
             if (is_int($token) === false) {
                 if (defined($token) === false) {
                     continue;
                 }
                 $token = constant($token);
             }
             $this->_ignoreIndentationTokens[$token] = true;
         }
     }
     //end if
     $this->exact = (bool) $this->exact;
     $this->tabIndent = (bool) $this->tabIndent;
     for ($i = $stackPtr + 1; $i < $phpcsFile->numTokens; $i++) {
         if ($i === false) {
             // Something has gone very wrong; maybe a parse error.
             break;
         }
         $checkToken = null;
         $checkIndent = null;
         $exact = (bool) $this->exact;
         if ($exact === true && isset($tokens[$i]['nested_parenthesis']) === true) {
             // Don't check indents exactly between parenthesis as they
             // tend to have custom rules, such as with multi-line function calls
             // and control structure conditions.
             $exact = false;
         }
         // Detect line changes and figure out where the indent is.
         if ($tokens[$i]['column'] === 1) {
             $trimmed = ltrim($tokens[$i]['content']);
             if ($trimmed === '') {
                 if (isset($tokens[$i + 1]) === true && $tokens[$i]['line'] === $tokens[$i + 1]['line']) {
                     $checkToken = $i + 1;
                     $tokenIndent = $tokens[$i + 1]['column'] - 1;
                 }
             } else {
                 $checkToken = $i;
                 $tokenIndent = strlen($tokens[$i]['content']) - strlen($trimmed);
             }
         }
         // Closing parenthesis should just be indented to at least
         // the same level as where they were opened (but can be more).
         if ($checkToken !== null && $tokens[$checkToken]['code'] === T_CLOSE_PARENTHESIS && isset($tokens[$checkToken]['parenthesis_opener']) === true) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Closing parenthesis found on line {$line}" . PHP_EOL;
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$checkToken]['parenthesis_opener'], true);
             $checkIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $checkIndent += $adjustments[$first];
             }
             $exact = false;
             if ($this->_debug === true) {
                 $line = $tokens[$first]['line'];
                 $type = $tokens[$first]['type'];
                 echo "\t* first token on line {$line} is {$type} *" . PHP_EOL;
             }
             $prev = $phpcsFile->findStartOfStatement($first);
             if ($prev !== $first) {
                 // This is not the start of the statement.
                 if ($this->_debug === true) {
                     $line = $tokens[$prev]['line'];
                     $type = $tokens[$prev]['type'];
                     echo "\t* previous is {$type} on line {$line} *" . PHP_EOL;
                 }
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
                 $prev = $phpcsFile->findStartOfStatement($first);
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
                 if ($this->_debug === true) {
                     $line = $tokens[$first]['line'];
                     $type = $tokens[$first]['type'];
                     echo "\t* amended first token is {$type} on line {$line} *" . PHP_EOL;
                 }
             }
             // Don't force current indent to divisible because there could be custom
             // rules in place between parenthesis, such as with arrays.
             $currentIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             if ($this->_debug === true) {
                 echo "\t=> checking indent of {$checkIndent}; main indent set to {$currentIndent}" . PHP_EOL;
             }
         }
         //end if
         // Closing parenthesis should just be indented to at least
         // the same level as where they were opened (but can be more).
         if ($checkToken !== null && $tokens[$checkToken]['code'] === T_CLOSE_SHORT_ARRAY) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Closing short array bracket found on line {$line}" . PHP_EOL;
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$checkToken]['bracket_opener'], true);
             $checkIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $checkIndent += $adjustments[$first];
             }
             $exact = false;
             if ($this->_debug === true) {
                 $line = $tokens[$first]['line'];
                 $type = $tokens[$first]['type'];
                 echo "\t* first token on line {$line} is {$type} *" . PHP_EOL;
             }
             $prev = $phpcsFile->findStartOfStatement($first);
             if ($prev !== $first) {
                 // This is not the start of the statement.
                 if ($this->_debug === true) {
                     $line = $tokens[$prev]['line'];
                     $type = $tokens[$prev]['type'];
                     echo "\t* previous is {$type} on line {$line} *" . PHP_EOL;
                 }
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
                 $prev = $phpcsFile->findStartOfStatement($first);
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
                 if ($this->_debug === true) {
                     $line = $tokens[$first]['line'];
                     $type = $tokens[$first]['type'];
                     echo "\t* amended first token is {$type} on line {$line} *" . PHP_EOL;
                 }
             }
             // Don't force current indent to be divisible because there could be custom
             // rules in place for arrays.
             $currentIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             if ($this->_debug === true) {
                 echo "\t=> checking indent of {$checkIndent}; main indent set to {$currentIndent}" . PHP_EOL;
             }
         }
         //end if
         // Adjust lines within scopes while auto-fixing.
         if ($checkToken !== null && $exact === false && (empty($tokens[$checkToken]['conditions']) === false || isset($tokens[$checkToken]['scope_opener']) === true && $tokens[$checkToken]['scope_opener'] === $checkToken)) {
             if (empty($tokens[$checkToken]['conditions']) === false) {
                 end($tokens[$checkToken]['conditions']);
                 $condition = key($tokens[$checkToken]['conditions']);
             } else {
                 $condition = $tokens[$checkToken]['scope_condition'];
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $condition, true);
             if (isset($adjustments[$first]) === true && ($adjustments[$first] < 0 && $tokenIndent > $currentIndent || $adjustments[$first] > 0 && $tokenIndent < $currentIndent)) {
                 $padding = $tokenIndent + $adjustments[$first];
                 if ($padding > 0) {
                     if ($this->tabIndent === true) {
                         $numTabs = floor($padding / $this->_tabWidth);
                         $numSpaces = $padding - $numTabs * $this->_tabWidth;
                         $padding = str_repeat("\t", $numTabs) . str_repeat(' ', $numSpaces);
                     } else {
                         $padding = str_repeat(' ', $padding);
                     }
                 } else {
                     $padding = '';
                 }
                 if ($checkToken === $i) {
                     $phpcsFile->fixer->replaceToken($checkToken, $padding . $trimmed);
                 } else {
                     // Easier to just replace the entire indent.
                     $phpcsFile->fixer->replaceToken($checkToken - 1, $padding);
                 }
                 if ($this->_debug === true) {
                     $length = strlen($padding);
                     $line = $tokens[$checkToken]['line'];
                     $type = $tokens[$checkToken]['type'];
                     echo "Indent adjusted to {$length} for {$type} on line {$line}" . PHP_EOL;
                 }
                 $adjustments[$checkToken] = $adjustments[$first];
                 if ($this->_debug === true) {
                     $line = $tokens[$checkToken]['line'];
                     $type = $tokens[$checkToken]['type'];
                     echo "\t=> Add adjustment of " . $adjustments[$checkToken] . " for token {$checkToken} ({$type}) on line {$line}" . PHP_EOL;
                 }
             }
             //end if
         }
         //end if
         // Scope closers reset the required indent to the same level as the opening condition.
         if ($checkToken !== null && isset($openScopes[$checkToken]) === true || isset($tokens[$checkToken]['scope_condition']) === true && isset($tokens[$checkToken]['scope_closer']) === true && $tokens[$checkToken]['scope_closer'] === $checkToken && $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['scope_opener']]['line'] || ($checkToken === null && isset($openScopes[$i]) === true || isset($tokens[$i]['scope_condition']) === true && isset($tokens[$i]['scope_closer']) === true && $tokens[$i]['scope_closer'] === $i && $tokens[$i]['line'] !== $tokens[$tokens[$i]['scope_opener']]['line'])) {
             if ($this->_debug === true) {
                 if ($checkToken === null) {
                     $type = $tokens[$tokens[$i]['scope_condition']]['type'];
                     $line = $tokens[$i]['line'];
                 } else {
                     $type = $tokens[$tokens[$checkToken]['scope_condition']]['type'];
                     $line = $tokens[$checkToken]['line'];
                 }
                 echo "Close scope ({$type}) on line {$line}" . PHP_EOL;
             }
             $scopeCloser = $checkToken;
             if ($scopeCloser === null) {
                 $scopeCloser = $i;
             } else {
                 array_pop($openScopes);
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$scopeCloser]['scope_condition'], true);
             $currentIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             // Make sure it is divisible by our expected indent.
             if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'] !== T_CLOSURE) {
                 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             }
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
             // We only check the indent of scope closers if they are
             // curly braces because other constructs tend to have different rules.
             if ($tokens[$scopeCloser]['code'] === T_CLOSE_CURLY_BRACKET) {
                 $exact = true;
             } else {
                 $checkToken = null;
             }
         }
         //end if
         // Handle scope for JS object notation.
         if ($phpcsFile->tokenizerType === 'JS' && ($checkToken !== null && $tokens[$checkToken]['code'] === T_CLOSE_OBJECT && $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['bracket_opener']]['line'] || $checkToken === null && $tokens[$i]['code'] === T_CLOSE_OBJECT && $tokens[$i]['line'] !== $tokens[$tokens[$i]['bracket_opener']]['line'])) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Close JS object on line {$line}" . PHP_EOL;
             }
             $scopeCloser = $checkToken;
             if ($scopeCloser === null) {
                 $scopeCloser = $i;
             } else {
                 array_pop($openScopes);
             }
             $parens = 0;
             if (isset($tokens[$scopeCloser]['nested_parenthesis']) === true && empty($tokens[$scopeCloser]['nested_parenthesis']) === false) {
                 end($tokens[$scopeCloser]['nested_parenthesis']);
                 $parens = key($tokens[$scopeCloser]['nested_parenthesis']);
                 if ($this->_debug === true) {
                     $line = $tokens[$parens]['line'];
                     echo "\t* token has nested parenthesis {$parens} on line {$line} *" . PHP_EOL;
                 }
             }
             $condition = 0;
             if (isset($tokens[$scopeCloser]['conditions']) === true && empty($tokens[$scopeCloser]['conditions']) === false) {
                 end($tokens[$scopeCloser]['conditions']);
                 $condition = key($tokens[$scopeCloser]['conditions']);
                 if ($this->_debug === true) {
                     $line = $tokens[$condition]['line'];
                     $type = $tokens[$condition]['type'];
                     echo "\t* token is inside condition {$condition} ({$type}) on line {$line} *" . PHP_EOL;
                 }
             }
             if ($parens > $condition) {
                 if ($this->_debug === true) {
                     echo "\t* using parenthesis *" . PHP_EOL;
                 }
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parens, true);
                 $condition = 0;
             } else {
                 if ($condition > 0) {
                     if ($this->_debug === true) {
                         echo "\t* using condition *" . PHP_EOL;
                     }
                     $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $condition, true);
                     $parens = 0;
                 } else {
                     if ($this->_debug === true) {
                         $line = $tokens[$tokens[$scopeCloser]['bracket_opener']]['line'];
                         echo "\t* token is not in parenthesis or condition; using opener on line {$line} *" . PHP_EOL;
                     }
                     $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$scopeCloser]['bracket_opener'], true);
                 }
             }
             //end if
             $currentIndent = $tokens[$first]['column'] - 1;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             if ($parens > 0 || $condition > 0) {
                 $checkIndent = $tokens[$first]['column'] - 1;
                 if (isset($adjustments[$first]) === true) {
                     $checkIndent += $adjustments[$first];
                 }
                 if ($condition > 0) {
                     $checkIndent += $this->indent;
                     $currentIndent += $this->indent;
                     $exact = true;
                 }
             } else {
                 $checkIndent = $currentIndent;
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             $checkIndent = (int) (ceil($checkIndent / $this->indent) * $this->indent);
             if ($this->_debug === true) {
                 echo "\t=> checking indent of {$checkIndent}; main indent set to {$currentIndent}" . PHP_EOL;
             }
         }
         //end if
         if ($checkToken !== null && isset(PHP_CodeSniffer_Tokens::$scopeOpeners[$tokens[$checkToken]['code']]) === true && in_array($tokens[$checkToken]['code'], $this->nonIndentingScopes) === false && isset($tokens[$checkToken]['scope_opener']) === true) {
             $exact = true;
             $lastOpener = null;
             if (empty($openScopes) === false) {
                 end($openScopes);
                 $lastOpener = current($openScopes);
             }
             // A scope opener that shares a closer with another token (like multiple
             // CASEs using the same BREAK) needs to reduce the indent level so its
             // indent is checked correctly. It will then increase the indent again
             // (as all openers do) after being checked.
             if ($lastOpener !== null && isset($tokens[$lastOpener]['scope_closer']) === true && $tokens[$lastOpener]['level'] === $tokens[$checkToken]['level'] && $tokens[$lastOpener]['scope_closer'] === $tokens[$checkToken]['scope_closer']) {
                 $currentIndent -= $this->indent;
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     echo "Shared closer found on line {$line}" . PHP_EOL;
                     echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
                 }
             }
             if ($tokens[$checkToken]['code'] === T_CLOSURE && $tokenIndent > $currentIndent) {
                 // The opener is indented more than needed, which is fine.
                 // But just check that it is divisible by our expected indent.
                 $checkIndent = (int) (ceil($tokenIndent / $this->indent) * $this->indent);
                 $exact = false;
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     echo "Closure found on line {$line}" . PHP_EOL;
                     echo "\t=> checking indent of {$checkIndent}; main indent remains at {$currentIndent}" . PHP_EOL;
                 }
             }
         }
         //end if
         // JS property indentation has to be exact or else if will break
         // things like function and object indentation.
         if ($checkToken !== null && $tokens[$checkToken]['code'] === T_PROPERTY) {
             $exact = true;
         }
         // PHP tags needs to be indented to exact column positions
         // so they don't cause problems with indent checks for the code
         // within them, but they don't need to line up with the current indent.
         if ($checkToken !== null && ($tokens[$checkToken]['code'] === T_OPEN_TAG || $tokens[$checkToken]['code'] === T_OPEN_TAG_WITH_ECHO || $tokens[$checkToken]['code'] === T_CLOSE_TAG)) {
             $exact = true;
             $checkIndent = $tokens[$checkToken]['column'] - 1;
             $checkIndent = (int) (ceil($checkIndent / $this->indent) * $this->indent);
         }
         // Check the line indent.
         if ($checkIndent === null) {
             $checkIndent = $currentIndent;
         }
         $adjusted = false;
         if ($checkToken !== null && isset($this->_ignoreIndentationTokens[$tokens[$checkToken]['code']]) === false && ($tokenIndent !== $checkIndent && $exact === true || $tokenIndent < $checkIndent && $exact === false)) {
             $type = 'IncorrectExact';
             $error = 'Line indented incorrectly; expected ';
             if ($exact === false) {
                 $error .= 'at least ';
                 $type = 'Incorrect';
             }
             if ($this->tabIndent === true) {
                 $error .= '%s tabs, found %s';
                 $data = array(floor($checkIndent / $this->_tabWidth), floor($tokenIndent / $this->_tabWidth));
             } else {
                 $error .= '%s spaces, found %s';
                 $data = array($checkIndent, $tokenIndent);
             }
             if ($this->_debug === true) {
                 $line = $tokens[$checkToken]['line'];
                 $message = vsprintf($error, $data);
                 echo "[Line {$line}] {$message}" . PHP_EOL;
             }
             $fix = $phpcsFile->addFixableError($error, $checkToken, $type, $data);
             if ($fix === true || $this->_debug === true) {
                 $padding = '';
                 if ($this->tabIndent === true) {
                     $numTabs = floor($checkIndent / $this->_tabWidth);
                     if ($numTabs > 0) {
                         $numSpaces = $checkIndent - $numTabs * $this->_tabWidth;
                         $padding = str_repeat("\t", $numTabs) . str_repeat(' ', $numSpaces);
                     }
                 } else {
                     if ($checkIndent > 0) {
                         $padding = str_repeat(' ', $checkIndent);
                     }
                 }
                 if ($checkToken === $i) {
                     $accepted = $phpcsFile->fixer->replaceToken($checkToken, $padding . $trimmed);
                 } else {
                     // Easier to just replace the entire indent.
                     $accepted = $phpcsFile->fixer->replaceToken($checkToken - 1, $padding);
                 }
                 if ($accepted === true) {
                     $adjustments[$checkToken] = $checkIndent - $tokenIndent;
                     if ($this->_debug === true) {
                         $line = $tokens[$checkToken]['line'];
                         $type = $tokens[$checkToken]['type'];
                         echo "\t=> Add adjustment of " . $adjustments[$checkToken] . " for token {$checkToken} ({$type}) on line {$line}" . PHP_EOL;
                     }
                 }
             }
             //end if
         }
         //end if
         if ($checkToken !== null) {
             $i = $checkToken;
         }
         // Completely skip here/now docs as the indent is a part of the
         // content itself.
         if ($tokens[$i]['code'] === T_START_HEREDOC || $tokens[$i]['code'] === T_START_NOWDOC) {
             $i = $phpcsFile->findNext(array(T_END_HEREDOC, T_END_NOWDOC), $i + 1);
             continue;
         }
         // Completely skip multi-line strings as the indent is a part of the
         // content itself.
         if ($tokens[$i]['code'] === T_CONSTANT_ENCAPSED_STRING || $tokens[$i]['code'] === T_DOUBLE_QUOTED_STRING) {
             $i = $phpcsFile->findNext($tokens[$i]['code'], $i + 1, null, true);
             $i--;
             continue;
         }
         // Completely skip doc comments as they tend to have complex
         // indentation rules.
         if ($tokens[$i]['code'] === T_DOC_COMMENT_OPEN_TAG) {
             $i = $tokens[$i]['comment_closer'];
             continue;
         }
         // Open tags reset the indent level.
         if ($tokens[$i]['code'] === T_OPEN_TAG || $tokens[$i]['code'] === T_OPEN_TAG_WITH_ECHO) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Open PHP tag found on line {$line}" . PHP_EOL;
             }
             if ($checkToken === null) {
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
                 $currentIndent = strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']));
             } else {
                 $currentIndent = $tokens[$i]['column'] - 1;
             }
             $lastOpenTag = $i;
             if (isset($adjustments[$i]) === true) {
                 $currentIndent += $adjustments[$i];
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
             continue;
         }
         //end if
         // Close tags reset the indent level, unless they are closing a tag
         // opened on the same line.
         if ($tokens[$i]['code'] === T_CLOSE_TAG) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Close PHP tag found on line {$line}" . PHP_EOL;
             }
             if ($tokens[$lastOpenTag]['line'] !== $tokens[$i]['line']) {
                 $currentIndent = $tokens[$i]['column'] - 1;
                 $lastCloseTag = $i;
             } else {
                 if ($lastCloseTag === null) {
                     $currentIndent = 0;
                 } else {
                     $currentIndent = $tokens[$lastCloseTag]['column'] - 1;
                 }
             }
             if (isset($adjustments[$i]) === true) {
                 $currentIndent += $adjustments[$i];
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
             continue;
         }
         //end if
         // Closures set the indent based on their own indent level.
         if ($tokens[$i]['code'] === T_CLOSURE) {
             $closer = $tokens[$i]['scope_closer'];
             if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     echo "* ignoring single-line closure on line {$line}" . PHP_EOL;
                 }
                 $i = $closer;
                 continue;
             }
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Open closure on line {$line}" . PHP_EOL;
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
             $currentIndent = $tokens[$first]['column'] - 1 + $this->indent;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (floor($currentIndent / $this->indent) * $this->indent);
             $i = $tokens[$i]['scope_opener'];
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
             continue;
         }
         //end if
         // Scope openers increase the indent level.
         if (isset($tokens[$i]['scope_condition']) === true && isset($tokens[$i]['scope_opener']) === true && $tokens[$i]['scope_opener'] === $i) {
             $closer = $tokens[$i]['scope_closer'];
             if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     $type = $tokens[$i]['type'];
                     echo "* ignoring single-line {$type} on line {$line}" . PHP_EOL;
                 }
                 $i = $closer;
                 continue;
             }
             $condition = $tokens[$tokens[$i]['scope_condition']]['code'];
             if (isset(PHP_CodeSniffer_Tokens::$scopeOpeners[$condition]) === true && in_array($condition, $this->nonIndentingScopes) === false) {
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     $type = $tokens[$tokens[$i]['scope_condition']]['type'];
                     echo "Open scope ({$type}) on line {$line}" . PHP_EOL;
                 }
                 $currentIndent += $this->indent;
                 $openScopes[$tokens[$i]['scope_closer']] = $tokens[$i]['scope_condition'];
                 if ($this->_debug === true) {
                     echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
                 }
                 continue;
             }
         }
         //end if
         // JS objects set the indent level.
         if ($phpcsFile->tokenizerType === 'JS' && $tokens[$i]['code'] === T_OBJECT) {
             $closer = $tokens[$i]['bracket_closer'];
             if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
                 if ($this->_debug === true) {
                     $line = $tokens[$i]['line'];
                     echo "* ignoring single-line JS object on line {$line}" . PHP_EOL;
                 }
                 $i = $closer;
                 continue;
             }
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Open JS object on line {$line}" . PHP_EOL;
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
             $currentIndent = $tokens[$first]['column'] - 1 + $this->indent;
             if (isset($adjustments[$first]) === true) {
                 $currentIndent += $adjustments[$first];
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
             continue;
         }
         //end if
         // Closing a closure.
         if (isset($tokens[$i]['scope_condition']) === true && $tokens[$i]['scope_closer'] === $i && $tokens[$tokens[$i]['scope_condition']]['code'] === T_CLOSURE) {
             if ($this->_debug === true) {
                 $line = $tokens[$i]['line'];
                 echo "Close closure on line {$line}" . PHP_EOL;
             }
             $prev = false;
             $object = 0;
             if ($phpcsFile->tokenizerType === 'JS') {
                 $conditions = $tokens[$i]['conditions'];
                 krsort($conditions, SORT_NUMERIC);
                 foreach ($conditions as $token => $condition) {
                     if ($condition === T_OBJECT) {
                         $object = $token;
                         break;
                     }
                 }
                 if ($this->_debug === true && $object !== 0) {
                     $line = $tokens[$object]['line'];
                     echo "\t* token is inside JS object {$object} on line {$line} *" . PHP_EOL;
                 }
             }
             $parens = 0;
             if (isset($tokens[$i]['nested_parenthesis']) === true && empty($tokens[$i]['nested_parenthesis']) === false) {
                 end($tokens[$i]['nested_parenthesis']);
                 $parens = key($tokens[$i]['nested_parenthesis']);
                 if ($this->_debug === true) {
                     $line = $tokens[$parens]['line'];
                     echo "\t* token has nested parenthesis {$parens} on line {$line} *" . PHP_EOL;
                 }
             }
             $condition = 0;
             if (isset($tokens[$i]['conditions']) === true && empty($tokens[$i]['conditions']) === false) {
                 end($tokens[$i]['conditions']);
                 $condition = key($tokens[$i]['conditions']);
                 if ($this->_debug === true) {
                     $line = $tokens[$condition]['line'];
                     $type = $tokens[$condition]['type'];
                     echo "\t* token is inside condition {$condition} ({$type}) on line {$line} *" . PHP_EOL;
                 }
             }
             if ($parens > $object && $parens > $condition) {
                 if ($this->_debug === true) {
                     echo "\t* using parenthesis *" . PHP_EOL;
                 }
                 $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $parens - 1, null, true);
                 $object = 0;
                 $condition = 0;
             } else {
                 if ($object > 0 && $object >= $condition) {
                     if ($this->_debug === true) {
                         echo "\t* using object *" . PHP_EOL;
                     }
                     $prev = $object;
                     $parens = 0;
                     $condition = 0;
                 } else {
                     if ($condition > 0) {
                         if ($this->_debug === true) {
                             echo "\t* using condition *" . PHP_EOL;
                         }
                         $prev = $condition;
                         $object = 0;
                         $parens = 0;
                     }
                 }
             }
             //end if
             if ($prev === false) {
                 $prev = $phpcsFile->findPrevious(array(T_EQUAL, T_RETURN), $tokens[$i]['scope_condition'] - 1, null, false, null, true);
                 if ($prev === false) {
                     $prev = $i;
                     if ($this->_debug === true) {
                         echo "\t* could not find a previous T_EQUAL or T_RETURN token; will use current token *" . PHP_EOL;
                     }
                 }
             }
             if ($this->_debug === true) {
                 $line = $tokens[$prev]['line'];
                 $type = $tokens[$prev]['type'];
                 echo "\t* previous token is {$type} on line {$line} *" . PHP_EOL;
             }
             $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
             if ($this->_debug === true) {
                 $line = $tokens[$first]['line'];
                 $type = $tokens[$first]['type'];
                 echo "\t* first token on line {$line} is {$type} *" . PHP_EOL;
             }
             $prev = $phpcsFile->findStartOfStatement($first);
             if ($prev !== $first) {
                 // This is not the start of the statement.
                 if ($this->_debug === true) {
                     $line = $tokens[$prev]['line'];
                     $type = $tokens[$prev]['type'];
                     echo "\t* amended previous is {$type} on line {$line} *" . PHP_EOL;
                 }
                 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
                 if ($this->_debug === true) {
                     $line = $tokens[$first]['line'];
                     $type = $tokens[$first]['type'];
                     echo "\t* amended first token is {$type} on line {$line} *" . PHP_EOL;
                 }
             }
             $currentIndent = $tokens[$first]['column'] - 1;
             if ($object > 0 || $condition > 0) {
                 $currentIndent += $this->indent;
             }
             // Make sure it is divisible by our expected indent.
             $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
             if ($this->_debug === true) {
                 echo "\t=> indent set to {$currentIndent}" . PHP_EOL;
             }
         }
         //end if
     }
     //end for
     // Don't process the rest of the file.
     return $phpcsFile->numTokens;
 }
 /**
  * Processes a multi-line array definition.
  *
  * @param PHP_CodeSniffer_File $phpcsFile  The current file being checked.
  * @param int                  $stackPtr   The position of the current token
  *                                         in the stack passed in $tokens.
  * @param int                  $arrayStart The token that starts the array definition.
  * @param int                  $arrayEnd   The token that ends the array definition.
  *
  * @return void
  */
 public function processMultiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $arrayStart, $arrayEnd)
 {
     $tokens = $phpcsFile->getTokens();
     $keywordStart = $tokens[$stackPtr]['column'];
     // Check the closing bracket is on a new line.
     $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $arrayEnd - 1, $arrayStart, true);
     if ($tokens[$lastContent]['line'] === $tokens[$arrayEnd]['line']) {
         $error = 'Closing bracket of array declaration must be on a new line';
         $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNewLine');
         if ($fix === true) {
             $phpcsFile->fixer->addNewlineBefore($arrayEnd);
         }
     }
     $nextToken = $stackPtr;
     $keyUsed = false;
     $singleUsed = false;
     $indices = [];
     $maxLength = 0;
     if ($tokens[$stackPtr]['code'] === T_ARRAY) {
         $lastToken = $tokens[$stackPtr]['parenthesis_opener'];
     } else {
         $lastToken = $stackPtr;
     }
     // Find all the double arrows that reside in this scope.
     for ($nextToken = $stackPtr + 1; $nextToken < $arrayEnd; $nextToken++) {
         // Skip bracketed statements, like function calls.
         if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS && (isset($tokens[$nextToken]['parenthesis_owner']) === false || $tokens[$nextToken]['parenthesis_owner'] !== $stackPtr)) {
             $nextToken = $tokens[$nextToken]['parenthesis_closer'];
             continue;
         }
         if ($tokens[$nextToken]['code'] === T_ARRAY) {
             // Let subsequent calls of this test handle nested arrays.
             if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
                 $indices[] = ['value' => $nextToken];
                 $lastToken = $nextToken;
             }
             $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer'];
             $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextToken + 1, null, true);
             if ($tokens[$nextToken]['code'] !== T_COMMA) {
                 $nextToken--;
             } else {
                 $lastToken = $nextToken;
             }
             continue;
         }
         if ($tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY) {
             // Let subsequent calls of this test handle nested arrays.
             if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
                 $indices[] = ['value' => $nextToken];
                 $lastToken = $nextToken;
             }
             $nextToken = $tokens[$nextToken]['bracket_closer'];
             $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextToken + 1, null, true);
             if ($tokens[$nextToken]['code'] !== T_COMMA) {
                 $nextToken--;
             } else {
                 $lastToken = $nextToken;
             }
             continue;
         }
         if ($tokens[$nextToken]['code'] === T_CLOSURE) {
             if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
                 $indices[] = ['value' => $nextToken];
                 $lastToken = $nextToken;
             }
             $nextToken = $tokens[$nextToken]['scope_closer'];
             $nextToken = $phpcsFile->findNext(T_WHITESPACE, $nextToken + 1, null, true);
             if ($tokens[$nextToken]['code'] !== T_COMMA) {
                 $nextToken--;
             } else {
                 $lastToken = $nextToken;
             }
             continue;
         }
         if ($tokens[$nextToken]['code'] !== T_DOUBLE_ARROW && $tokens[$nextToken]['code'] !== T_COMMA) {
             continue;
         }
         $currentEntry = [];
         if ($tokens[$nextToken]['code'] === T_COMMA) {
             $stackPtrCount = 0;
             if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
                 $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']);
             }
             $commaCount = 0;
             if (isset($tokens[$nextToken]['nested_parenthesis']) === true) {
                 $commaCount = count($tokens[$nextToken]['nested_parenthesis']);
                 if ($tokens[$stackPtr]['code'] === T_ARRAY) {
                     // Remove parenthesis that are used to define the array.
                     $commaCount--;
                 }
             }
             if ($commaCount > $stackPtrCount) {
                 // This comma is inside more parenthesis than the ARRAY keyword,
                 // then there it is actually a comma used to separate arguments
                 // in a function call.
                 continue;
             }
             if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) {
                 $error = 'No key specified for array entry; first entry specifies key';
                 $phpcsFile->addError($error, $nextToken, 'NoKeySpecified');
                 return;
             }
             if ($keyUsed === false) {
                 if ($tokens[$nextToken - 1]['code'] === T_WHITESPACE) {
                     $content = $tokens[$nextToken - 2]['content'];
                     if ($tokens[$nextToken - 1]['content'] === $phpcsFile->eolChar) {
                         $spaceLength = 'newline';
                     } else {
                         $spaceLength = $tokens[$nextToken - 1]['length'];
                     }
                     $error = 'Expected 0 spaces between "%s" and comma; %s found';
                     $data = [$content, $spaceLength];
                     $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data);
                     if ($fix === true) {
                         $phpcsFile->fixer->replaceToken($nextToken - 1, '');
                     }
                 }
                 $valueContent = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $lastToken + 1, $nextToken, true);
                 $indices[] = ['value' => $valueContent];
                 $singleUsed = true;
             }
             //end if
             $lastToken = $nextToken;
             continue;
         }
         //end if
         if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) {
             if ($tokens[$nextToken - 1]['code'] !== T_WHITESPACE) {
                 $content = $tokens[$nextToken - 1]['content'];
                 $error = 'Expected 1 space between "%s" and double arrow; 0 found';
                 $data = [$content];
                 $phpcsFile->addError($error, $nextToken, 'NoSpaceAfterComma', $data);
             } else {
                 $spaceLength = $tokens[$nextToken - 1]['length'];
                 if ($spaceLength !== 1) {
                     $content = $tokens[$nextToken - 2]['content'];
                     $error = 'Expected 1 space between "%s" and double arrow; %s found';
                     $data = [$content, $spaceLength];
                     $phpcsFile->addError($error, $nextToken, 'SpaceAfterComma', $data);
                 }
             }
             //end if
             if ($tokens[$nextToken + 1]['code'] !== T_WHITESPACE) {
                 $content = $tokens[$nextToken + 1]['content'];
                 $error = 'Expected 1 space between double arrow and "%s"; 0 found';
                 $data = [$content];
                 $phpcsFile->addError($error, $nextToken, 'NoSpaceAfterDoubleArrow', $data);
             } else {
                 $spaceLength = $tokens[$nextToken + 1]['length'];
                 if ($spaceLength !== 1) {
                     $content = $tokens[$nextToken + 2]['content'];
                     $error = 'Expected 1 space between double arrow and "%s"; %s found';
                     $data = [$content, $spaceLength];
                     $phpcsFile->addError($error, $nextToken, 'SpaceAfterDoubleArrow', $data);
                 }
             }
             //end if
             if ($singleUsed === true) {
                 $error = 'Key specified for array entry; first entry has no key';
                 $phpcsFile->addError($error, $nextToken, 'KeySpecified');
                 return;
             }
             $currentEntry['arrow'] = $nextToken;
             $keyUsed = true;
             // Find the start of index that uses this double arrow.
             $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, $nextToken - 1, $arrayStart, true);
             $indexStart = $phpcsFile->findStartOfStatement($indexEnd);
             if ($indexStart === $indexEnd) {
                 $currentEntry['index'] = $indexEnd;
                 $currentEntry['index_content'] = $tokens[$indexEnd]['content'];
             } else {
                 $currentEntry['index'] = $indexStart;
                 $currentEntry['index_content'] = $phpcsFile->getTokensAsString($indexStart, $indexEnd - $indexStart + 1);
             }
             $indexLength = strlen($currentEntry['index_content']);
             if ($maxLength < $indexLength) {
                 $maxLength = $indexLength;
             }
             // Find the value of this index.
             $nextContent = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $nextToken + 1, $arrayEnd, true);
             $currentEntry['value'] = $nextContent;
             $indices[] = $currentEntry;
             $lastToken = $nextToken;
         }
         //end if
     }
     //end for
     // Check for mutli-line arrays that should be single-line.
     $singleValue = false;
     if (empty($indices) === true) {
         $singleValue = true;
     } elseif (count($indices) === 1 && $tokens[$lastToken]['code'] === T_COMMA) {
         // There may be another array value without a comma.
         $exclude = PHP_CodeSniffer_Tokens::$emptyTokens;
         $exclude[] = T_COMMA;
         $nextContent = $phpcsFile->findNext($exclude, $indices[0]['value'] + 1, $arrayEnd, true);
         if ($nextContent === false) {
             $singleValue = true;
         }
     }
     if ($singleValue === true) {
         // Array cannot be empty, so this is a multi-line array with
         // a single value. It should be defined on single line.
         $error = 'Multi-line array contains a single value; use single-line array instead';
         $fix = $phpcsFile->addWarning($error, $stackPtr, 'MultiLineNotAllowed');
         if ($fix === true) {
             $phpcsFile->fixer->beginChangeset();
             for ($i = $arrayStart + 1; $i < $arrayEnd; $i++) {
                 if ($tokens[$i]['code'] !== T_WHITESPACE) {
                     break;
                 }
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             for ($i = $arrayEnd - 1; $i > $arrayStart; $i--) {
                 if ($tokens[$i]['code'] !== T_WHITESPACE) {
                     break;
                 }
                 $phpcsFile->fixer->replaceToken($i, '');
             }
             $phpcsFile->fixer->endChangeset();
         }
         return;
     }
     //end if
     /*
         This section checks for arrays that don't specify keys.
     
         Arrays such as:
            [
             'aaa',
             'bbb',
             'd',
            ];
     */
     if ($keyUsed === false && empty($indices) === false) {
         $count = count($indices);
         $lastIndex = $indices[$count - 1]['value'];
         $trailingContent = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrayEnd - 1, $lastIndex, true);
         if ($tokens[$trailingContent]['code'] !== T_COMMA) {
             $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no');
             $error = 'Comma required after last value in array declaration';
             $fix = $phpcsFile->addFixableError($error, $trailingContent, 'NoCommaAfterLast');
             if ($fix === true) {
                 $phpcsFile->fixer->addContent($trailingContent, ',');
             }
         } else {
             $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes');
         }
         $lastValueLine = false;
         foreach ($indices as $value) {
             if (empty($value['value']) === true) {
                 // Array was malformed and we couldn't figure out
                 // the array value correctly, so we have to ignore it.
                 // Other parts of this sniff will correct the error.
                 continue;
             }
             if ($lastValueLine !== false && $tokens[$value['value']]['line'] === $lastValueLine) {
                 $error = 'Each value in a multi-line array must be on a new line';
                 $fix = $phpcsFile->addFixableError($error, $value['value'], 'ValueNoNewline');
                 if ($fix === true) {
                     if ($tokens[$value['value'] - 1]['code'] === T_WHITESPACE) {
                         $phpcsFile->fixer->replaceToken($value['value'] - 1, '');
                     }
                     $phpcsFile->fixer->addNewlineBefore($value['value']);
                 }
             }
             $lastValueLine = $tokens[$value['value']]['line'];
         }
         //end foreach
     }
     //end if
     /*
         Below the actual indentation of the array is checked.
         Errors will be thrown when a key is not aligned, when
         a double arrow is not aligned, and when a value is not
         aligned correctly.
         If an error is found in one of the above areas, then errors
         are not reported for the rest of the line to avoid reporting
         spaces and columns incorrectly. Often fixing the first
         problem will fix the other 2 anyway.
     
         For example:
     
         $a = [
               'index'  => '2',
              ];
     
         In this array, the double arrow is indented too far, but this
         will also cause an error in the value's alignment. If the arrow were
         to be moved back one space however, then both errors would be fixed.
     */
     $numValues = count($indices);
     $indicesStart = $keywordStart + 1;
     $arrowStart = $indicesStart + $maxLength + 1;
     $valueStart = $arrowStart + 3;
     $indexLine = $tokens[$stackPtr]['line'];
     $lastIndexLine = null;
     foreach ($indices as $index) {
         if (isset($index['index']) === false) {
             // Array value only.
             if ($tokens[$index['value']]['line'] === $tokens[$stackPtr]['line'] && $numValues > 1) {
                 $error = 'The first value in a multi-value array must be on a new line';
                 $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FirstValueNoNewline');
                 if ($fix === true) {
                     $phpcsFile->fixer->addNewlineBefore($index['value']);
                 }
             }
             continue;
         }
         $lastIndexLine = $indexLine;
         $indexLine = $tokens[$index['index']]['line'];
         // Check each line ends in a comma.
         $valueLine = $tokens[$index['value']]['line'];
         $nextComma = false;
         for ($i = $index['value']; $i < $arrayEnd; $i++) {
             // Skip bracketed statements, like function calls.
             if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                 $i = $tokens[$i]['parenthesis_closer'];
                 $valueLine = $tokens[$i]['line'];
                 continue;
             }
             if ($tokens[$i]['code'] === T_ARRAY) {
                 $i = $tokens[$tokens[$i]['parenthesis_opener']]['parenthesis_closer'];
                 $valueLine = $tokens[$i]['line'];
                 continue;
             }
             // Skip to the end of multi-line strings.
             if (isset(PHP_CodeSniffer_Tokens::$stringTokens[$tokens[$i]['code']]) === true) {
                 $i = $phpcsFile->findNext($tokens[$i]['code'], $i + 1, null, true);
                 $i--;
                 $valueLine = $tokens[$i]['line'];
                 continue;
             }
             if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
                 $i = $tokens[$i]['bracket_closer'];
                 $valueLine = $tokens[$i]['line'];
                 continue;
             }
             if ($tokens[$i]['code'] === T_CLOSURE) {
                 $i = $tokens[$i]['scope_closer'];
                 $valueLine = $tokens[$i]['line'];
                 continue;
             }
             if ($tokens[$i]['code'] === T_COMMA) {
                 $nextComma = $i;
                 break;
             }
         }
         //end for
         if ($nextComma === false || $tokens[$nextComma]['line'] !== $valueLine) {
             $error = 'Each line in an array declaration must end in a comma';
             $fix = $phpcsFile->addFixableError($error, $index['value'], 'NoComma');
             if ($fix === true) {
                 // Find the end of the line and put a comma there.
                 for ($i = $index['value'] + 1; $i < $phpcsFile->numTokens; $i++) {
                     if ($tokens[$i]['line'] > $valueLine) {
                         break;
                     }
                 }
                 $phpcsFile->fixer->addContentBefore($i - 1, ',');
             }
         }
         // Check that there is no space before the comma.
         if ($nextComma !== false && $tokens[$nextComma - 1]['code'] === T_WHITESPACE) {
             $content = $tokens[$nextComma - 2]['content'];
             $spaceLength = $tokens[$nextComma - 1]['length'];
             $error = 'Expected 0 spaces between "%s" and comma; %s found';
             $data = [$content, $spaceLength];
             $fix = $phpcsFile->addFixableError($error, $nextComma, 'SpaceBeforeComma', $data);
             if ($fix === true) {
                 $phpcsFile->fixer->replaceToken($nextComma - 1, '');
             }
         }
     }
     //end foreach
 }