PHP_CodeSniffer
[ class tree: PHP_CodeSniffer ] [ index: PHP_CodeSniffer ] [ all elements ]

Source for file ScopeIndentSniff.php

Documentation is available at ScopeIndentSniff.php

  1. <?php
  2. /**
  3.  * Checks that control structures are defined and indented correctly.
  4.  *
  5.  * @author    Greg Sherwood <gsherwood@squiz.net>
  6.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  7.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  8.  */
  9.  
  10. namespace PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace;
  11.  
  12. use PHP_CodeSniffer\Sniffs\Sniff;
  13. use PHP_CodeSniffer\Files\File;
  14. use PHP_CodeSniffer\Util\Tokens;
  15. use PHP_CodeSniffer\Config;
  16.  
  17. class ScopeIndentSniff implements Sniff
  18. {
  19.  
  20.     /**
  21.      * A list of tokenizers this sniff supports.
  22.      *
  23.      * @var array 
  24.      */
  25.     public $supportedTokenizers = array(
  26.                                    'PHP',
  27.                                    'JS',
  28.                                   );
  29.  
  30.     /**
  31.      * The number of spaces code should be indented.
  32.      *
  33.      * @var integer 
  34.      */
  35.     public $indent = 4;
  36.  
  37.     /**
  38.      * Does the indent need to be exactly right?
  39.      *
  40.      * If TRUE, indent needs to be exactly $indent spaces. If FALSE,
  41.      * indent needs to be at least $indent spaces (but can be more).
  42.      *
  43.      * @var boolean 
  44.      */
  45.     public $exact = false;
  46.  
  47.     /**
  48.      * Should tabs be used for indenting?
  49.      *
  50.      * If TRUE, fixes will be made using tabs instead of spaces.
  51.      * The size of each tab is important, so it should be specified
  52.      * using the --tab-width CLI argument.
  53.      *
  54.      * @var boolean 
  55.      */
  56.     public $tabIndent = false;
  57.  
  58.     /**
  59.      * The --tab-width CLI value that is being used.
  60.      *
  61.      * @var integer 
  62.      */
  63.     private $tabWidth = null;
  64.  
  65.     /**
  66.      * List of tokens not needing to be checked for indentation.
  67.      *
  68.      * Useful to allow Sniffs based on this to easily ignore/skip some
  69.      * tokens from verification. For example, inline HTML sections
  70.      * or PHP open/close tags can escape from here and have their own
  71.      * rules elsewhere.
  72.      *
  73.      * @var int[] 
  74.      */
  75.     public $ignoreIndentationTokens = array();
  76.  
  77.     /**
  78.      * List of tokens not needing to be checked for indentation.
  79.      *
  80.      * This is a cached copy of the public version of this var, which
  81.      * can be set in a ruleset file, and some core ignored tokens.
  82.      *
  83.      * @var int[] 
  84.      */
  85.     private $ignoreIndentation = array();
  86.  
  87.     /**
  88.      * Any scope openers that should not cause an indent.
  89.      *
  90.      * @var int[] 
  91.      */
  92.     protected $nonIndentingScopes = array();
  93.  
  94.     /**
  95.      * Show debug output for this sniff.
  96.      *
  97.      * @var boolean 
  98.      */
  99.     private $debug = false;
  100.  
  101.  
  102.     /**
  103.      * Returns an array of tokens this test wants to listen for.
  104.      *
  105.      * @return array 
  106.      */
  107.     public function register()
  108.     {
  109.         if (defined('PHP_CODESNIFFER_IN_TESTS'=== true{
  110.             $this->debug = false;
  111.         }
  112.  
  113.         return array(T_OPEN_TAG);
  114.  
  115.     }//end register()
  116.  
  117.  
  118.     /**
  119.      * Processes this test, when one of its tokens is encountered.
  120.      *
  121.      * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document.
  122.      * @param int                         $stackPtr  The position of the current token
  123.      *                                                in the stack passed in $tokens.
  124.      *
  125.      * @return void 
  126.      */
  127.     public function process(File $phpcsFile$stackPtr)
  128.     {
  129.         $debug = Config::getConfigData('scope_indent_debug');
  130.         if ($debug !== null{
  131.             $this->debug = (bool) $debug;
  132.         }
  133.  
  134.         if ($this->tabWidth === null{
  135.             if (isset($phpcsFile->config->tabWidth=== false || $phpcsFile->config->tabWidth === 0{
  136.                 // We have no idea how wide tabs are, so assume 4 spaces for fixing.
  137.                 // It shouldn't really matter because indent checks elsewhere in the
  138.                 // standard should fix things up.
  139.                 $this->tabWidth = 4;
  140.             else {
  141.                 $this->tabWidth $phpcsFile->config->tabWidth;
  142.             }
  143.         }
  144.  
  145.         $currentIndent = 0;
  146.         $lastOpenTag   $stackPtr;
  147.         $lastCloseTag  = null;
  148.         $openScopes    = array();
  149.         $adjustments   = array();
  150.         $setIndents    = array();
  151.  
  152.         $tokens  $phpcsFile->getTokens();
  153.         $first   $phpcsFile->findFirstOnLine(T_INLINE_HTML$stackPtr);
  154.         $trimmed ltrim($tokens[$first]['content']);
  155.         if ($trimmed === ''{
  156.             $currentIndent ($tokens[$stackPtr]['column'- 1);
  157.         else {
  158.             $currentIndent (strlen($tokens[$first]['content']strlen($trimmed));
  159.         }
  160.  
  161.         if ($this->debug === true{
  162.             $line $tokens[$stackPtr]['line'];
  163.             echo "Start with token $stackPtr on line $line with indent $currentIndent".PHP_EOL;
  164.         }
  165.  
  166.         if (empty($this->ignoreIndentation=== true{
  167.             $this->ignoreIndentation = array(T_INLINE_HTML => true);
  168.             foreach ($this->ignoreIndentationTokens as $token{
  169.                 if (is_int($token=== false{
  170.                     if (defined($token=== false{
  171.                         continue;
  172.                     }
  173.  
  174.                     $token constant($token);
  175.                 }
  176.  
  177.                 $this->ignoreIndentation[$token= true;
  178.             }
  179.         }//end if
  180.  
  181.         $this->exact     = (bool) $this->exact;
  182.         $this->tabIndent = (bool) $this->tabIndent;
  183.  
  184.         for ($i ($stackPtr + 1)$i $phpcsFile->numTokens; $i++{
  185.             if ($i === false{
  186.                 // Something has gone very wrong; maybe a parse error.
  187.                 break;
  188.             }
  189.  
  190.             $checkToken  = null;
  191.             $checkIndent = null;
  192.  
  193.             $exact = (bool) $this->exact;
  194.             if ($exact === true && isset($tokens[$i]['nested_parenthesis']=== true{
  195.                 // Don't check indents exactly between parenthesis as they
  196.                 // tend to have custom rules, such as with multi-line function calls
  197.                 // and control structure conditions.
  198.                 $exact = false;
  199.             }
  200.  
  201.             // Detect line changes and figure out where the indent is.
  202.             if ($tokens[$i]['column'=== 1{
  203.                 $trimmed ltrim($tokens[$i]['content']);
  204.                 if ($trimmed === ''{
  205.                     if (isset($tokens[($i + 1)]=== true
  206.                         && $tokens[$i]['line'=== $tokens[($i + 1)]['line']
  207.                     {
  208.                         $checkToken  ($i + 1);
  209.                         $tokenIndent ($tokens[($i + 1)]['column'- 1);
  210.                     }
  211.                 else {
  212.                     $checkToken  $i;
  213.                     $tokenIndent (strlen($tokens[$i]['content']strlen($trimmed));
  214.                 }
  215.             }
  216.  
  217.             // Closing parenthesis should just be indented to at least
  218.             // the same level as where they were opened (but can be more).
  219.             if (($checkToken !== null
  220.                 && $tokens[$checkToken]['code'=== T_CLOSE_PARENTHESIS
  221.                 && isset($tokens[$checkToken]['parenthesis_opener']=== true)
  222.                 || ($tokens[$i]['code'=== T_CLOSE_PARENTHESIS
  223.                 && isset($tokens[$i]['parenthesis_opener']=== true)
  224.             {
  225.                 if ($checkToken !== null{
  226.                     $parenCloser $checkToken;
  227.                 else {
  228.                     $parenCloser $i;
  229.                 }
  230.  
  231.                 if ($this->debug === true{
  232.                     $line $tokens[$i]['line'];
  233.                     echo "Closing parenthesis found on line $line".PHP_EOL;
  234.                 }
  235.  
  236.                 $parenOpener $tokens[$parenCloser]['parenthesis_opener'];
  237.                 if ($tokens[$parenCloser]['line'!== $tokens[$parenOpener]['line']{
  238.                     $parens = 0;
  239.                     if (isset($tokens[$parenCloser]['nested_parenthesis']=== true
  240.                         && empty($tokens[$parenCloser]['nested_parenthesis']=== false
  241.                     {
  242.                         end($tokens[$parenCloser]['nested_parenthesis']);
  243.                         $parens key($tokens[$parenCloser]['nested_parenthesis']);
  244.                         if ($this->debug === true{
  245.                             $line $tokens[$parens]['line'];
  246.                             echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
  247.                         }
  248.                     }
  249.  
  250.                     $condition = 0;
  251.                     if (isset($tokens[$parenCloser]['conditions']=== true
  252.                         && empty($tokens[$parenCloser]['conditions']=== false
  253.                     {
  254.                         end($tokens[$parenCloser]['conditions']);
  255.                         $condition key($tokens[$parenCloser]['conditions']);
  256.                         if ($this->debug === true{
  257.                             $line $tokens[$condition]['line'];
  258.                             $type $tokens[$condition]['type'];
  259.                             echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
  260.                         }
  261.                     }
  262.  
  263.                     if ($parens $condition{
  264.                         if ($this->debug === true{
  265.                             echo "\t* using parenthesis *".PHP_EOL;
  266.                         }
  267.  
  268.                         $parenOpener $parens;
  269.                         $condition   = 0;
  270.                     else if ($condition > 0{
  271.                         if ($this->debug === true{
  272.                             echo "\t* using condition *".PHP_EOL;
  273.                         }
  274.  
  275.                         $parenOpener $condition;
  276.                         $parens      = 0;
  277.                     }
  278.  
  279.                     $exact = false;
  280.  
  281.                     $lastOpenTagConditions array_keys($tokens[$lastOpenTag]['conditions']);
  282.                     $lastOpenTagCondition  array_pop($lastOpenTagConditions);
  283.  
  284.                     if ($condition > 0 && $lastOpenTagCondition === $condition{
  285.                         if ($this->debug === true{
  286.                             echo "\t* open tag is inside condition; using open tag *".PHP_EOL;
  287.                         }
  288.  
  289.                         $checkIndent ($tokens[$lastOpenTag]['column'- 1);
  290.                         if (isset($adjustments[$condition]=== true{
  291.                             $checkIndent += $adjustments[$condition];
  292.                         }
  293.  
  294.                         $currentIndent $checkIndent;
  295.  
  296.                         if ($this->debug === true{
  297.                             $type $tokens[$lastOpenTag]['type'];
  298.                             echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $lastOpenTag ($type)".PHP_EOL;
  299.                         }
  300.                     else if ($condition > 0
  301.                         && isset($tokens[$condition]['scope_opener']=== true
  302.                         && isset($setIndents[$tokens[$condition]['scope_opener']]=== true
  303.                     {
  304.                         $checkIndent $setIndents[$tokens[$condition]['scope_opener']];
  305.                         if (isset($adjustments[$condition]=== true{
  306.                             $checkIndent += $adjustments[$condition];
  307.                         }
  308.  
  309.                         $currentIndent $checkIndent;
  310.  
  311.                         if ($this->debug === true{
  312.                             $type $tokens[$condition]['type'];
  313.                             echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $condition ($type)".PHP_EOL;
  314.                         }
  315.                     else {
  316.                         $first $phpcsFile->findFirstOnLine(T_WHITESPACE$parenOpenertrue);
  317.  
  318.                         $checkIndent ($tokens[$first]['column'- 1);
  319.                         if (isset($adjustments[$first]=== true{
  320.                             $checkIndent += $adjustments[$first];
  321.                         }
  322.  
  323.                         if ($this->debug === true{
  324.                             $line $tokens[$first]['line'];
  325.                             $type $tokens[$first]['type'];
  326.                             echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
  327.                         }
  328.  
  329.                         if ($first === $tokens[$parenCloser]['parenthesis_opener']{
  330.                             // This is unlikely to be the start of the statement, so look
  331.                             // back further to find it.
  332.                             $first--;
  333.                         }
  334.  
  335.                         $prev $phpcsFile->findStartOfStatement($firstT_COMMA);
  336.                         if ($prev !== $first{
  337.                             // This is not the start of the statement.
  338.                             if ($this->debug === true{
  339.                                 $line $tokens[$prev]['line'];
  340.                                 $type $tokens[$prev]['type'];
  341.                                 echo "\t* previous is $type on line $line *".PHP_EOL;
  342.                             }
  343.  
  344.                             $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  345.                             $prev  $phpcsFile->findStartOfStatement($firstT_COMMA);
  346.                             $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  347.                             if ($this->debug === true{
  348.                                 $line $tokens[$first]['line'];
  349.                                 $type $tokens[$first]['type'];
  350.                                 echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
  351.                             }
  352.                         }
  353.  
  354.                         if (isset($tokens[$first]['scope_closer']=== true
  355.                             && $tokens[$first]['scope_closer'=== $first
  356.                         {
  357.                             if ($this->debug === true{
  358.                                 echo "\t* first token is a scope closer *".PHP_EOL;
  359.                             }
  360.  
  361.                             if (isset($tokens[$first]['scope_condition']=== true{
  362.                                 $scopeCloser $first;
  363.                                 $first       $phpcsFile->findFirstOnLine(T_WHITESPACE$tokens[$scopeCloser]['scope_condition']true);
  364.  
  365.                                 $currentIndent ($tokens[$first]['column'- 1);
  366.                                 if (isset($adjustments[$first]=== true{
  367.                                     $currentIndent += $adjustments[$first];
  368.                                 }
  369.  
  370.                                 // Make sure it is divisible by our expected indent.
  371.                                 if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'!== T_CLOSURE{
  372.                                     $currentIndent = (int) (ceil($currentIndent $this->indent$this->indent);
  373.                                 }
  374.  
  375.                                 $setIndents[$first$currentIndent;
  376.  
  377.                                 if ($this->debug === true{
  378.                                     $type $tokens[$first]['type'];
  379.                                     echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
  380.                                 }
  381.                             }//end if
  382.                         else {
  383.                             // Don't force current indent to divisible because there could be custom
  384.                             // rules in place between parenthesis, such as with arrays.
  385.                             $currentIndent ($tokens[$first]['column'- 1);
  386.                             if (isset($adjustments[$first]=== true{
  387.                                 $currentIndent += $adjustments[$first];
  388.                             }
  389.  
  390.                             $setIndents[$first$currentIndent;
  391.  
  392.                             if ($this->debug === true{
  393.                                 $type $tokens[$first]['type'];
  394.                                 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
  395.                             }
  396.                         }//end if
  397.                     }//end if
  398.                 else if ($this->debug === true{
  399.                     echo "\t * ignoring single-line definition *".PHP_EOL;
  400.                 }//end if
  401.             }//end if
  402.  
  403.             // Closing short array bracket should just be indented to at least
  404.             // the same level as where it was opened (but can be more).
  405.             if ($tokens[$i]['code'=== T_CLOSE_SHORT_ARRAY
  406.                 || ($checkToken !== null
  407.                 && $tokens[$checkToken]['code'=== T_CLOSE_SHORT_ARRAY)
  408.             {
  409.                 if ($checkToken !== null{
  410.                     $arrayCloser $checkToken;
  411.                 else {
  412.                     $arrayCloser $i;
  413.                 }
  414.  
  415.                 if ($this->debug === true{
  416.                     $line $tokens[$arrayCloser]['line'];
  417.                     echo "Closing short array bracket found on line $line".PHP_EOL;
  418.                 }
  419.  
  420.                 $arrayOpener $tokens[$arrayCloser]['bracket_opener'];
  421.                 if ($tokens[$arrayCloser]['line'!== $tokens[$arrayOpener]['line']{
  422.                     $first       $phpcsFile->findFirstOnLine(T_WHITESPACE$arrayOpenertrue);
  423.                     $checkIndent ($tokens[$first]['column'- 1);
  424.                     if (isset($adjustments[$first]=== true{
  425.                         $checkIndent += $adjustments[$first];
  426.                     }
  427.  
  428.                     $exact = false;
  429.  
  430.                     if ($this->debug === true{
  431.                         $line $tokens[$first]['line'];
  432.                         $type $tokens[$first]['type'];
  433.                         echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
  434.                     }
  435.  
  436.                     if ($first === $tokens[$arrayCloser]['bracket_opener']{
  437.                         // This is unlikely to be the start of the statement, so look
  438.                         // back further to find it.
  439.                         $first--;
  440.                     }
  441.  
  442.                     $prev $phpcsFile->findStartOfStatement($firstarray(T_COMMAT_DOUBLE_ARROW));
  443.                     if ($prev !== $first{
  444.                         // This is not the start of the statement.
  445.                         if ($this->debug === true{
  446.                             $line $tokens[$prev]['line'];
  447.                             $type $tokens[$prev]['type'];
  448.                             echo "\t* previous is $type on line $line *".PHP_EOL;
  449.                         }
  450.  
  451.                         $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  452.                         $prev  $phpcsFile->findStartOfStatement($firstarray(T_COMMAT_DOUBLE_ARROW));
  453.                         $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  454.                         if ($this->debug === true{
  455.                             $line $tokens[$first]['line'];
  456.                             $type $tokens[$first]['type'];
  457.                             echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
  458.                         }
  459.                     else if ($tokens[$first]['code'=== T_WHITESPACE{
  460.                         $first $phpcsFile->findNext(T_WHITESPACE($first + 1)nulltrue);
  461.                     }
  462.  
  463.                     if (isset($tokens[$first]['scope_closer']=== true
  464.                         && $tokens[$first]['scope_closer'=== $first
  465.                     {
  466.                         // The first token is a scope closer and would have already
  467.                         // been processed and set the indent level correctly, so
  468.                         // don't adjust it again.
  469.                         if ($this->debug === true{
  470.                             echo "\t* first token is a scope closer; ignoring closing short array bracket *".PHP_EOL;
  471.                         }
  472.  
  473.                         if (isset($setIndents[$first]=== true{
  474.                             $currentIndent $setIndents[$first];
  475.                             if ($this->debug === true{
  476.                                 echo "\t=> indent reset to $currentIndent".PHP_EOL;
  477.                             }
  478.                         }
  479.                     else {
  480.                         // Don't force current indent to be divisible because there could be custom
  481.                         // rules in place for arrays.
  482.                         $currentIndent ($tokens[$first]['column'- 1);
  483.                         if (isset($adjustments[$first]=== true{
  484.                             $currentIndent += $adjustments[$first];
  485.                         }
  486.  
  487.                         $setIndents[$first$currentIndent;
  488.  
  489.                         if ($this->debug === true{
  490.                             $type $tokens[$first]['type'];
  491.                             echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
  492.                         }
  493.                     }//end if
  494.                 else if ($this->debug === true{
  495.                     echo "\t * ignoring single-line definition *".PHP_EOL;
  496.                 }//end if
  497.             }//end if
  498.  
  499.             // Adjust lines within scopes while auto-fixing.
  500.             if ($checkToken !== null
  501.                 && $exact === false
  502.                 && (empty($tokens[$checkToken]['conditions']=== false
  503.                 || (isset($tokens[$checkToken]['scope_opener']=== true
  504.                 && $tokens[$checkToken]['scope_opener'=== $checkToken))
  505.             {
  506.                 if (empty($tokens[$checkToken]['conditions']=== false{
  507.                     end($tokens[$checkToken]['conditions']);
  508.                     $condition key($tokens[$checkToken]['conditions']);
  509.                 else {
  510.                     $condition $tokens[$checkToken]['scope_condition'];
  511.                 }
  512.  
  513.                 $first $phpcsFile->findFirstOnLine(T_WHITESPACE$conditiontrue);
  514.  
  515.                 if (isset($adjustments[$first]=== true
  516.                     && (($adjustments[$first< 0 && $tokenIndent $currentIndent)
  517.                     || ($adjustments[$first> 0 && $tokenIndent $currentIndent))
  518.                 {
  519.                     $padding ($tokenIndent $adjustments[$first]);
  520.                     if ($padding > 0{
  521.                         if ($this->tabIndent === true{
  522.                             $numTabs   floor($padding $this->tabWidth);
  523.                             $numSpaces ($padding ($numTabs $this->tabWidth));
  524.                             $padding   str_repeat("\t"$numTabs).str_repeat(' '$numSpaces);
  525.                         else {
  526.                             $padding str_repeat(' '$padding);
  527.                         }
  528.                     else {
  529.                         $padding '';
  530.                     }
  531.  
  532.                     if ($phpcsFile->fixer->enabled === true{
  533.                         if ($checkToken === $i{
  534.                             $phpcsFile->fixer->replaceToken($checkToken$padding.$trimmed);
  535.                         else {
  536.                             // Easier to just replace the entire indent.
  537.                             $phpcsFile->fixer->replaceToken(($checkToken - 1)$padding);
  538.                         }
  539.                     }
  540.  
  541.                     if ($this->debug === true{
  542.                         $length strlen($padding);
  543.                         $line   $tokens[$checkToken]['line'];
  544.                         $type   $tokens[$checkToken]['type'];
  545.                         echo "Indent adjusted to $length for $type on line $line".PHP_EOL;
  546.                     }
  547.  
  548.                     $adjustments[$checkToken$adjustments[$first];
  549.  
  550.                     if ($this->debug === true{
  551.                         $line $tokens[$checkToken]['line'];
  552.                         $type $tokens[$checkToken]['type'];
  553.                         echo "\t=> Add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL;
  554.                     }
  555.                 }//end if
  556.             }//end if
  557.  
  558.             // Scope closers reset the required indent to the same level as the opening condition.
  559.             if (($checkToken !== null
  560.                 && isset($openScopes[$checkToken]=== true
  561.                 || (isset($tokens[$checkToken]['scope_condition']=== true
  562.                 && isset($tokens[$checkToken]['scope_closer']=== true
  563.                 && $tokens[$checkToken]['scope_closer'=== $checkToken
  564.                 && $tokens[$checkToken]['line'!== $tokens[$tokens[$checkToken]['scope_opener']]['line']))
  565.                 || ($checkToken === null
  566.                 && isset($openScopes[$i]=== true
  567.                 || (isset($tokens[$i]['scope_condition']=== true
  568.                 && isset($tokens[$i]['scope_closer']=== true
  569.                 && $tokens[$i]['scope_closer'=== $i
  570.                 && $tokens[$i]['line'!== $tokens[$tokens[$i]['scope_opener']]['line']))
  571.             {
  572.                 if ($this->debug === true{
  573.                     if ($checkToken === null{
  574.                         $type $tokens[$tokens[$i]['scope_condition']]['type'];
  575.                         $line $tokens[$i]['line'];
  576.                     else {
  577.                         $type $tokens[$tokens[$checkToken]['scope_condition']]['type'];
  578.                         $line $tokens[$checkToken]['line'];
  579.                     }
  580.  
  581.                     echo "Close scope ($type) on line $line".PHP_EOL;
  582.                 }
  583.  
  584.                 $scopeCloser $checkToken;
  585.                 if ($scopeCloser === null{
  586.                     $scopeCloser $i;
  587.                 else {
  588.                     array_pop($openScopes);
  589.                 }
  590.  
  591.                 if (isset($tokens[$scopeCloser]['scope_condition']=== true{
  592.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE$tokens[$scopeCloser]['scope_condition']true);
  593.                     if ($this->debug === true{
  594.                         $line $tokens[$first]['line'];
  595.                         $type $tokens[$first]['type'];
  596.                         echo "\t* first token is $first ($type) on line $line *".PHP_EOL;
  597.                     }
  598.  
  599.                     while ($tokens[$first]['code'=== T_CONSTANT_ENCAPSED_STRING
  600.                         && $tokens[($first - 1)]['code'=== T_CONSTANT_ENCAPSED_STRING
  601.                     {
  602.                         $first $phpcsFile->findFirstOnLine(T_WHITESPACE($first - 1)true);
  603.                         if ($this->debug === true{
  604.                             $line $tokens[$first]['line'];
  605.                             $type $tokens[$first]['type'];
  606.                             echo "\t* found multi-line string; amended first token is $first ($type) on line $line *".PHP_EOL;
  607.                         }
  608.                     }
  609.  
  610.                     $currentIndent ($tokens[$first]['column'- 1);
  611.                     if (isset($adjustments[$first]=== true{
  612.                         $currentIndent += $adjustments[$first];
  613.                     }
  614.  
  615.                     // Make sure it is divisible by our expected indent.
  616.                     if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'!== T_CLOSURE{
  617.                         $currentIndent = (int) (ceil($currentIndent $this->indent$this->indent);
  618.                     }
  619.  
  620.                     $setIndents[$scopeCloser$currentIndent;
  621.  
  622.                     if ($this->debug === true{
  623.                         $type $tokens[$scopeCloser]['type'];
  624.                         echo "\t=> indent set to $currentIndent by token $scopeCloser ($type)".PHP_EOL;
  625.                     }
  626.  
  627.                     // We only check the indent of scope closers if they are
  628.                     // curly braces because other constructs tend to have different rules.
  629.                     if ($tokens[$scopeCloser]['code'=== T_CLOSE_CURLY_BRACKET{
  630.                         $exact = true;
  631.                     else {
  632.                         $checkToken = null;
  633.                     }
  634.                 }//end if
  635.             }//end if
  636.  
  637.             // Handle scope for JS object notation.
  638.             if ($phpcsFile->tokenizerType === 'JS'
  639.                 && (($checkToken !== null
  640.                 && $tokens[$checkToken]['code'=== T_CLOSE_OBJECT
  641.                 && $tokens[$checkToken]['line'!== $tokens[$tokens[$checkToken]['bracket_opener']]['line'])
  642.                 || ($checkToken === null
  643.                 && $tokens[$i]['code'=== T_CLOSE_OBJECT
  644.                 && $tokens[$i]['line'!== $tokens[$tokens[$i]['bracket_opener']]['line']))
  645.             {
  646.                 if ($this->debug === true{
  647.                     $line $tokens[$i]['line'];
  648.                     echo "Close JS object on line $line".PHP_EOL;
  649.                 }
  650.  
  651.                 $scopeCloser $checkToken;
  652.                 if ($scopeCloser === null{
  653.                     $scopeCloser $i;
  654.                 else {
  655.                     array_pop($openScopes);
  656.                 }
  657.  
  658.                 $parens = 0;
  659.                 if (isset($tokens[$scopeCloser]['nested_parenthesis']=== true
  660.                     && empty($tokens[$scopeCloser]['nested_parenthesis']=== false
  661.                 {
  662.                     end($tokens[$scopeCloser]['nested_parenthesis']);
  663.                     $parens key($tokens[$scopeCloser]['nested_parenthesis']);
  664.                     if ($this->debug === true{
  665.                         $line $tokens[$parens]['line'];
  666.                         echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
  667.                     }
  668.                 }
  669.  
  670.                 $condition = 0;
  671.                 if (isset($tokens[$scopeCloser]['conditions']=== true
  672.                     && empty($tokens[$scopeCloser]['conditions']=== false
  673.                 {
  674.                     end($tokens[$scopeCloser]['conditions']);
  675.                     $condition key($tokens[$scopeCloser]['conditions']);
  676.                     if ($this->debug === true{
  677.                         $line $tokens[$condition]['line'];
  678.                         $type $tokens[$condition]['type'];
  679.                         echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
  680.                     }
  681.                 }
  682.  
  683.                 if ($parens $condition{
  684.                     if ($this->debug === true{
  685.                         echo "\t* using parenthesis *".PHP_EOL;
  686.                     }
  687.  
  688.                     $first     $phpcsFile->findFirstOnLine(T_WHITESPACE$parenstrue);
  689.                     $condition = 0;
  690.                 else if ($condition > 0{
  691.                     if ($this->debug === true{
  692.                         echo "\t* using condition *".PHP_EOL;
  693.                     }
  694.  
  695.                     $first  $phpcsFile->findFirstOnLine(T_WHITESPACE$conditiontrue);
  696.                     $parens = 0;
  697.                 else {
  698.                     if ($this->debug === true{
  699.                         $line $tokens[$tokens[$scopeCloser]['bracket_opener']]['line'];
  700.                         echo "\t* token is not in parenthesis or condition; using opener on line $line *".PHP_EOL;
  701.                     }
  702.  
  703.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE$tokens[$scopeCloser]['bracket_opener']true);
  704.                 }//end if
  705.  
  706.                 $currentIndent ($tokens[$first]['column'- 1);
  707.                 if (isset($adjustments[$first]=== true{
  708.                     $currentIndent += $adjustments[$first];
  709.                 }
  710.  
  711.                 if ($parens > 0 || $condition > 0{
  712.                     $checkIndent ($tokens[$first]['column'- 1);
  713.                     if (isset($adjustments[$first]=== true{
  714.                         $checkIndent += $adjustments[$first];
  715.                     }
  716.  
  717.                     if ($condition > 0{
  718.                         $checkIndent   += $this->indent;
  719.                         $currentIndent += $this->indent;
  720.                         $exact          = true;
  721.                     }
  722.                 else {
  723.                     $checkIndent $currentIndent;
  724.                 }
  725.  
  726.                 // Make sure it is divisible by our expected indent.
  727.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  728.                 $checkIndent        = (int) (ceil($checkIndent $this->indent$this->indent);
  729.                 $setIndents[$first$currentIndent;
  730.  
  731.                 if ($this->debug === true{
  732.                     $type $tokens[$first]['type'];
  733.                     echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
  734.                 }
  735.             }//end if
  736.  
  737.             if ($checkToken !== null
  738.                 && isset(Tokens::$scopeOpeners[$tokens[$checkToken]['code']]=== true
  739.                 && in_array($tokens[$checkToken]['code']$this->nonIndentingScopes=== false
  740.                 && isset($tokens[$checkToken]['scope_opener']=== true
  741.             {
  742.                 $exact = true;
  743.  
  744.                 $lastOpener = null;
  745.                 if (empty($openScopes=== false{
  746.                     end($openScopes);
  747.                     $lastOpener current($openScopes);
  748.                 }
  749.  
  750.                 // A scope opener that shares a closer with another token (like multiple
  751.                 // CASEs using the same BREAK) needs to reduce the indent level so its
  752.                 // indent is checked correctly. It will then increase the indent again
  753.                 // (as all openers do) after being checked.
  754.                 if ($lastOpener !== null
  755.                     && isset($tokens[$lastOpener]['scope_closer']=== true
  756.                     && $tokens[$lastOpener]['level'=== $tokens[$checkToken]['level']
  757.                     && $tokens[$lastOpener]['scope_closer'=== $tokens[$checkToken]['scope_closer']
  758.                 {
  759.                     $currentIndent          -= $this->indent;
  760.                     $setIndents[$lastOpener$currentIndent;
  761.                     if ($this->debug === true{
  762.                         $line $tokens[$i]['line'];
  763.                         $type $tokens[$lastOpener]['type'];
  764.                         echo "Shared closer found on line $line".PHP_EOL;
  765.                         echo "\t=> indent set to $currentIndent by token $lastOpener ($type)".PHP_EOL;
  766.                     }
  767.                 }
  768.  
  769.                 if ($tokens[$checkToken]['code'=== T_CLOSURE
  770.                     && $tokenIndent $currentIndent
  771.                 {
  772.                     // The opener is indented more than needed, which is fine.
  773.                     // But just check that it is divisible by our expected indent.
  774.                     $checkIndent = (int) (ceil($tokenIndent $this->indent$this->indent);
  775.                     $exact       = false;
  776.  
  777.                     if ($this->debug === true{
  778.                         $line $tokens[$i]['line'];
  779.                         echo "Closure found on line $line".PHP_EOL;
  780.                         echo "\t=> checking indent of $checkIndent; main indent remains at $currentIndent".PHP_EOL;
  781.                     }
  782.                 }
  783.             }//end if
  784.  
  785.             // Method prefix indentation has to be exact or else if will break
  786.             // the rest of the function declaration, and potentially future ones.
  787.             if ($checkToken !== null
  788.                 && isset(Tokens::$methodPrefixes[$tokens[$checkToken]['code']]=== true
  789.                 && $tokens[($checkToken + 1)]['code'!== T_DOUBLE_COLON
  790.             {
  791.                 $exact = true;
  792.             }
  793.  
  794.             // JS property indentation has to be exact or else if will break
  795.             // things like function and object indentation.
  796.             if ($checkToken !== null && $tokens[$checkToken]['code'=== T_PROPERTY{
  797.                 $exact = true;
  798.             }
  799.  
  800.             // PHP tags needs to be indented to exact column positions
  801.             // so they don't cause problems with indent checks for the code
  802.             // within them, but they don't need to line up with the current indent.
  803.             if ($checkToken !== null
  804.                 && ($tokens[$checkToken]['code'=== T_OPEN_TAG
  805.                 || $tokens[$checkToken]['code'=== T_OPEN_TAG_WITH_ECHO
  806.                 || $tokens[$checkToken]['code'=== T_CLOSE_TAG)
  807.             {
  808.                 $exact       = true;
  809.                 $checkIndent ($tokens[$checkToken]['column'- 1);
  810.                 $checkIndent = (int) (ceil($checkIndent $this->indent$this->indent);
  811.             }
  812.  
  813.             // Special case for ELSE statements that are not on the same
  814.             // line as the previous IF statements closing brace. They still need
  815.             // to have the same indent or it will break code after the block.
  816.             if ($checkToken !== null && $tokens[$checkToken]['code'=== T_ELSE{
  817.                 $exact = true;
  818.             }
  819.  
  820.             if ($checkIndent === null{
  821.                 $checkIndent $currentIndent;
  822.             }
  823.  
  824.             /*
  825.                 The indent of the line is checked by the following IF block.
  826.  
  827.                 Up until now, we've just been figuring out what the indent
  828.                 of this line should be.
  829.  
  830.                 After this IF block, we adjust the indent again for
  831.                 the checking of future line.
  832.             */
  833.  
  834.             $adjusted = false;
  835.             if ($checkToken !== null
  836.                 && isset($this->ignoreIndentation[$tokens[$checkToken]['code']]=== false
  837.                 && (($tokenIndent !== $checkIndent && $exact === true)
  838.                 || ($tokenIndent $checkIndent && $exact === false))
  839.             {
  840.                 $type  'IncorrectExact';
  841.                 $error 'Line indented incorrectly; expected ';
  842.                 if ($exact === false{
  843.                     $error .= 'at least ';
  844.                     $type   'Incorrect';
  845.                 }
  846.  
  847.                 if ($this->tabIndent === true{
  848.                     $error .= '%s tabs, found %s';
  849.                     $data   = array(
  850.                                floor($checkIndent $this->tabWidth),
  851.                                floor($tokenIndent $this->tabWidth),
  852.                               );
  853.                 else {
  854.                     $error .= '%s spaces, found %s';
  855.                     $data   = array(
  856.                                $checkIndent,
  857.                                $tokenIndent,
  858.                               );
  859.                 }
  860.  
  861.                 if ($this->debug === true{
  862.                     $line    $tokens[$checkToken]['line'];
  863.                     $message vsprintf($error$data);
  864.                     echo "[Line $line$message".PHP_EOL;
  865.                 }
  866.  
  867.                 $fix $phpcsFile->addFixableError($error$checkToken$type$data);
  868.                 if ($fix === true || $this->debug === true{
  869.                     $padding '';
  870.                     if ($this->tabIndent === true{
  871.                         $numTabs floor($checkIndent $this->tabWidth);
  872.                         if ($numTabs > 0{
  873.                             $numSpaces ($checkIndent ($numTabs $this->tabWidth));
  874.                             $padding   str_repeat("\t"$numTabs).str_repeat(' '$numSpaces);
  875.                         }
  876.                     else if ($checkIndent > 0{
  877.                         $padding str_repeat(' '$checkIndent);
  878.                     }
  879.  
  880.                     if ($checkToken === $i{
  881.                         $accepted $phpcsFile->fixer->replaceToken($checkToken$padding.$trimmed);
  882.                     else {
  883.                         // Easier to just replace the entire indent.
  884.                         $accepted $phpcsFile->fixer->replaceToken(($checkToken - 1)$padding);
  885.                     }
  886.  
  887.                     if ($accepted === true{
  888.                         $adjustments[$checkToken($checkIndent $tokenIndent);
  889.                         if ($this->debug === true{
  890.                             $line $tokens[$checkToken]['line'];
  891.                             $type $tokens[$checkToken]['type'];
  892.                             echo "\t=> Add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL;
  893.                         }
  894.                     }
  895.                 else {
  896.                     // Assume the change would be applied and continue
  897.                     // checking indents under this assumption. This gives more
  898.                     // technically accurate error messages.
  899.                     $adjustments[$checkToken($checkIndent $tokenIndent);
  900.                 }//end if
  901.             }//end if
  902.  
  903.             if ($checkToken !== null{
  904.                 $i $checkToken;
  905.             }
  906.  
  907.             // Completely skip here/now docs as the indent is a part of the
  908.             // content itself.
  909.             if ($tokens[$i]['code'=== T_START_HEREDOC
  910.                 || $tokens[$i]['code'=== T_START_NOWDOC
  911.             {
  912.                 $i $phpcsFile->findNext(array(T_END_HEREDOCT_END_NOWDOC)($i + 1));
  913.                 continue;
  914.             }
  915.  
  916.             // Completely skip multi-line strings as the indent is a part of the
  917.             // content itself.
  918.             if ($tokens[$i]['code'=== T_CONSTANT_ENCAPSED_STRING
  919.                 || $tokens[$i]['code'=== T_DOUBLE_QUOTED_STRING
  920.             {
  921.                 $i $phpcsFile->findNext($tokens[$i]['code']($i + 1)nulltrue);
  922.                 $i--;
  923.                 continue;
  924.             }
  925.  
  926.             // Completely skip doc comments as they tend to have complex
  927.             // indentation rules.
  928.             if ($tokens[$i]['code'=== T_DOC_COMMENT_OPEN_TAG{
  929.                 $i $tokens[$i]['comment_closer'];
  930.                 continue;
  931.             }
  932.  
  933.             // Open tags reset the indent level.
  934.             if ($tokens[$i]['code'=== T_OPEN_TAG
  935.                 || $tokens[$i]['code'=== T_OPEN_TAG_WITH_ECHO
  936.             {
  937.                 if ($this->debug === true{
  938.                     $line $tokens[$i]['line'];
  939.                     echo "Open PHP tag found on line $line".PHP_EOL;
  940.                 }
  941.  
  942.                 if ($checkToken === null{
  943.                     $first         $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  944.                     $currentIndent (strlen($tokens[$first]['content']strlen(ltrim($tokens[$first]['content'])));
  945.                 else {
  946.                     $currentIndent ($tokens[$i]['column'- 1);
  947.                 }
  948.  
  949.                 $lastOpenTag $i;
  950.  
  951.                 if (isset($adjustments[$i]=== true{
  952.                     $currentIndent += $adjustments[$i];
  953.                 }
  954.  
  955.                 // Make sure it is divisible by our expected indent.
  956.                 $currentIndent  = (int) (ceil($currentIndent $this->indent$this->indent);
  957.                 $setIndents[$i$currentIndent;
  958.  
  959.                 if ($this->debug === true{
  960.                     $type $tokens[$i]['type'];
  961.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  962.                 }
  963.  
  964.                 continue;
  965.             }//end if
  966.  
  967.             // Close tags reset the indent level, unless they are closing a tag
  968.             // opened on the same line.
  969.             if ($tokens[$i]['code'=== T_CLOSE_TAG{
  970.                 if ($this->debug === true{
  971.                     $line $tokens[$i]['line'];
  972.                     echo "Close PHP tag found on line $line".PHP_EOL;
  973.                 }
  974.  
  975.                 if ($tokens[$lastOpenTag]['line'!== $tokens[$i]['line']{
  976.                     $currentIndent ($tokens[$i]['column'- 1);
  977.                     $lastCloseTag  $i;
  978.                 else {
  979.                     if ($lastCloseTag === null{
  980.                         $currentIndent = 0;
  981.                     else {
  982.                         $currentIndent ($tokens[$lastCloseTag]['column'- 1);
  983.                     }
  984.                 }
  985.  
  986.                 if (isset($adjustments[$i]=== true{
  987.                     $currentIndent += $adjustments[$i];
  988.                 }
  989.  
  990.                 // Make sure it is divisible by our expected indent.
  991.                 $currentIndent  = (int) (ceil($currentIndent $this->indent$this->indent);
  992.                 $setIndents[$i$currentIndent;
  993.  
  994.                 if ($this->debug === true{
  995.                     $type $tokens[$i]['type'];
  996.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  997.                 }
  998.  
  999.                 continue;
  1000.             }//end if
  1001.  
  1002.             // Anon classes and functions set the indent based on their own indent level.
  1003.             if ($tokens[$i]['code'=== T_CLOSURE || $tokens[$i]['code'=== T_ANON_CLASS{
  1004.                 $closer $tokens[$i]['scope_closer'];
  1005.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  1006.                     if ($this->debug === true{
  1007.                         $type str_replace('_'' 'strtolower(substr($tokens[$i]['type']2)));
  1008.                         $line $tokens[$i]['line'];
  1009.                         echo "* ignoring single-line $type on line $line".PHP_EOL;
  1010.                     }
  1011.  
  1012.                     $i $closer;
  1013.                     continue;
  1014.                 }
  1015.  
  1016.                 if ($this->debug === true{
  1017.                     $type str_replace('_'' 'strtolower(substr($tokens[$i]['type']2)));
  1018.                     $line $tokens[$i]['line'];
  1019.                     echo "Open $type on line $line".PHP_EOL;
  1020.                 }
  1021.  
  1022.                 $first $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  1023.                 if ($this->debug === true{
  1024.                     $line $tokens[$first]['line'];
  1025.                     $type $tokens[$first]['type'];
  1026.                     echo "\t* first token is $first ($type) on line $line *".PHP_EOL;
  1027.                 }
  1028.  
  1029.                 while ($tokens[$first]['code'=== T_CONSTANT_ENCAPSED_STRING
  1030.                     && $tokens[($first - 1)]['code'=== T_CONSTANT_ENCAPSED_STRING
  1031.                 {
  1032.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE($first - 1)true);
  1033.                     if ($this->debug === true{
  1034.                         $line $tokens[$first]['line'];
  1035.                         $type $tokens[$first]['type'];
  1036.                         echo "\t* found multi-line string; amended first token is $first ($type) on line $line *".PHP_EOL;
  1037.                     }
  1038.                 }
  1039.  
  1040.                 $currentIndent (($tokens[$first]['column'- 1$this->indent);
  1041.                 $openScopes[$tokens[$i]['scope_closer']] $tokens[$i]['scope_condition'];
  1042.  
  1043.                 if (isset($adjustments[$first]=== true{
  1044.                     $currentIndent += $adjustments[$first];
  1045.                 }
  1046.  
  1047.                 // Make sure it is divisible by our expected indent.
  1048.                 $currentIndent = (int) (floor($currentIndent $this->indent$this->indent);
  1049.                 $i $tokens[$i]['scope_opener'];
  1050.                 $setIndents[$i$currentIndent;
  1051.  
  1052.                 if ($this->debug === true{
  1053.                     $type $tokens[$i]['type'];
  1054.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  1055.                 }
  1056.  
  1057.                 continue;
  1058.             }//end if
  1059.  
  1060.             // Scope openers increase the indent level.
  1061.             if (isset($tokens[$i]['scope_condition']=== true
  1062.                 && isset($tokens[$i]['scope_opener']=== true
  1063.                 && $tokens[$i]['scope_opener'=== $i
  1064.             {
  1065.                 $closer $tokens[$i]['scope_closer'];
  1066.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  1067.                     if ($this->debug === true{
  1068.                         $line $tokens[$i]['line'];
  1069.                         $type $tokens[$i]['type'];
  1070.                         echo "* ignoring single-line $type on line $line".PHP_EOL;
  1071.                     }
  1072.  
  1073.                     $i $closer;
  1074.                     continue;
  1075.                 }
  1076.  
  1077.                 $condition $tokens[$tokens[$i]['scope_condition']]['code'];
  1078.                 if (isset(Tokens::$scopeOpeners[$condition]=== true
  1079.                     && in_array($condition$this->nonIndentingScopes=== false
  1080.                 {
  1081.                     if ($this->debug === true{
  1082.                         $line $tokens[$i]['line'];
  1083.                         $type $tokens[$tokens[$i]['scope_condition']]['type'];
  1084.                         echo "Open scope ($type) on line $line".PHP_EOL;
  1085.                     }
  1086.  
  1087.                     $currentIndent += $this->indent;
  1088.                     $setIndents[$i$currentIndent;
  1089.                     $openScopes[$tokens[$i]['scope_closer']] $tokens[$i]['scope_condition'];
  1090.  
  1091.                     if ($this->debug === true{
  1092.                         $type $tokens[$i]['type'];
  1093.                         echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  1094.                     }
  1095.  
  1096.                     continue;
  1097.                 }
  1098.             }//end if
  1099.  
  1100.             // JS objects set the indent level.
  1101.             if ($phpcsFile->tokenizerType === 'JS'
  1102.                 && $tokens[$i]['code'=== T_OBJECT
  1103.             {
  1104.                 $closer $tokens[$i]['bracket_closer'];
  1105.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  1106.                     if ($this->debug === true{
  1107.                         $line $tokens[$i]['line'];
  1108.                         echo "* ignoring single-line JS object on line $line".PHP_EOL;
  1109.                     }
  1110.  
  1111.                     $i $closer;
  1112.                     continue;
  1113.                 }
  1114.  
  1115.                 if ($this->debug === true{
  1116.                     $line $tokens[$i]['line'];
  1117.                     echo "Open JS object on line $line".PHP_EOL;
  1118.                 }
  1119.  
  1120.                 $first         $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  1121.                 $currentIndent (($tokens[$first]['column'- 1$this->indent);
  1122.                 if (isset($adjustments[$first]=== true{
  1123.                     $currentIndent += $adjustments[$first];
  1124.                 }
  1125.  
  1126.                 // Make sure it is divisible by our expected indent.
  1127.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  1128.                 $setIndents[$first$currentIndent;
  1129.  
  1130.                 if ($this->debug === true{
  1131.                     $type $tokens[$first]['type'];
  1132.                     echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
  1133.                 }
  1134.  
  1135.                 continue;
  1136.             }//end if
  1137.  
  1138.             // Closing an anon class or function.
  1139.             if (isset($tokens[$i]['scope_condition']=== true
  1140.                 && $tokens[$i]['scope_closer'=== $i
  1141.                 && ($tokens[$tokens[$i]['scope_condition']]['code'=== T_CLOSURE
  1142.                 || $tokens[$tokens[$i]['scope_condition']]['code'=== T_ANON_CLASS)
  1143.             {
  1144.                 if ($this->debug === true{
  1145.                     $type str_replace('_'' 'strtolower(substr($tokens[$tokens[$i]['scope_condition']]['type']2)));
  1146.                     $line $tokens[$i]['line'];
  1147.                     echo "Close $type on line $line".PHP_EOL;
  1148.                 }
  1149.  
  1150.                 $prev = false;
  1151.  
  1152.                 $object = 0;
  1153.                 if ($phpcsFile->tokenizerType === 'JS'{
  1154.                     $conditions $tokens[$i]['conditions'];
  1155.                     krsort($conditionsSORT_NUMERIC);
  1156.                     foreach ($conditions as $token => $condition{
  1157.                         if ($condition === T_OBJECT{
  1158.                             $object $token;
  1159.                             break;
  1160.                         }
  1161.                     }
  1162.  
  1163.                     if ($this->debug === true && $object !== 0{
  1164.                         $line $tokens[$object]['line'];
  1165.                         echo "\t* token is inside JS object $object on line $line *".PHP_EOL;
  1166.                     }
  1167.                 }
  1168.  
  1169.                 $parens = 0;
  1170.                 if (isset($tokens[$i]['nested_parenthesis']=== true
  1171.                     && empty($tokens[$i]['nested_parenthesis']=== false
  1172.                 {
  1173.                     end($tokens[$i]['nested_parenthesis']);
  1174.                     $parens key($tokens[$i]['nested_parenthesis']);
  1175.                     if ($this->debug === true{
  1176.                         $line $tokens[$parens]['line'];
  1177.                         echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
  1178.                     }
  1179.                 }
  1180.  
  1181.                 $condition = 0;
  1182.                 if (isset($tokens[$i]['conditions']=== true
  1183.                     && empty($tokens[$i]['conditions']=== false
  1184.                 {
  1185.                     end($tokens[$i]['conditions']);
  1186.                     $condition key($tokens[$i]['conditions']);
  1187.                     if ($this->debug === true{
  1188.                         $line $tokens[$condition]['line'];
  1189.                         $type $tokens[$condition]['type'];
  1190.                         echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
  1191.                     }
  1192.                 }
  1193.  
  1194.                 if ($parens $object && $parens $condition{
  1195.                     if ($this->debug === true{
  1196.                         echo "\t* using parenthesis *".PHP_EOL;
  1197.                     }
  1198.  
  1199.                     $prev      $phpcsFile->findPrevious(Tokens::$emptyTokens($parens - 1)nulltrue);
  1200.                     $object    = 0;
  1201.                     $condition = 0;
  1202.                 else if ($object > 0 && $object >= $condition{
  1203.                     if ($this->debug === true{
  1204.                         echo "\t* using object *".PHP_EOL;
  1205.                     }
  1206.  
  1207.                     $prev      $object;
  1208.                     $parens    = 0;
  1209.                     $condition = 0;
  1210.                 else if ($condition > 0{
  1211.                     if ($this->debug === true{
  1212.                         echo "\t* using condition *".PHP_EOL;
  1213.                     }
  1214.  
  1215.                     $prev   $condition;
  1216.                     $object = 0;
  1217.                     $parens = 0;
  1218.                 }//end if
  1219.  
  1220.                 if ($prev === false{
  1221.                     $prev $phpcsFile->findPrevious(array(T_EQUALT_RETURN)($tokens[$i]['scope_condition'- 1)nullfalsenulltrue);
  1222.                     if ($prev === false{
  1223.                         $prev $i;
  1224.                         if ($this->debug === true{
  1225.                             echo "\t* could not find a previous T_EQUAL or T_RETURN token; will use current token *".PHP_EOL;
  1226.                         }
  1227.                     }
  1228.                 }
  1229.  
  1230.                 if ($this->debug === true{
  1231.                     $line $tokens[$prev]['line'];
  1232.                     $type $tokens[$prev]['type'];
  1233.                     echo "\t* previous token is $type on line $line *".PHP_EOL;
  1234.                 }
  1235.  
  1236.                 $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  1237.                 if ($this->debug === true{
  1238.                     $line $tokens[$first]['line'];
  1239.                     $type $tokens[$first]['type'];
  1240.                     echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
  1241.                 }
  1242.  
  1243.                 $prev $phpcsFile->findStartOfStatement($first);
  1244.                 if ($prev !== $first{
  1245.                     // This is not the start of the statement.
  1246.                     if ($this->debug === true{
  1247.                         $line $tokens[$prev]['line'];
  1248.                         $type $tokens[$prev]['type'];
  1249.                         echo "\t* amended previous is $type on line $line *".PHP_EOL;
  1250.                     }
  1251.  
  1252.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  1253.                     if ($this->debug === true{
  1254.                         $line $tokens[$first]['line'];
  1255.                         $type $tokens[$first]['type'];
  1256.                         echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
  1257.                     }
  1258.                 }
  1259.  
  1260.                 $currentIndent ($tokens[$first]['column'- 1);
  1261.                 if ($object > 0 || $condition > 0{
  1262.                     $currentIndent += $this->indent;
  1263.                 }
  1264.  
  1265.                 if (isset($tokens[$first]['scope_closer']=== true
  1266.                     && $tokens[$first]['scope_closer'=== $first
  1267.                 {
  1268.                     if ($this->debug === true{
  1269.                         echo "\t* first token is a scope closer *".PHP_EOL;
  1270.                     }
  1271.  
  1272.                     if ($condition === 0 || $tokens[$condition]['scope_opener'$first{
  1273.                         $currentIndent $setIndents[$first];
  1274.                     else if ($this->debug === true{
  1275.                         echo "\t* ignoring scope closer *".PHP_EOL;
  1276.                     }
  1277.                 }
  1278.  
  1279.                 // Make sure it is divisible by our expected indent.
  1280.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  1281.                 $setIndents[$first$currentIndent;
  1282.  
  1283.                 if ($this->debug === true{
  1284.                     $type $tokens[$first]['type'];
  1285.                     echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
  1286.                 }
  1287.             }//end if
  1288.         }//end for
  1289.  
  1290.         // Don't process the rest of the file.
  1291.         return $phpcsFile->numTokens;
  1292.  
  1293.     }//end process()
  1294.  
  1295.  
  1296. }//end class

Documentation generated on Mon, 11 Mar 2019 15:27:46 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.