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

Source for file JS.php

Documentation is available at JS.php

  1. <?php
  2. /**
  3.  * Tokenizes JS code.
  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\Tokenizers;
  11.  
  12. use PHP_CodeSniffer\Util;
  13. use PHP_CodeSniffer\Exceptions\TokenizerException;
  14. use PHP_CodeSniffer\Config;
  15.  
  16. class JS extends Tokenizer
  17. {
  18.  
  19.  
  20.     /**
  21.      * A list of tokens that are allowed to open a scope.
  22.      *
  23.      * This array also contains information about what kind of token the scope
  24.      * opener uses to open and close the scope, if the token strictly requires
  25.      * an opener, if the token can share a scope closer, and who it can be shared
  26.      * with. An example of a token that shares a scope closer is a CASE scope.
  27.      *
  28.      * @var array 
  29.      */
  30.     public $scopeOpeners = array(
  31.                             T_IF       => array(
  32.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  33.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  34.                                            'strict' => false,
  35.                                            'shared' => false,
  36.                                            'with'   => array(),
  37.                                           ),
  38.                             T_TRY      => array(
  39.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  40.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  41.                                            'strict' => true,
  42.                                            'shared' => false,
  43.                                            'with'   => array(),
  44.                                           ),
  45.                             T_CATCH    => array(
  46.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  47.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  48.                                            'strict' => true,
  49.                                            'shared' => false,
  50.                                            'with'   => array(),
  51.                                           ),
  52.                             T_ELSE     => array(
  53.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  54.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  55.                                            'strict' => false,
  56.                                            'shared' => false,
  57.                                            'with'   => array(),
  58.                                           ),
  59.                             T_FOR      => array(
  60.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  61.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  62.                                            'strict' => false,
  63.                                            'shared' => false,
  64.                                            'with'   => array(),
  65.                                           ),
  66.                             T_CLASS    => array(
  67.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  68.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  69.                                            'strict' => true,
  70.                                            'shared' => false,
  71.                                            'with'   => array(),
  72.                                           ),
  73.                             T_FUNCTION => array(
  74.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  75.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  76.                                            'strict' => false,
  77.                                            'shared' => false,
  78.                                            'with'   => array(),
  79.                                           ),
  80.                             T_WHILE    => array(
  81.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  82.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  83.                                            'strict' => false,
  84.                                            'shared' => false,
  85.                                            'with'   => array(),
  86.                                           ),
  87.                             T_DO       => array(
  88.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  89.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  90.                                            'strict' => true,
  91.                                            'shared' => false,
  92.                                            'with'   => array(),
  93.                                           ),
  94.                             T_SWITCH   => array(
  95.                                            'start'  => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
  96.                                            'end'    => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
  97.                                            'strict' => true,
  98.                                            'shared' => false,
  99.                                            'with'   => array(),
  100.                                           ),
  101.                             T_CASE     => array(
  102.                                            'start'  => array(T_COLON => T_COLON),
  103.                                            'end'    => array(
  104.                                                         T_BREAK    => T_BREAK,
  105.                                                         T_RETURN   => T_RETURN,
  106.                                                         T_CONTINUE => T_CONTINUE,
  107.                                                         T_THROW    => T_THROW,
  108.                                                        ),
  109.                                            'strict' => true,
  110.                                            'shared' => true,
  111.                                            'with'   => array(
  112.                                                         T_DEFAULT => T_DEFAULT,
  113.                                                         T_CASE    => T_CASE,
  114.                                                         T_SWITCH  => T_SWITCH,
  115.                                                        ),
  116.                                           ),
  117.                             T_DEFAULT  => array(
  118.                                            'start'  => array(T_COLON => T_COLON),
  119.                                            'end'    => array(
  120.                                                         T_BREAK    => T_BREAK,
  121.                                                         T_RETURN   => T_RETURN,
  122.                                                         T_CONTINUE => T_CONTINUE,
  123.                                                         T_THROW    => T_THROW,
  124.                                                        ),
  125.                                            'strict' => true,
  126.                                            'shared' => true,
  127.                                            'with'   => array(
  128.                                                         T_CASE   => T_CASE,
  129.                                                         T_SWITCH => T_SWITCH,
  130.                                                        ),
  131.                                           ),
  132.                            );
  133.  
  134.     /**
  135.      * A list of tokens that end the scope.
  136.      *
  137.      * This array is just a unique collection of the end tokens
  138.      * from the _scopeOpeners array. The data is duplicated here to
  139.      * save time during parsing of the file.
  140.      *
  141.      * @var array 
  142.      */
  143.     public $endScopeTokens = array(
  144.                               T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
  145.                               T_BREAK               => T_BREAK,
  146.                              );
  147.  
  148.     /**
  149.      * A list of special JS tokens and their types.
  150.      *
  151.      * @var array 
  152.      */
  153.     protected $tokenValues = array(
  154.                               'class'     => 'T_CLASS',
  155.                               'function'  => 'T_FUNCTION',
  156.                               'prototype' => 'T_PROTOTYPE',
  157.                               'try'       => 'T_TRY',
  158.                               'catch'     => 'T_CATCH',
  159.                               'return'    => 'T_RETURN',
  160.                               'throw'     => 'T_THROW',
  161.                               'break'     => 'T_BREAK',
  162.                               'switch'    => 'T_SWITCH',
  163.                               'continue'  => 'T_CONTINUE',
  164.                               'if'        => 'T_IF',
  165.                               'else'      => 'T_ELSE',
  166.                               'do'        => 'T_DO',
  167.                               'while'     => 'T_WHILE',
  168.                               'for'       => 'T_FOR',
  169.                               'var'       => 'T_VAR',
  170.                               'case'      => 'T_CASE',
  171.                               'default'   => 'T_DEFAULT',
  172.                               'true'      => 'T_TRUE',
  173.                               'false'     => 'T_FALSE',
  174.                               'null'      => 'T_NULL',
  175.                               'this'      => 'T_THIS',
  176.                               'typeof'    => 'T_TYPEOF',
  177.                               '('         => 'T_OPEN_PARENTHESIS',
  178.                               ')'         => 'T_CLOSE_PARENTHESIS',
  179.                               '{'         => 'T_OPEN_CURLY_BRACKET',
  180.                               '}'         => 'T_CLOSE_CURLY_BRACKET',
  181.                               '['         => 'T_OPEN_SQUARE_BRACKET',
  182.                               ']'         => 'T_CLOSE_SQUARE_BRACKET',
  183.                               '?'         => 'T_INLINE_THEN',
  184.                               '.'         => 'T_OBJECT_OPERATOR',
  185.                               '+'         => 'T_PLUS',
  186.                               '-'         => 'T_MINUS',
  187.                               '*'         => 'T_MULTIPLY',
  188.                               '%'         => 'T_MODULUS',
  189.                               '/'         => 'T_DIVIDE',
  190.                               '^'         => 'T_LOGICAL_XOR',
  191.                               ','         => 'T_COMMA',
  192.                               ';'         => 'T_SEMICOLON',
  193.                               ':'         => 'T_COLON',
  194.                               '<'         => 'T_LESS_THAN',
  195.                               '>'         => 'T_GREATER_THAN',
  196.                               '<<'        => 'T_SL',
  197.                               '>>'        => 'T_SR',
  198.                               '>>>'       => 'T_ZSR',
  199.                               '<<='       => 'T_SL_EQUAL',
  200.                               '>>='       => 'T_SR_EQUAL',
  201.                               '>>>='      => 'T_ZSR_EQUAL',
  202.                               '<='        => 'T_IS_SMALLER_OR_EQUAL',
  203.                               '>='        => 'T_IS_GREATER_OR_EQUAL',
  204.                               '=>'        => 'T_DOUBLE_ARROW',
  205.                               '!'         => 'T_BOOLEAN_NOT',
  206.                               '||'        => 'T_BOOLEAN_OR',
  207.                               '&&'        => 'T_BOOLEAN_AND',
  208.                               '|'         => 'T_BITWISE_OR',
  209.                               '&'         => 'T_BITWISE_AND',
  210.                               '!='        => 'T_IS_NOT_EQUAL',
  211.                               '!=='       => 'T_IS_NOT_IDENTICAL',
  212.                               '='         => 'T_EQUAL',
  213.                               '=='        => 'T_IS_EQUAL',
  214.                               '==='       => 'T_IS_IDENTICAL',
  215.                               '-='        => 'T_MINUS_EQUAL',
  216.                               '+='        => 'T_PLUS_EQUAL',
  217.                               '*='        => 'T_MUL_EQUAL',
  218.                               '/='        => 'T_DIV_EQUAL',
  219.                               '%='        => 'T_MOD_EQUAL',
  220.                               '++'        => 'T_INC',
  221.                               '--'        => 'T_DEC',
  222.                               '//'        => 'T_COMMENT',
  223.                               '/*'        => 'T_COMMENT',
  224.                               '/**'       => 'T_DOC_COMMENT',
  225.                               '*/'        => 'T_COMMENT',
  226.                              );
  227.  
  228.     /**
  229.      * A list string delimiters.
  230.      *
  231.      * @var array 
  232.      */
  233.     protected $stringTokens = array(
  234.                                '\'' => '\'',
  235.                                '"'  => '"',
  236.                               );
  237.  
  238.     /**
  239.      * A list tokens that start and end comments.
  240.      *
  241.      * @var array 
  242.      */
  243.     protected $commentTokens = array(
  244.                                 '//'  => null,
  245.                                 '/*'  => '*/',
  246.                                 '/**' => '*/',
  247.                                );
  248.  
  249.  
  250.     /**
  251.      * Initialise the tokenizer.
  252.      *
  253.      * Pre-checks the content to see if it looks minified.
  254.      *
  255.      * @param string                  $content The content to tokenize,
  256.      * @param \PHP_CodeSniffer\Config $config  The config data for the run.
  257.      * @param string                  $eolChar The EOL char used in the content.
  258.      *
  259.      * @return void 
  260.      * @throws TokenizerException If the file appears to be minified.
  261.      */
  262.     public function __construct($contentConfig $config$eolChar='\n')
  263.     {
  264.         if ($this->isMinifiedContent($content$eolChar=== true{
  265.             throw new TokenizerException('File appears to be minified and cannot be processed');
  266.         }
  267.  
  268.         return parent::__construct($content$config$eolChar);
  269.  
  270.     }//end __construct()
  271.  
  272.  
  273.     /**
  274.      * Creates an array of tokens when given some JS code.
  275.      *
  276.      * @param string $string The string to tokenize.
  277.      *
  278.      * @return array 
  279.      */
  280.     public function tokenize($string)
  281.     {
  282.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  283.             echo "\t*** START JS TOKENIZING ***".PHP_EOL;
  284.         }
  285.  
  286.         $maxTokenLength = 0;
  287.         foreach ($this->tokenValues as $token => $values{
  288.             if (strlen($token$maxTokenLength{
  289.                 $maxTokenLength strlen($token);
  290.             }
  291.         }
  292.  
  293.         $tokens          = array();
  294.         $inString        '';
  295.         $stringChar      = null;
  296.         $inComment       '';
  297.         $buffer          '';
  298.         $preStringBuffer '';
  299.         $cleanBuffer     = false;
  300.  
  301.         $commentTokenizer = new Comment();
  302.  
  303.         $tokens[= array(
  304.                      'code'    => T_OPEN_TAG,
  305.                      'type'    => 'T_OPEN_TAG',
  306.                      'content' => '',
  307.                     );
  308.  
  309.         // Convert newlines to single characters for ease of
  310.         // processing. We will change them back later.
  311.         $string str_replace($this->eolChar"\n"$string);
  312.  
  313.         $chars    str_split($string);
  314.         $numChars count($chars);
  315.         for ($i = 0; $i $numChars$i++{
  316.             $char $chars[$i];
  317.  
  318.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  319.                 $content       = Util\Common::prepareForOutput($char);
  320.                 $bufferContent = Util\Common::prepareForOutput($buffer);
  321.  
  322.                 if ($inString !== ''{
  323.                     echo "\t";
  324.                 }
  325.  
  326.                 if ($inComment !== ''{
  327.                     echo "\t";
  328.                 }
  329.  
  330.                 echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL;
  331.             }//end if
  332.  
  333.             if ($inString === '' && $inComment === '' && $buffer !== ''{
  334.                 // If the buffer only has whitespace and we are about to
  335.                 // add a character, store the whitespace first.
  336.                 if (trim($char!== '' && trim($buffer=== ''{
  337.                     $tokens[= array(
  338.                                  'code'    => T_WHITESPACE,
  339.                                  'type'    => 'T_WHITESPACE',
  340.                                  'content' => str_replace("\n"$this->eolChar$buffer),
  341.                                 );
  342.  
  343.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  344.                         $content = Util\Common::prepareForOutput($buffer);
  345.                         echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
  346.                     }
  347.  
  348.                     $buffer '';
  349.                 }
  350.  
  351.                 // If the buffer is not whitespace and we are about to
  352.                 // add a whitespace character, store the content first.
  353.                 if ($inString === ''
  354.                     && $inComment === ''
  355.                     && trim($char=== ''
  356.                     && trim($buffer!== ''
  357.                 {
  358.                     $tokens[= array(
  359.                                  'code'    => T_STRING,
  360.                                  'type'    => 'T_STRING',
  361.                                  'content' => str_replace("\n"$this->eolChar$buffer),
  362.                                 );
  363.  
  364.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  365.                         $content = Util\Common::prepareForOutput($buffer);
  366.                         echo "\t=> Added token T_STRING ($content)".PHP_EOL;
  367.                     }
  368.  
  369.                     $buffer '';
  370.                 }
  371.             }//end if
  372.  
  373.             // Process strings.
  374.             if ($inComment === '' && isset($this->stringTokens[$char]=== true{
  375.                 if ($inString === $char{
  376.                     // This could be the end of the string, but make sure it
  377.                     // is not escaped first.
  378.                     $escapes = 0;
  379.                     for ($x ($i - 1)$x >= 0; $x--{
  380.                         if ($chars[$x!== '\\'{
  381.                             break;
  382.                         }
  383.  
  384.                         $escapes++;
  385.                     }
  386.  
  387.                     if ($escapes === 0 || ($escapes % 2=== 0{
  388.                         // There is an even number escape chars,
  389.                         // so this is not escaped, it is the end of the string.
  390.                         $tokens[= array(
  391.                                      'code'    => T_CONSTANT_ENCAPSED_STRING,
  392.                                      'type'    => 'T_CONSTANT_ENCAPSED_STRING',
  393.                                      'content' => str_replace("\n"$this->eolChar$buffer).$char,
  394.                                     );
  395.  
  396.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  397.                             echo "\t\t* found end of string *".PHP_EOL;
  398.                             $content = Util\Common::prepareForOutput($buffer.$char);
  399.                             echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL;
  400.                         }
  401.  
  402.                         $buffer          '';
  403.                         $preStringBuffer '';
  404.                         $inString        '';
  405.                         $stringChar      = null;
  406.                         continue;
  407.                     }//end if
  408.                 else if ($inString === ''{
  409.                     $inString        $char;
  410.                     $stringChar      $i;
  411.                     $preStringBuffer $buffer;
  412.  
  413.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  414.                         echo "\t\t* looking for string closer *".PHP_EOL;
  415.                     }
  416.                 }//end if
  417.             }//end if
  418.  
  419.             if ($inString !== '' && $char === "\n"{
  420.                 // Unless this newline character is escaped, the string did not
  421.                 // end before the end of the line, which means it probably
  422.                 // wasn't a string at all (maybe a regex).
  423.                 if ($chars[($i - 1)!== '\\'{
  424.                     $i      $stringChar;
  425.                     $buffer $preStringBuffer;
  426.                     $preStringBuffer '';
  427.                     $inString        '';
  428.                     $stringChar      = null;
  429.                     $char            $chars[$i];
  430.  
  431.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  432.                         echo "\t\t* found newline before end of string, bailing *".PHP_EOL;
  433.                     }
  434.                 }
  435.             }
  436.  
  437.             $buffer .= $char;
  438.  
  439.             // We don't look for special tokens inside strings,
  440.             // so if we are in a string, we can continue here now
  441.             // that the current char is in the buffer.
  442.             if ($inString !== ''{
  443.                 continue;
  444.             }
  445.  
  446.             // Special case for T_DIVIDE which can actually be
  447.             // the start of a regular expression.
  448.             if ($buffer === $char && $char === '/' && $chars[($i + 1)!== '*'{
  449.                 $regex $this->getRegexToken(
  450.                     $i,
  451.                     $string,
  452.                     $chars,
  453.                     $tokens,
  454.                     $this->eolChar
  455.                 );
  456.  
  457.                 if ($regex !== null{
  458.                     $tokens[= array(
  459.                                  'code'    => T_REGULAR_EXPRESSION,
  460.                                  'type'    => 'T_REGULAR_EXPRESSION',
  461.                                  'content' => $regex['content'],
  462.                                 );
  463.  
  464.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  465.                         $content = Util\Common::prepareForOutput($regex['content']);
  466.                         echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL;
  467.                     }
  468.  
  469.                     $i           $regex['end'];
  470.                     $buffer      '';
  471.                     $cleanBuffer = false;
  472.                     continue;
  473.                 }//end if
  474.             }//end if
  475.  
  476.             // Check for known tokens, but ignore tokens found that are not at
  477.             // the end of a string, like FOR and this.FORmat.
  478.             if (isset($this->tokenValues[strtolower($buffer)]=== true
  479.                 && (preg_match('|[a-zA-z0-9_]|'$char=== 0
  480.                 || isset($chars[($i + 1)]=== false
  481.                 || preg_match('|[a-zA-z0-9_]|'$chars[($i + 1)]=== 0)
  482.             {
  483.                 $matchedToken    = false;
  484.                 $lookAheadLength ($maxTokenLength strlen($buffer));
  485.  
  486.                 if ($lookAheadLength > 0{
  487.                     // The buffer contains a token type, but we need
  488.                     // to look ahead at the next chars to see if this is
  489.                     // actually part of a larger token. For example,
  490.                     // FOR and FOREACH.
  491.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  492.                         echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL;
  493.                     }
  494.  
  495.                     $charBuffer $buffer;
  496.                     for ($x = 1; $x <= $lookAheadLength$x++{
  497.                         if (isset($chars[($i $x)]=== false{
  498.                             break;
  499.                         }
  500.  
  501.                         $charBuffer .= $chars[($i $x)];
  502.  
  503.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  504.                             $content = Util\Common::prepareForOutput($charBuffer);
  505.                             echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
  506.                         }
  507.  
  508.                         if (isset($this->tokenValues[strtolower($charBuffer)]=== true{
  509.                             // We've found something larger that matches
  510.                             // so we can ignore this char. Except for 1 very specific
  511.                             // case where a comment like /**/ needs to tokenize as
  512.                             // T_COMMENT and not T_DOC_COMMENT.
  513.                             $oldType $this->tokenValues[strtolower($buffer)];
  514.                             $newType $this->tokenValues[strtolower($charBuffer)];
  515.                             if ($oldType === 'T_COMMENT'
  516.                                 && $newType === 'T_DOC_COMMENT'
  517.                                 && $chars[($i $x + 1)=== '/'
  518.                             {
  519.                                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  520.                                     echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL;
  521.                                 }
  522.                             else {
  523.                                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  524.                                     echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL;
  525.                                 }
  526.  
  527.                                 $matchedToken = true;
  528.                                 break;
  529.                             }
  530.                         }//end if
  531.                     }//end for
  532.                 }//end if
  533.  
  534.                 if ($matchedToken === false{
  535.                     if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0{
  536.                         echo "\t\t* look ahead found nothing *".PHP_EOL;
  537.                     }
  538.  
  539.                     $value $this->tokenValues[strtolower($buffer)];
  540.  
  541.                     if ($value === 'T_FUNCTION' && $buffer !== 'function'{
  542.                         // The function keyword needs to be all lowercase or else
  543.                         // it is just a function called "Function".
  544.                         $value 'T_STRING';
  545.                     }
  546.  
  547.                     $tokens[= array(
  548.                                  'code'    => constant($value),
  549.                                  'type'    => $value,
  550.                                  'content' => $buffer,
  551.                                 );
  552.  
  553.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  554.                         $content = Util\Common::prepareForOutput($buffer);
  555.                         echo "\t=> Added token $value ($content)".PHP_EOL;
  556.                     }
  557.  
  558.                     $cleanBuffer = true;
  559.                 }//end if
  560.             else if (isset($this->tokenValues[strtolower($char)]=== true{
  561.                 // No matter what token we end up using, we don't
  562.                 // need the content in the buffer any more because we have
  563.                 // found a valid token.
  564.                 $newContent substr(str_replace("\n"$this->eolChar$buffer)0-1);
  565.                 if ($newContent !== ''{
  566.                     $tokens[= array(
  567.                                  'code'    => T_STRING,
  568.                                  'type'    => 'T_STRING',
  569.                                  'content' => $newContent,
  570.                                 );
  571.  
  572.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  573.                         $content = Util\Common::prepareForOutput(substr($buffer0-1));
  574.                         echo "\t=> Added token T_STRING ($content)".PHP_EOL;
  575.                     }
  576.                 }
  577.  
  578.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  579.                     echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL;
  580.                 }
  581.  
  582.                 // The char is a token type, but we need to look ahead at the
  583.                 // next chars to see if this is actually part of a larger token.
  584.                 // For example, = and ===.
  585.                 $charBuffer   $char;
  586.                 $matchedToken = false;
  587.                 for ($x = 1; $x <= $maxTokenLength$x++{
  588.                     if (isset($chars[($i $x)]=== false{
  589.                         break;
  590.                     }
  591.  
  592.                     $charBuffer .= $chars[($i $x)];
  593.  
  594.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  595.                         $content = Util\Common::prepareForOutput($charBuffer);
  596.                         echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
  597.                     }
  598.  
  599.                     if (isset($this->tokenValues[strtolower($charBuffer)]=== true{
  600.                         // We've found something larger that matches
  601.                         // so we can ignore this char.
  602.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  603.                             $type $this->tokenValues[strtolower($charBuffer)];
  604.                             echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL;
  605.                         }
  606.  
  607.                         $matchedToken = true;
  608.                         break;
  609.                     }
  610.                 }//end for
  611.  
  612.                 if ($matchedToken === false{
  613.                     $value    $this->tokenValues[strtolower($char)];
  614.                     $tokens[= array(
  615.                                  'code'    => constant($value),
  616.                                  'type'    => $value,
  617.                                  'content' => $char,
  618.                                 );
  619.  
  620.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  621.                         echo "\t\t* look ahead found nothing *".PHP_EOL;
  622.                         $content = Util\Common::prepareForOutput($char);
  623.                         echo "\t=> Added token $value ($content)".PHP_EOL;
  624.                     }
  625.  
  626.                     $cleanBuffer = true;
  627.                 else {
  628.                     $buffer $char;
  629.                 }//end if
  630.             }//end if
  631.  
  632.             // Keep track of content inside comments.
  633.             if ($inComment === ''
  634.                 && array_key_exists($buffer$this->commentTokens=== true
  635.             {
  636.                 // This is not really a comment if the content
  637.                 // looks like \// (i.e., it is escaped).
  638.                 if (isset($chars[($i - 2)]=== true && $chars[($i - 2)=== '\\'{
  639.                     $lastToken   array_pop($tokens);
  640.                     $lastContent $lastToken['content'];
  641.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  642.                         $value   $this->tokenValues[strtolower($lastContent)];
  643.                         $content = Util\Common::prepareForOutput($lastContent);
  644.                         echo "\t=> Removed token $value ($content)".PHP_EOL;
  645.                     }
  646.  
  647.                     $lastChars    str_split($lastContent);
  648.                     $lastNumChars count($lastChars);
  649.                     for ($x = 0; $x $lastNumChars$x++{
  650.                         $lastChar $lastChars[$x];
  651.                         $value    $this->tokenValues[strtolower($lastChar)];
  652.                         $tokens[= array(
  653.                                      'code'    => constant($value),
  654.                                      'type'    => $value,
  655.                                      'content' => $lastChar,
  656.                                     );
  657.  
  658.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  659.                             $content = Util\Common::prepareForOutput($lastChar);
  660.                             echo "\t=> Added token $value ($content)".PHP_EOL;
  661.                         }
  662.                     }
  663.                 else {
  664.                     // We have started a comment.
  665.                     $inComment $buffer;
  666.  
  667.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  668.                         echo "\t\t* looking for end of comment *".PHP_EOL;
  669.                     }
  670.                 }//end if
  671.             else if ($inComment !== ''{
  672.                 if ($this->commentTokens[$inComment=== null{
  673.                     // Comment ends at the next newline.
  674.                     if (strpos($buffer"\n"!== false{
  675.                         $inComment '';
  676.                     }
  677.                 else {
  678.                     if ($this->commentTokens[$inComment=== $buffer{
  679.                         $inComment '';
  680.                     }
  681.                 }
  682.  
  683.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  684.                     if ($inComment === ''{
  685.                         echo "\t\t* found end of comment *".PHP_EOL;
  686.                     }
  687.                 }
  688.  
  689.                 if ($inComment === '' && $cleanBuffer === false{
  690.                     $tokens[= array(
  691.                                  'code'    => T_STRING,
  692.                                  'type'    => 'T_STRING',
  693.                                  'content' => str_replace("\n"$this->eolChar$buffer),
  694.                                 );
  695.  
  696.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  697.                         $content = Util\Common::prepareForOutput($buffer);
  698.                         echo "\t=> Added token T_STRING ($content)".PHP_EOL;
  699.                     }
  700.  
  701.                     $buffer '';
  702.                 }
  703.             }//end if
  704.  
  705.             if ($cleanBuffer === true{
  706.                 $buffer      '';
  707.                 $cleanBuffer = false;
  708.             }
  709.         }//end for
  710.  
  711.         if (empty($buffer=== false{
  712.             // Buffer contains whitespace from the end of the file.
  713.             $tokens[= array(
  714.                          'code'    => T_WHITESPACE,
  715.                          'type'    => 'T_WHITESPACE',
  716.                          'content' => str_replace("\n"$this->eolChar$buffer),
  717.                         );
  718.  
  719.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  720.                 $content = Util\Common::prepareForOutput($buffer);
  721.                 echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
  722.             }
  723.         }
  724.  
  725.         $tokens[= array(
  726.                      'code'    => T_CLOSE_TAG,
  727.                      'type'    => 'T_CLOSE_TAG',
  728.                      'content' => '',
  729.                     );
  730.  
  731.         /*
  732.             Now that we have done some basic tokenizing, we need to
  733.             modify the tokens to join some together and split some apart
  734.             so they match what the PHP tokenizer does.
  735.         */
  736.  
  737.         $finalTokens = array();
  738.         $newStackPtr = 0;
  739.         $numTokens   count($tokens);
  740.         for ($stackPtr = 0; $stackPtr $numTokens$stackPtr++{
  741.             $token $tokens[$stackPtr];
  742.  
  743.             /*
  744.                 Look for comments and join the tokens together.
  745.             */
  746.  
  747.             if ($token['code'=== T_COMMENT || $token['code'=== T_DOC_COMMENT{
  748.                 $newContent   '';
  749.                 $tokenContent $token['content'];
  750.  
  751.                 $endContent = null;
  752.                 if (isset($this->commentTokens[$tokenContent]=== true{
  753.                     $endContent $this->commentTokens[$tokenContent];
  754.                 }
  755.  
  756.                 while ($tokenContent !== $endContent{
  757.                     if ($endContent === null
  758.                         && strpos($tokenContent$this->eolChar!== false
  759.                     {
  760.                         // A null end token means the comment ends at the end of
  761.                         // the line so we look for newlines and split the token.
  762.                         $tokens[$stackPtr]['content'substr(
  763.                             $tokenContent,
  764.                             (strpos($tokenContent$this->eolCharstrlen($this->eolChar))
  765.                         );
  766.  
  767.                         $tokenContent substr(
  768.                             $tokenContent,
  769.                             0,
  770.                             (strpos($tokenContent$this->eolCharstrlen($this->eolChar))
  771.                         );
  772.  
  773.                         // If the substr failed, skip the token as the content
  774.                         // will now be blank.
  775.                         if ($tokens[$stackPtr]['content'!== false
  776.                             && $tokens[$stackPtr]['content'!== ''
  777.                         {
  778.                             $stackPtr--;
  779.                         }
  780.  
  781.                         break;
  782.                     }//end if
  783.  
  784.                     $stackPtr++;
  785.                     $newContent .= $tokenContent;
  786.                     if (isset($tokens[$stackPtr]=== false{
  787.                         break;
  788.                     }
  789.  
  790.                     $tokenContent $tokens[$stackPtr]['content'];
  791.                 }//end while
  792.  
  793.                 if ($token['code'=== T_DOC_COMMENT{
  794.                     $commentTokens $commentTokenizer->tokenizeString($newContent.$tokenContent$this->eolChar$newStackPtr);
  795.                     foreach ($commentTokens as $commentToken{
  796.                         $finalTokens[$newStackPtr$commentToken;
  797.                         $newStackPtr++;
  798.                     }
  799.  
  800.                     continue;
  801.                 else {
  802.                     // Save the new content in the current token so
  803.                     // the code below can chop it up on newlines.
  804.                     $token['content'$newContent.$tokenContent;
  805.                 }
  806.             }//end if
  807.  
  808.             /*
  809.                 If this token has newlines in its content, split each line up
  810.                 and create a new token for each line. We do this so it's easier
  811.                 to ascertain where errors occur on a line.
  812.                 Note that $token[1] is the token's content.
  813.             */
  814.  
  815.             if (strpos($token['content']$this->eolChar!== false{
  816.                 $tokenLines explode($this->eolChar$token['content']);
  817.                 $numLines   count($tokenLines);
  818.  
  819.                 for ($i = 0; $i $numLines$i++{
  820.                     $newToken['content'$tokenLines[$i];
  821.                     if ($i === ($numLines - 1)) {
  822.                         if ($tokenLines[$i=== ''{
  823.                             break;
  824.                         }
  825.                     else {
  826.                         $newToken['content'.= $this->eolChar;
  827.                     }
  828.  
  829.                     $newToken['type']          $token['type'];
  830.                     $newToken['code']          $token['code'];
  831.                     $finalTokens[$newStackPtr$newToken;
  832.                     $newStackPtr++;
  833.                 }
  834.             else {
  835.                 $finalTokens[$newStackPtr$token;
  836.                 $newStackPtr++;
  837.             }//end if
  838.  
  839.             // Convert numbers, including decimals.
  840.             if ($token['code'=== T_STRING
  841.                 || $token['code'=== T_OBJECT_OPERATOR
  842.             {
  843.                 $newContent  '';
  844.                 $oldStackPtr $stackPtr;
  845.                 while (preg_match('|^[0-9\.]+$|'$tokens[$stackPtr]['content']!== 0{
  846.                     $newContent .= $tokens[$stackPtr]['content'];
  847.                     $stackPtr++;
  848.                 }
  849.  
  850.                 if ($newContent !== '' && $newContent !== '.'{
  851.                     $finalTokens[($newStackPtr - 1)]['content'$newContent;
  852.                     if (ctype_digit($newContent=== true{
  853.                         $finalTokens[($newStackPtr - 1)]['code'constant('T_LNUMBER');
  854.                         $finalTokens[($newStackPtr - 1)]['type''T_LNUMBER';
  855.                     else {
  856.                         $finalTokens[($newStackPtr - 1)]['code'constant('T_DNUMBER');
  857.                         $finalTokens[($newStackPtr - 1)]['type''T_DNUMBER';
  858.                     }
  859.  
  860.                     $stackPtr--;
  861.                     continue;
  862.                 else {
  863.                     $stackPtr $oldStackPtr;
  864.                 }
  865.             }//end if
  866.  
  867.             // Convert the token after an object operator into a string, in most cases.
  868.             if ($token['code'=== T_OBJECT_OPERATOR{
  869.                 for ($i ($stackPtr + 1)$i $numTokens$i++{
  870.                     if (isset(Util\Tokens::$emptyTokens[$tokens[$i]['code']]=== true{
  871.                         continue;
  872.                     }
  873.  
  874.                     if ($tokens[$i]['code'!== T_PROTOTYPE
  875.                         && $tokens[$i]['code'!== T_LNUMBER
  876.                         && $tokens[$i]['code'!== T_DNUMBER
  877.                     {
  878.                         $tokens[$i]['code'= T_STRING;
  879.                         $tokens[$i]['type''T_STRING';
  880.                     }
  881.  
  882.                     break;
  883.                 }
  884.             }
  885.         }//end for
  886.  
  887.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  888.             echo "\t*** END TOKENIZING ***".PHP_EOL;
  889.         }
  890.  
  891.         return $finalTokens;
  892.  
  893.     }//end tokenize()
  894.  
  895.  
  896.     /**
  897.      * Tokenizes a regular expression if one is found.
  898.      *
  899.      * If a regular expression is not found, NULL is returned.
  900.      *
  901.      * @param string $char   The index of the possible regex start character.
  902.      * @param string $string The complete content of the string being tokenized.
  903.      * @param string $chars  An array of characters being tokenized.
  904.      * @param string $tokens The current array of tokens found in the string.
  905.      *
  906.      * @return void 
  907.      */
  908.     public function getRegexToken($char$string$chars$tokens)
  909.     {
  910.         $beforeTokens = array(
  911.                          T_EQUAL               => true,
  912.                          T_IS_NOT_EQUAL        => true,
  913.                          T_IS_IDENTICAL        => true,
  914.                          T_IS_NOT_IDENTICAL    => true,
  915.                          T_OPEN_PARENTHESIS    => true,
  916.                          T_OPEN_SQUARE_BRACKET => true,
  917.                          T_RETURN              => true,
  918.                          T_BOOLEAN_OR          => true,
  919.                          T_BOOLEAN_AND         => true,
  920.                          T_BITWISE_OR          => true,
  921.                          T_BITWISE_AND         => true,
  922.                          T_COMMA               => true,
  923.                          T_COLON               => true,
  924.                          T_TYPEOF              => true,
  925.                          T_INLINE_THEN         => true,
  926.                          T_INLINE_ELSE         => true,
  927.                         );
  928.  
  929.         $afterTokens = array(
  930.                         ','            => true,
  931.                         ')'            => true,
  932.                         ']'            => true,
  933.                         ';'            => true,
  934.                         ' '            => true,
  935.                         '.'            => true,
  936.                         ':'            => true,
  937.                         $this->eolChar => true,
  938.                        );
  939.  
  940.         // Find the last non-whitespace token that was added
  941.         // to the tokens array.
  942.         $numTokens count($tokens);
  943.         for ($prev ($numTokens - 1)$prev >= 0; $prev--{
  944.             if (isset(Util\Tokens::$emptyTokens[$tokens[$prev]['code']]=== false{
  945.                 break;
  946.             }
  947.         }
  948.  
  949.         if (isset($beforeTokens[$tokens[$prev]['code']]=== false{
  950.             return null;
  951.         }
  952.  
  953.         // This is probably a regular expression, so look for the end of it.
  954.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  955.             echo "\t* token possibly starts a regular expression *".PHP_EOL;
  956.         }
  957.  
  958.         $numChars count($chars);
  959.         for ($next ($char + 1)$next $numChars$next++{
  960.             if ($chars[$next=== '/'{
  961.                 // Just make sure this is not escaped first.
  962.                 if ($chars[($next - 1)!== '\\'{
  963.                     // In the simple form: /.../ so we found the end.
  964.                     break;
  965.                 else if ($chars[($next - 2)=== '\\'{
  966.                     // In the form: /...\\/ so we found the end.
  967.                     break;
  968.                 }
  969.             else {
  970.                 $possibleEolChar substr($string$nextstrlen($this->eolChar));
  971.                 if ($possibleEolChar === $this->eolChar{
  972.                     // This is the last token on the line and regular
  973.                     // expressions need to be defined on a single line,
  974.                     // so this is not a regular expression.
  975.                     break;
  976.                 }
  977.             }
  978.         }
  979.  
  980.         if ($chars[$next!== '/'{
  981.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  982.                 echo "\t* could not find end of regular expression *".PHP_EOL;
  983.             }
  984.  
  985.             return null;
  986.         }
  987.  
  988.         while (preg_match('|[a-zA-Z]|'$chars[($next + 1)]!== 0{
  989.             // The token directly after the end of the regex can
  990.             // be modifiers like global and case insensitive
  991.             // (.e.g, /pattern/gi).
  992.             $next++;
  993.         }
  994.  
  995.         $regexEnd $next;
  996.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  997.             echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL;
  998.         }
  999.  
  1000.         for ($next ($next + 1)$next $numChars$next++{
  1001.             if ($chars[$next!== ' '{
  1002.                 break;
  1003.             else {
  1004.                 $possibleEolChar substr($string$nextstrlen($this->eolChar));
  1005.                 if ($possibleEolChar === $this->eolChar{
  1006.                     // This is the last token on the line.
  1007.                     break;
  1008.                 }
  1009.             }
  1010.         }
  1011.  
  1012.         if (isset($afterTokens[$chars[$next]]=== false{
  1013.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  1014.                 echo "\t* tokens after regular expression do not look correct *".PHP_EOL;
  1015.             }
  1016.  
  1017.             return null;
  1018.         }
  1019.  
  1020.         // This is a regular expression, so join all the tokens together.
  1021.         $content '';
  1022.         for ($x $char$x <= $regexEnd$x++{
  1023.             $content .= $chars[$x];
  1024.         }
  1025.  
  1026.         $token = array(
  1027.                   'start'   => $char,
  1028.                   'end'     => $regexEnd,
  1029.                   'content' => $content,
  1030.                  );
  1031.  
  1032.         return $token;
  1033.  
  1034.     }//end getRegexToken()
  1035.  
  1036.  
  1037.     /**
  1038.      * Performs additional processing after main tokenizing.
  1039.      *
  1040.      * This additional processing looks for properties, closures, labels and objects.
  1041.      *
  1042.      * @return void 
  1043.      */
  1044.     public function processAdditional()
  1045.     {
  1046.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  1047.             echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL;
  1048.         }
  1049.  
  1050.         $numTokens  count($this->tokens);
  1051.         $classStack = array();
  1052.  
  1053.         for ($i = 0; $i $numTokens$i++{
  1054.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  1055.                 $type    $this->tokens[$i]['type'];
  1056.                 $content = Util\Common::prepareForOutput($this->tokens[$i]['content']);
  1057.  
  1058.                 echo str_repeat("\t"count($classStack));
  1059.                 echo "\tProcess token $i$type => $content".PHP_EOL;
  1060.             }
  1061.  
  1062.             // Looking for functions that are actually closures.
  1063.             if ($this->tokens[$i]['code'=== T_FUNCTION && isset($this->tokens[$i]['scope_opener']=== true{
  1064.                 for ($x ($i + 1)$x $numTokens$x++{
  1065.                     if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]=== false{
  1066.                         break;
  1067.                     }
  1068.                 }
  1069.  
  1070.                 if ($this->tokens[$x]['code'=== T_OPEN_PARENTHESIS{
  1071.                     $this->tokens[$i]['code'T_CLOSURE;
  1072.                     $this->tokens[$i]['type''T_CLOSURE';
  1073.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  1074.                         $line $this->tokens[$i]['line'];
  1075.                         echo str_repeat("\t"count($classStack));
  1076.                         echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE *".PHP_EOL;
  1077.                     }
  1078.  
  1079.                     for ($x ($this->tokens[$i]['scope_opener'+ 1)$x $this->tokens[$i]['scope_closer']$x++{
  1080.                         if (isset($this->tokens[$x]['conditions'][$i]=== false{
  1081.                             continue;
  1082.                         }
  1083.  
  1084.                         $this->tokens[$x]['conditions'][$iT_CLOSURE;
  1085.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  1086.                             $type $this->tokens[$x]['type'];
  1087.                             echo str_repeat("\t"count($classStack));
  1088.                             echo "\t\t* cleaned $x ($type) *".PHP_EOL;
  1089.                         }
  1090.                     }
  1091.                 }//end if
  1092.  
  1093.                 continue;
  1094.             else if ($this->tokens[$i]['code'=== T_OPEN_CURLY_BRACKET
  1095.                 && isset($this->tokens[$i]['scope_condition']=== false
  1096.                 && isset($this->tokens[$i]['bracket_closer']=== true
  1097.             {
  1098.                 $condition end($this->tokens[$i]['conditions']);
  1099.                 reset($this->tokens[$i]['conditions']);
  1100.                 if ($condition === T_CLASS{
  1101.                     // Possibly an ES6 method. To be classified as one, the previous
  1102.                     // non-empty tokens need to be a set of parenthesis, and then a string
  1103.                     // (the method name).
  1104.                     for ($parenCloser ($i - 1)$parenCloser > 0; $parenCloser--{
  1105.                         if (isset(Util\Tokens::$emptyTokens[$this->tokens[$parenCloser]['code']]=== false{
  1106.                             break;
  1107.                         }
  1108.                     }
  1109.  
  1110.                     if ($this->tokens[$parenCloser]['code'=== T_CLOSE_PARENTHESIS{
  1111.                         $parenOpener $this->tokens[$parenCloser]['parenthesis_opener'];
  1112.                         for ($name ($parenOpener - 1)$name > 0; $name--{
  1113.                             if (isset(Util\Tokens::$emptyTokens[$this->tokens[$name]['code']]=== false{
  1114.                                 break;
  1115.                             }
  1116.                         }
  1117.  
  1118.                         if ($this->tokens[$name]['code'=== T_STRING{
  1119.                             // We found a method name.
  1120.                             if (PHP_CODESNIFFER_VERBOSITY > 1{
  1121.                                 $line $this->tokens[$name]['line'];
  1122.                                 echo str_repeat("\t"count($classStack));
  1123.                                 echo "\t* token $name on line $line changed from T_STRING to T_FUNCTION *".PHP_EOL;
  1124.                             }
  1125.  
  1126.                             $closer $this->tokens[$i]['bracket_closer'];
  1127.  
  1128.                             $this->tokens[$name]['code'= T_FUNCTION;
  1129.                             $this->tokens[$name]['type''T_FUNCTION';
  1130.  
  1131.                             foreach (array($name$i$closeras $token{
  1132.                                 $this->tokens[$token]['scope_condition']    $name;
  1133.                                 $this->tokens[$token]['scope_opener']       $i;
  1134.                                 $this->tokens[$token]['scope_closer']       $closer;
  1135.                                 $this->tokens[$token]['parenthesis_opener'$parenOpener;
  1136.                                 $this->tokens[$token]['parenthesis_closer'$parenCloser;
  1137.                                 $this->tokens[$token]['parenthesis_owner']  $name;
  1138.                             }
  1139.  
  1140.                             $this->tokens[$parenOpener]['parenthesis_owner'$name;
  1141.                             $this->tokens[$parenCloser]['parenthesis_owner'$name;
  1142.  
  1143.                             for ($x ($i + 1)$x $closer$x++{
  1144.                                 $this->tokens[$x]['conditions'][$name= T_FUNCTION;
  1145.                                 ksort($this->tokens[$x]['conditions']SORT_NUMERIC);
  1146.                                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  1147.                                     $type $this->tokens[$x]['type'];
  1148.                                     echo str_repeat("\t"count($classStack));
  1149.                                     echo "\t\t* added T_FUNCTION condition to $x ($type) *".PHP_EOL;
  1150.                                 }
  1151.                             }
  1152.  
  1153.                             continue;
  1154.                         }//end if
  1155.                     }//end if
  1156.                 }//end if
  1157.  
  1158.                 $classStack[$i;
  1159.  
  1160.                 $closer $this->tokens[$i]['bracket_closer'];
  1161.                 $this->tokens[$i]['code']      T_OBJECT;
  1162.                 $this->tokens[$i]['type']      'T_OBJECT';
  1163.                 $this->tokens[$closer]['code'T_CLOSE_OBJECT;
  1164.                 $this->tokens[$closer]['type''T_CLOSE_OBJECT';
  1165.  
  1166.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  1167.                     echo str_repeat("\t"count($classStack));
  1168.                     echo "\t* token $i converted from T_OPEN_CURLY_BRACKET to T_OBJECT *".PHP_EOL;
  1169.                     echo str_repeat("\t"count($classStack));
  1170.                     echo "\t* token $closer converted from T_CLOSE_CURLY_BRACKET to T_CLOSE_OBJECT *".PHP_EOL;
  1171.                 }
  1172.  
  1173.                 for ($x ($i + 1)$x $closer$x++{
  1174.                     $this->tokens[$x]['conditions'][$iT_OBJECT;
  1175.                     ksort($this->tokens[$x]['conditions']SORT_NUMERIC);
  1176.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  1177.                         $type $this->tokens[$x]['type'];
  1178.                         echo str_repeat("\t"count($classStack));
  1179.                         echo "\t\t* added T_OBJECT condition to $x ($type) *".PHP_EOL;
  1180.                     }
  1181.                 }
  1182.             else if ($this->tokens[$i]['code'=== T_CLOSE_OBJECT{
  1183.                 $opener array_pop($classStack);
  1184.             else if ($this->tokens[$i]['code'=== T_COLON{
  1185.                 // If it is a scope opener, it belongs to a
  1186.                 // DEFAULT or CASE statement.
  1187.                 if (isset($this->tokens[$i]['scope_condition']=== true{
  1188.                     continue;
  1189.                 }
  1190.  
  1191.                 // Make sure this is not part of an inline IF statement.
  1192.                 for ($x ($i - 1)$x >= 0; $x--{
  1193.                     if ($this->tokens[$x]['code'=== T_INLINE_THEN{
  1194.                         $this->tokens[$i]['code'T_INLINE_ELSE;
  1195.                         $this->tokens[$i]['type''T_INLINE_ELSE';
  1196.  
  1197.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  1198.                             echo str_repeat("\t"count($classStack));
  1199.                             echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL;
  1200.                         }
  1201.  
  1202.                         continue(2);
  1203.                     else if ($this->tokens[$x]['line'$this->tokens[$i]['line']{
  1204.                         break;
  1205.                     }
  1206.                 }
  1207.  
  1208.                 // The string to the left of the colon is either a property or label.
  1209.                 for ($label ($i - 1)$label >= 0; $label--{
  1210.                     if (isset(Util\Tokens::$emptyTokens[$this->tokens[$label]['code']]=== false{
  1211.                         break;
  1212.                     }
  1213.                 }
  1214.  
  1215.                 if ($this->tokens[$label]['code'!== T_STRING
  1216.                     && $this->tokens[$label]['code'!== T_CONSTANT_ENCAPSED_STRING
  1217.                 {
  1218.                     continue;
  1219.                 }
  1220.  
  1221.                 if (empty($classStack=== false{
  1222.                     $this->tokens[$label]['code'T_PROPERTY;
  1223.                     $this->tokens[$label]['type''T_PROPERTY';
  1224.  
  1225.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  1226.                         echo str_repeat("\t"count($classStack));
  1227.                         echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL;
  1228.                     }
  1229.                 else {
  1230.                     $this->tokens[$label]['code'T_LABEL;
  1231.                     $this->tokens[$label]['type''T_LABEL';
  1232.  
  1233.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  1234.                         echo str_repeat("\t"count($classStack));
  1235.                         echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL;
  1236.                     }
  1237.                 }//end if
  1238.             }//end if
  1239.         }//end for
  1240.  
  1241.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  1242.             echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL;
  1243.         }
  1244.  
  1245.     }//end processAdditional()
  1246.  
  1247.  
  1248. }//end class

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