/**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  * @param int                  $stackPtr  The position of the current token
  *                                        in the stack passed in $tokens.
  *
  * @todo Allow T_CONSTANT_ENCAPSED_STRING?
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     // Merge any custom functions with the defaults, if we haven't already.
     if (!self::$addedCustomFunctions) {
         self::$sanitizingFunctions = array_merge(self::$sanitizingFunctions, $this->customSanitizingFunctions);
         self::$autoEscapedFunctions = array_merge(self::$autoEscapedFunctions, $this->customAutoEscapedFunctions);
         self::$addedCustomFunctions = true;
     }
     $tokens = $phpcsFile->getTokens();
     // If function, not T_ECHO nor T_PRINT
     if ($tokens[$stackPtr]['code'] == T_STRING) {
         // Skip if it is a function but is not of the printing functions ( self::needSanitizingFunctions )
         if (!in_array($tokens[$stackPtr]['content'], $this->needSanitizingFunctions)) {
             return;
         }
         $stackPtr++;
         // Ignore the starting bracket
     }
     // Ensure that the next token is a whitespace.
     $stackPtr++;
     if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
         $stackPtr++;
     }
     // Checking for the ignore comment, ex: //xss ok
     $isAtEndOfStatement = false;
     $commentOkRegex = '/xss\\W*(ok|pass|clear|whitelist)/i';
     $tokensCount = count($tokens);
     for ($i = $stackPtr; $i < $tokensCount; $i++) {
         if ($tokens[$i]['code'] === T_SEMICOLON) {
             $isAtEndOfStatement = true;
         }
         if ($isAtEndOfStatement === true && in_array($tokens[$i]['code'], array(T_SEMICOLON, T_WHITESPACE, T_COMMENT)) === false) {
             break;
         }
         preg_match($commentOkRegex, $tokens[$i]['content'], $matches);
         if ($tokens[$i]['code'] === T_COMMENT && empty($matches) === false) {
             return;
         }
     }
     // looping through echo'd components
     $watch = true;
     for ($i = $stackPtr; $i < count($tokens); $i++) {
         // End processing if found the end of statement
         if ($tokens[$i]['code'] == T_SEMICOLON) {
             return;
         }
         // Ignore whitespaces
         if ($tokens[$i]['code'] == T_WHITESPACE) {
             continue;
         }
         // Wake up on concatenation characters, another part to check
         if (in_array($tokens[$i]['code'], array(T_STRING_CONCAT))) {
             $watch = true;
             continue;
         }
         if ($watch === false) {
             continue;
         }
         $watch = false;
         // Allow T_CONSTANT_ENCAPSED_STRING eg: echo 'Some String';
         if (in_array($tokens[$i]['code'], array(T_CONSTANT_ENCAPSED_STRING))) {
             continue;
         }
         // Allow int/double/bool casted variables
         if (in_array($tokens[$i]['code'], array(T_INT_CAST, T_DOUBLE_CAST, T_BOOL_CAST))) {
             continue;
         }
         // Now check that next token is a function call.
         if (in_array($tokens[$i]['code'], array(T_STRING)) === false) {
             $phpcsFile->addError("Expected next thing to be a escaping function, not '%s'", $i, null, $tokens[$i]['content']);
             continue;
         } else {
             $functionName = $tokens[$i]['content'];
             if (in_array($functionName, self::$autoEscapedFunctions) === false && in_array($functionName, self::$sanitizingFunctions) === false) {
                 $phpcsFile->addError("Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '%s'", $i, null, $tokens[$i]['content']);
             }
             // Skip pointer to after the function
             if ($_pos = $phpcsFile->findNext(array(T_OPEN_PARENTHESIS), $i, null, null, null, true)) {
                 $i = $tokens[$_pos]['parenthesis_closer'];
             }
             continue;
         }
     }
 }