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.  
  594.                     $currentIndent ($tokens[$first]['column'- 1);
  595.                     if (isset($adjustments[$first]=== true{
  596.                         $currentIndent += $adjustments[$first];
  597.                     }
  598.  
  599.                     // Make sure it is divisible by our expected indent.
  600.                     if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'!== T_CLOSURE{
  601.                         $currentIndent = (int) (ceil($currentIndent $this->indent$this->indent);
  602.                     }
  603.  
  604.                     $setIndents[$scopeCloser$currentIndent;
  605.  
  606.                     if ($this->debug === true{
  607.                         $type $tokens[$scopeCloser]['type'];
  608.                         echo "\t=> indent set to $currentIndent by token $scopeCloser ($type)".PHP_EOL;
  609.                     }
  610.  
  611.                     // We only check the indent of scope closers if they are
  612.                     // curly braces because other constructs tend to have different rules.
  613.                     if ($tokens[$scopeCloser]['code'=== T_CLOSE_CURLY_BRACKET{
  614.                         $exact = true;
  615.                     else {
  616.                         $checkToken = null;
  617.                     }
  618.                 }//end if
  619.             }//end if
  620.  
  621.             // Handle scope for JS object notation.
  622.             if ($phpcsFile->tokenizerType === 'JS'
  623.                 && (($checkToken !== null
  624.                 && $tokens[$checkToken]['code'=== T_CLOSE_OBJECT
  625.                 && $tokens[$checkToken]['line'!== $tokens[$tokens[$checkToken]['bracket_opener']]['line'])
  626.                 || ($checkToken === null
  627.                 && $tokens[$i]['code'=== T_CLOSE_OBJECT
  628.                 && $tokens[$i]['line'!== $tokens[$tokens[$i]['bracket_opener']]['line']))
  629.             {
  630.                 if ($this->debug === true{
  631.                     $line $tokens[$i]['line'];
  632.                     echo "Close JS object on line $line".PHP_EOL;
  633.                 }
  634.  
  635.                 $scopeCloser $checkToken;
  636.                 if ($scopeCloser === null{
  637.                     $scopeCloser $i;
  638.                 else {
  639.                     array_pop($openScopes);
  640.                 }
  641.  
  642.                 $parens = 0;
  643.                 if (isset($tokens[$scopeCloser]['nested_parenthesis']=== true
  644.                     && empty($tokens[$scopeCloser]['nested_parenthesis']=== false
  645.                 {
  646.                     end($tokens[$scopeCloser]['nested_parenthesis']);
  647.                     $parens key($tokens[$scopeCloser]['nested_parenthesis']);
  648.                     if ($this->debug === true{
  649.                         $line $tokens[$parens]['line'];
  650.                         echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
  651.                     }
  652.                 }
  653.  
  654.                 $condition = 0;
  655.                 if (isset($tokens[$scopeCloser]['conditions']=== true
  656.                     && empty($tokens[$scopeCloser]['conditions']=== false
  657.                 {
  658.                     end($tokens[$scopeCloser]['conditions']);
  659.                     $condition key($tokens[$scopeCloser]['conditions']);
  660.                     if ($this->debug === true{
  661.                         $line $tokens[$condition]['line'];
  662.                         $type $tokens[$condition]['type'];
  663.                         echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
  664.                     }
  665.                 }
  666.  
  667.                 if ($parens $condition{
  668.                     if ($this->debug === true{
  669.                         echo "\t* using parenthesis *".PHP_EOL;
  670.                     }
  671.  
  672.                     $first     $phpcsFile->findFirstOnLine(T_WHITESPACE$parenstrue);
  673.                     $condition = 0;
  674.                 else if ($condition > 0{
  675.                     if ($this->debug === true{
  676.                         echo "\t* using condition *".PHP_EOL;
  677.                     }
  678.  
  679.                     $first  $phpcsFile->findFirstOnLine(T_WHITESPACE$conditiontrue);
  680.                     $parens = 0;
  681.                 else {
  682.                     if ($this->debug === true{
  683.                         $line $tokens[$tokens[$scopeCloser]['bracket_opener']]['line'];
  684.                         echo "\t* token is not in parenthesis or condition; using opener on line $line *".PHP_EOL;
  685.                     }
  686.  
  687.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE$tokens[$scopeCloser]['bracket_opener']true);
  688.                 }//end if
  689.  
  690.                 $currentIndent ($tokens[$first]['column'- 1);
  691.                 if (isset($adjustments[$first]=== true{
  692.                     $currentIndent += $adjustments[$first];
  693.                 }
  694.  
  695.                 if ($parens > 0 || $condition > 0{
  696.                     $checkIndent ($tokens[$first]['column'- 1);
  697.                     if (isset($adjustments[$first]=== true{
  698.                         $checkIndent += $adjustments[$first];
  699.                     }
  700.  
  701.                     if ($condition > 0{
  702.                         $checkIndent   += $this->indent;
  703.                         $currentIndent += $this->indent;
  704.                         $exact          = true;
  705.                     }
  706.                 else {
  707.                     $checkIndent $currentIndent;
  708.                 }
  709.  
  710.                 // Make sure it is divisible by our expected indent.
  711.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  712.                 $checkIndent        = (int) (ceil($checkIndent $this->indent$this->indent);
  713.                 $setIndents[$first$currentIndent;
  714.  
  715.                 if ($this->debug === true{
  716.                     $type $tokens[$first]['type'];
  717.                     echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
  718.                 }
  719.             }//end if
  720.  
  721.             if ($checkToken !== null
  722.                 && isset(Tokens::$scopeOpeners[$tokens[$checkToken]['code']]=== true
  723.                 && in_array($tokens[$checkToken]['code']$this->nonIndentingScopes=== false
  724.                 && isset($tokens[$checkToken]['scope_opener']=== true
  725.             {
  726.                 $exact = true;
  727.  
  728.                 $lastOpener = null;
  729.                 if (empty($openScopes=== false{
  730.                     end($openScopes);
  731.                     $lastOpener current($openScopes);
  732.                 }
  733.  
  734.                 // A scope opener that shares a closer with another token (like multiple
  735.                 // CASEs using the same BREAK) needs to reduce the indent level so its
  736.                 // indent is checked correctly. It will then increase the indent again
  737.                 // (as all openers do) after being checked.
  738.                 if ($lastOpener !== null
  739.                     && isset($tokens[$lastOpener]['scope_closer']=== true
  740.                     && $tokens[$lastOpener]['level'=== $tokens[$checkToken]['level']
  741.                     && $tokens[$lastOpener]['scope_closer'=== $tokens[$checkToken]['scope_closer']
  742.                 {
  743.                     $currentIndent          -= $this->indent;
  744.                     $setIndents[$lastOpener$currentIndent;
  745.                     if ($this->debug === true{
  746.                         $line $tokens[$i]['line'];
  747.                         $type $tokens[$lastOpener]['type'];
  748.                         echo "Shared closer found on line $line".PHP_EOL;
  749.                         echo "\t=> indent set to $currentIndent by token $lastOpener ($type)".PHP_EOL;
  750.                     }
  751.                 }
  752.  
  753.                 if ($tokens[$checkToken]['code'=== T_CLOSURE
  754.                     && $tokenIndent $currentIndent
  755.                 {
  756.                     // The opener is indented more than needed, which is fine.
  757.                     // But just check that it is divisible by our expected indent.
  758.                     $checkIndent = (int) (ceil($tokenIndent $this->indent$this->indent);
  759.                     $exact       = false;
  760.  
  761.                     if ($this->debug === true{
  762.                         $line $tokens[$i]['line'];
  763.                         echo "Closure found on line $line".PHP_EOL;
  764.                         echo "\t=> checking indent of $checkIndent; main indent remains at $currentIndent".PHP_EOL;
  765.                     }
  766.                 }
  767.             }//end if
  768.  
  769.             // Method prefix indentation has to be exact or else if will break
  770.             // the rest of the function declaration, and potentially future ones.
  771.             if ($checkToken !== null
  772.                 && isset(Tokens::$methodPrefixes[$tokens[$checkToken]['code']]=== true
  773.                 && $tokens[($checkToken + 1)]['code'!== T_DOUBLE_COLON
  774.             {
  775.                 $exact = true;
  776.             }
  777.  
  778.             // JS property indentation has to be exact or else if will break
  779.             // things like function and object indentation.
  780.             if ($checkToken !== null && $tokens[$checkToken]['code'=== T_PROPERTY{
  781.                 $exact = true;
  782.             }
  783.  
  784.             // PHP tags needs to be indented to exact column positions
  785.             // so they don't cause problems with indent checks for the code
  786.             // within them, but they don't need to line up with the current indent.
  787.             if ($checkToken !== null
  788.                 && ($tokens[$checkToken]['code'=== T_OPEN_TAG
  789.                 || $tokens[$checkToken]['code'=== T_OPEN_TAG_WITH_ECHO
  790.                 || $tokens[$checkToken]['code'=== T_CLOSE_TAG)
  791.             {
  792.                 $exact       = true;
  793.                 $checkIndent ($tokens[$checkToken]['column'- 1);
  794.                 $checkIndent = (int) (ceil($checkIndent $this->indent$this->indent);
  795.             }
  796.  
  797.             // Special case for ELSE statements that are not on the same
  798.             // line as the previous IF statements closing brace. They still need
  799.             // to have the same indent or it will break code after the block.
  800.             if ($checkToken !== null && $tokens[$checkToken]['code'=== T_ELSE{
  801.                 $exact = true;
  802.             }
  803.  
  804.             if ($checkIndent === null{
  805.                 $checkIndent $currentIndent;
  806.             }
  807.  
  808.             /*
  809.                 The indent of the line is checked by the following IF block.
  810.  
  811.                 Up until now, we've just been figuring out what the indent
  812.                 of this line should be.
  813.  
  814.                 After this IF block, we adjust the indent again for
  815.                 the checking of future line.
  816.             */
  817.  
  818.             $adjusted = false;
  819.             if ($checkToken !== null
  820.                 && isset($this->ignoreIndentation[$tokens[$checkToken]['code']]=== false
  821.                 && (($tokenIndent !== $checkIndent && $exact === true)
  822.                 || ($tokenIndent $checkIndent && $exact === false))
  823.             {
  824.                 $type  'IncorrectExact';
  825.                 $error 'Line indented incorrectly; expected ';
  826.                 if ($exact === false{
  827.                     $error .= 'at least ';
  828.                     $type   'Incorrect';
  829.                 }
  830.  
  831.                 if ($this->tabIndent === true{
  832.                     $error .= '%s tabs, found %s';
  833.                     $data   = array(
  834.                                floor($checkIndent $this->tabWidth),
  835.                                floor($tokenIndent $this->tabWidth),
  836.                               );
  837.                 else {
  838.                     $error .= '%s spaces, found %s';
  839.                     $data   = array(
  840.                                $checkIndent,
  841.                                $tokenIndent,
  842.                               );
  843.                 }
  844.  
  845.                 if ($this->debug === true{
  846.                     $line    $tokens[$checkToken]['line'];
  847.                     $message vsprintf($error$data);
  848.                     echo "[Line $line$message".PHP_EOL;
  849.                 }
  850.  
  851.                 $fix $phpcsFile->addFixableError($error$checkToken$type$data);
  852.                 if ($fix === true || $this->debug === true{
  853.                     $padding '';
  854.                     if ($this->tabIndent === true{
  855.                         $numTabs floor($checkIndent $this->tabWidth);
  856.                         if ($numTabs > 0{
  857.                             $numSpaces ($checkIndent ($numTabs $this->tabWidth));
  858.                             $padding   str_repeat("\t"$numTabs).str_repeat(' '$numSpaces);
  859.                         }
  860.                     else if ($checkIndent > 0{
  861.                         $padding str_repeat(' '$checkIndent);
  862.                     }
  863.  
  864.                     if ($checkToken === $i{
  865.                         $accepted $phpcsFile->fixer->replaceToken($checkToken$padding.$trimmed);
  866.                     else {
  867.                         // Easier to just replace the entire indent.
  868.                         $accepted $phpcsFile->fixer->replaceToken(($checkToken - 1)$padding);
  869.                     }
  870.  
  871.                     if ($accepted === true{
  872.                         $adjustments[$checkToken($checkIndent $tokenIndent);
  873.                         if ($this->debug === true{
  874.                             $line $tokens[$checkToken]['line'];
  875.                             $type $tokens[$checkToken]['type'];
  876.                             echo "\t=> Add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL;
  877.                         }
  878.                     }
  879.                 else {
  880.                     // Assume the change would be applied and continue
  881.                     // checking indents under this assumption. This gives more
  882.                     // technically accurate error messages.
  883.                     $adjustments[$checkToken($checkIndent $tokenIndent);
  884.                 }//end if
  885.             }//end if
  886.  
  887.             if ($checkToken !== null{
  888.                 $i $checkToken;
  889.             }
  890.  
  891.             // Completely skip here/now docs as the indent is a part of the
  892.             // content itself.
  893.             if ($tokens[$i]['code'=== T_START_HEREDOC
  894.                 || $tokens[$i]['code'=== T_START_NOWDOC
  895.             {
  896.                 $i $phpcsFile->findNext(array(T_END_HEREDOCT_END_NOWDOC)($i + 1));
  897.                 continue;
  898.             }
  899.  
  900.             // Completely skip multi-line strings as the indent is a part of the
  901.             // content itself.
  902.             if ($tokens[$i]['code'=== T_CONSTANT_ENCAPSED_STRING
  903.                 || $tokens[$i]['code'=== T_DOUBLE_QUOTED_STRING
  904.             {
  905.                 $i $phpcsFile->findNext($tokens[$i]['code']($i + 1)nulltrue);
  906.                 $i--;
  907.                 continue;
  908.             }
  909.  
  910.             // Completely skip doc comments as they tend to have complex
  911.             // indentation rules.
  912.             if ($tokens[$i]['code'=== T_DOC_COMMENT_OPEN_TAG{
  913.                 $i $tokens[$i]['comment_closer'];
  914.                 continue;
  915.             }
  916.  
  917.             // Open tags reset the indent level.
  918.             if ($tokens[$i]['code'=== T_OPEN_TAG
  919.                 || $tokens[$i]['code'=== T_OPEN_TAG_WITH_ECHO
  920.             {
  921.                 if ($this->debug === true{
  922.                     $line $tokens[$i]['line'];
  923.                     echo "Open PHP tag found on line $line".PHP_EOL;
  924.                 }
  925.  
  926.                 if ($checkToken === null{
  927.                     $first         $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  928.                     $currentIndent (strlen($tokens[$first]['content']strlen(ltrim($tokens[$first]['content'])));
  929.                 else {
  930.                     $currentIndent ($tokens[$i]['column'- 1);
  931.                 }
  932.  
  933.                 $lastOpenTag $i;
  934.  
  935.                 if (isset($adjustments[$i]=== true{
  936.                     $currentIndent += $adjustments[$i];
  937.                 }
  938.  
  939.                 // Make sure it is divisible by our expected indent.
  940.                 $currentIndent  = (int) (ceil($currentIndent $this->indent$this->indent);
  941.                 $setIndents[$i$currentIndent;
  942.  
  943.                 if ($this->debug === true{
  944.                     $type $tokens[$i]['type'];
  945.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  946.                 }
  947.  
  948.                 continue;
  949.             }//end if
  950.  
  951.             // Close tags reset the indent level, unless they are closing a tag
  952.             // opened on the same line.
  953.             if ($tokens[$i]['code'=== T_CLOSE_TAG{
  954.                 if ($this->debug === true{
  955.                     $line $tokens[$i]['line'];
  956.                     echo "Close PHP tag found on line $line".PHP_EOL;
  957.                 }
  958.  
  959.                 if ($tokens[$lastOpenTag]['line'!== $tokens[$i]['line']{
  960.                     $currentIndent ($tokens[$i]['column'- 1);
  961.                     $lastCloseTag  $i;
  962.                 else {
  963.                     if ($lastCloseTag === null{
  964.                         $currentIndent = 0;
  965.                     else {
  966.                         $currentIndent ($tokens[$lastCloseTag]['column'- 1);
  967.                     }
  968.                 }
  969.  
  970.                 if (isset($adjustments[$i]=== true{
  971.                     $currentIndent += $adjustments[$i];
  972.                 }
  973.  
  974.                 // Make sure it is divisible by our expected indent.
  975.                 $currentIndent  = (int) (ceil($currentIndent $this->indent$this->indent);
  976.                 $setIndents[$i$currentIndent;
  977.  
  978.                 if ($this->debug === true{
  979.                     $type $tokens[$i]['type'];
  980.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  981.                 }
  982.  
  983.                 continue;
  984.             }//end if
  985.  
  986.             // Anon classes and functions set the indent based on their own indent level.
  987.             if ($tokens[$i]['code'=== T_CLOSURE || $tokens[$i]['code'=== T_ANON_CLASS{
  988.                 $closer $tokens[$i]['scope_closer'];
  989.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  990.                     if ($this->debug === true{
  991.                         $type str_replace('_'' 'strtolower(substr($tokens[$i]['type']2)));
  992.                         $line $tokens[$i]['line'];
  993.                         echo "* ignoring single-line $type on line $line".PHP_EOL;
  994.                     }
  995.  
  996.                     $i $closer;
  997.                     continue;
  998.                 }
  999.  
  1000.                 if ($this->debug === true{
  1001.                     $type str_replace('_'' 'strtolower(substr($tokens[$i]['type']2)));
  1002.                     $line $tokens[$i]['line'];
  1003.                     echo "Open $type on line $line".PHP_EOL;
  1004.                 }
  1005.  
  1006.                 $first         $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  1007.                 $currentIndent (($tokens[$first]['column'- 1$this->indent);
  1008.                 $openScopes[$tokens[$i]['scope_closer']] $tokens[$i]['scope_condition'];
  1009.  
  1010.                 if (isset($adjustments[$first]=== true{
  1011.                     $currentIndent += $adjustments[$first];
  1012.                 }
  1013.  
  1014.                 // Make sure it is divisible by our expected indent.
  1015.                 $currentIndent = (int) (floor($currentIndent $this->indent$this->indent);
  1016.                 $i $tokens[$i]['scope_opener'];
  1017.                 $setIndents[$i$currentIndent;
  1018.  
  1019.                 if ($this->debug === true{
  1020.                     $type $tokens[$i]['type'];
  1021.                     echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  1022.                 }
  1023.  
  1024.                 continue;
  1025.             }//end if
  1026.  
  1027.             // Scope openers increase the indent level.
  1028.             if (isset($tokens[$i]['scope_condition']=== true
  1029.                 && isset($tokens[$i]['scope_opener']=== true
  1030.                 && $tokens[$i]['scope_opener'=== $i
  1031.             {
  1032.                 $closer $tokens[$i]['scope_closer'];
  1033.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  1034.                     if ($this->debug === true{
  1035.                         $line $tokens[$i]['line'];
  1036.                         $type $tokens[$i]['type'];
  1037.                         echo "* ignoring single-line $type on line $line".PHP_EOL;
  1038.                     }
  1039.  
  1040.                     $i $closer;
  1041.                     continue;
  1042.                 }
  1043.  
  1044.                 $condition $tokens[$tokens[$i]['scope_condition']]['code'];
  1045.                 if (isset(Tokens::$scopeOpeners[$condition]=== true
  1046.                     && in_array($condition$this->nonIndentingScopes=== false
  1047.                 {
  1048.                     if ($this->debug === true{
  1049.                         $line $tokens[$i]['line'];
  1050.                         $type $tokens[$tokens[$i]['scope_condition']]['type'];
  1051.                         echo "Open scope ($type) on line $line".PHP_EOL;
  1052.                     }
  1053.  
  1054.                     $currentIndent += $this->indent;
  1055.                     $setIndents[$i$currentIndent;
  1056.                     $openScopes[$tokens[$i]['scope_closer']] $tokens[$i]['scope_condition'];
  1057.  
  1058.                     if ($this->debug === true{
  1059.                         $type $tokens[$i]['type'];
  1060.                         echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
  1061.                     }
  1062.  
  1063.                     continue;
  1064.                 }
  1065.             }//end if
  1066.  
  1067.             // JS objects set the indent level.
  1068.             if ($phpcsFile->tokenizerType === 'JS'
  1069.                 && $tokens[$i]['code'=== T_OBJECT
  1070.             {
  1071.                 $closer $tokens[$i]['bracket_closer'];
  1072.                 if ($tokens[$i]['line'=== $tokens[$closer]['line']{
  1073.                     if ($this->debug === true{
  1074.                         $line $tokens[$i]['line'];
  1075.                         echo "* ignoring single-line JS object on line $line".PHP_EOL;
  1076.                     }
  1077.  
  1078.                     $i $closer;
  1079.                     continue;
  1080.                 }
  1081.  
  1082.                 if ($this->debug === true{
  1083.                     $line $tokens[$i]['line'];
  1084.                     echo "Open JS object on line $line".PHP_EOL;
  1085.                 }
  1086.  
  1087.                 $first         $phpcsFile->findFirstOnLine(T_WHITESPACE$itrue);
  1088.                 $currentIndent (($tokens[$first]['column'- 1$this->indent);
  1089.                 if (isset($adjustments[$first]=== true{
  1090.                     $currentIndent += $adjustments[$first];
  1091.                 }
  1092.  
  1093.                 // Make sure it is divisible by our expected indent.
  1094.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  1095.                 $setIndents[$first$currentIndent;
  1096.  
  1097.                 if ($this->debug === true{
  1098.                     $type $tokens[$first]['type'];
  1099.                     echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
  1100.                 }
  1101.  
  1102.                 continue;
  1103.             }//end if
  1104.  
  1105.             // Closing an anon class or function.
  1106.             if (isset($tokens[$i]['scope_condition']=== true
  1107.                 && $tokens[$i]['scope_closer'=== $i
  1108.                 && ($tokens[$tokens[$i]['scope_condition']]['code'=== T_CLOSURE
  1109.                 || $tokens[$tokens[$i]['scope_condition']]['code'=== T_ANON_CLASS)
  1110.             {
  1111.                 if ($this->debug === true{
  1112.                     $type str_replace('_'' 'strtolower(substr($tokens[$tokens[$i]['scope_condition']]['type']2)));
  1113.                     $line $tokens[$i]['line'];
  1114.                     echo "Close $type on line $line".PHP_EOL;
  1115.                 }
  1116.  
  1117.                 $prev = false;
  1118.  
  1119.                 $object = 0;
  1120.                 if ($phpcsFile->tokenizerType === 'JS'{
  1121.                     $conditions $tokens[$i]['conditions'];
  1122.                     krsort($conditionsSORT_NUMERIC);
  1123.                     foreach ($conditions as $token => $condition{
  1124.                         if ($condition === T_OBJECT{
  1125.                             $object $token;
  1126.                             break;
  1127.                         }
  1128.                     }
  1129.  
  1130.                     if ($this->debug === true && $object !== 0{
  1131.                         $line $tokens[$object]['line'];
  1132.                         echo "\t* token is inside JS object $object on line $line *".PHP_EOL;
  1133.                     }
  1134.                 }
  1135.  
  1136.                 $parens = 0;
  1137.                 if (isset($tokens[$i]['nested_parenthesis']=== true
  1138.                     && empty($tokens[$i]['nested_parenthesis']=== false
  1139.                 {
  1140.                     end($tokens[$i]['nested_parenthesis']);
  1141.                     $parens key($tokens[$i]['nested_parenthesis']);
  1142.                     if ($this->debug === true{
  1143.                         $line $tokens[$parens]['line'];
  1144.                         echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
  1145.                     }
  1146.                 }
  1147.  
  1148.                 $condition = 0;
  1149.                 if (isset($tokens[$i]['conditions']=== true
  1150.                     && empty($tokens[$i]['conditions']=== false
  1151.                 {
  1152.                     end($tokens[$i]['conditions']);
  1153.                     $condition key($tokens[$i]['conditions']);
  1154.                     if ($this->debug === true{
  1155.                         $line $tokens[$condition]['line'];
  1156.                         $type $tokens[$condition]['type'];
  1157.                         echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
  1158.                     }
  1159.                 }
  1160.  
  1161.                 if ($parens $object && $parens $condition{
  1162.                     if ($this->debug === true{
  1163.                         echo "\t* using parenthesis *".PHP_EOL;
  1164.                     }
  1165.  
  1166.                     $prev      $phpcsFile->findPrevious(Tokens::$emptyTokens($parens - 1)nulltrue);
  1167.                     $object    = 0;
  1168.                     $condition = 0;
  1169.                 else if ($object > 0 && $object >= $condition{
  1170.                     if ($this->debug === true{
  1171.                         echo "\t* using object *".PHP_EOL;
  1172.                     }
  1173.  
  1174.                     $prev      $object;
  1175.                     $parens    = 0;
  1176.                     $condition = 0;
  1177.                 else if ($condition > 0{
  1178.                     if ($this->debug === true{
  1179.                         echo "\t* using condition *".PHP_EOL;
  1180.                     }
  1181.  
  1182.                     $prev   $condition;
  1183.                     $object = 0;
  1184.                     $parens = 0;
  1185.                 }//end if
  1186.  
  1187.                 if ($prev === false{
  1188.                     $prev $phpcsFile->findPrevious(array(T_EQUALT_RETURN)($tokens[$i]['scope_condition'- 1)nullfalsenulltrue);
  1189.                     if ($prev === false{
  1190.                         $prev $i;
  1191.                         if ($this->debug === true{
  1192.                             echo "\t* could not find a previous T_EQUAL or T_RETURN token; will use current token *".PHP_EOL;
  1193.                         }
  1194.                     }
  1195.                 }
  1196.  
  1197.                 if ($this->debug === true{
  1198.                     $line $tokens[$prev]['line'];
  1199.                     $type $tokens[$prev]['type'];
  1200.                     echo "\t* previous token is $type on line $line *".PHP_EOL;
  1201.                 }
  1202.  
  1203.                 $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  1204.                 if ($this->debug === true{
  1205.                     $line $tokens[$first]['line'];
  1206.                     $type $tokens[$first]['type'];
  1207.                     echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
  1208.                 }
  1209.  
  1210.                 $prev $phpcsFile->findStartOfStatement($first);
  1211.                 if ($prev !== $first{
  1212.                     // This is not the start of the statement.
  1213.                     if ($this->debug === true{
  1214.                         $line $tokens[$prev]['line'];
  1215.                         $type $tokens[$prev]['type'];
  1216.                         echo "\t* amended previous is $type on line $line *".PHP_EOL;
  1217.                     }
  1218.  
  1219.                     $first $phpcsFile->findFirstOnLine(T_WHITESPACE$prevtrue);
  1220.                     if ($this->debug === true{
  1221.                         $line $tokens[$first]['line'];
  1222.                         $type $tokens[$first]['type'];
  1223.                         echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
  1224.                     }
  1225.                 }
  1226.  
  1227.                 $currentIndent ($tokens[$first]['column'- 1);
  1228.                 if ($object > 0 || $condition > 0{
  1229.                     $currentIndent += $this->indent;
  1230.                 }
  1231.  
  1232.                 if (isset($tokens[$first]['scope_closer']=== true
  1233.                     && $tokens[$first]['scope_closer'=== $first
  1234.                 {
  1235.                     if ($this->debug === true{
  1236.                         echo "\t* first token is a scope closer *".PHP_EOL;
  1237.                     }
  1238.  
  1239.                     if ($condition === 0 || $tokens[$condition]['scope_opener'$first{
  1240.                         $currentIndent $setIndents[$first];
  1241.                     else if ($this->debug === true{
  1242.                         echo "\t* ignoring scope closer *".PHP_EOL;
  1243.                     }
  1244.                 }
  1245.  
  1246.                 // Make sure it is divisible by our expected indent.
  1247.                 $currentIndent      = (int) (ceil($currentIndent $this->indent$this->indent);
  1248.                 $setIndents[$first$currentIndent;
  1249.  
  1250.                 if ($this->debug === true{
  1251.                     $type $tokens[$first]['type'];
  1252.                     echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
  1253.                 }
  1254.             }//end if
  1255.         }//end for
  1256.  
  1257.         // Don't process the rest of the file.
  1258.         return $phpcsFile->numTokens;
  1259.  
  1260.     }//end process()
  1261.  
  1262.  
  1263. }//end class

Documentation generated on Mon, 11 Mar 2019 14:05:00 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.