findPrevious() public method

If a value is specified, the previous token of the specified type(s) containing the specified value will be returned. Returns false if no token can be found.
See also: findNext()
public findPrevious ( integer | array $types, integer $start, integer $end = null, boolean $exclude = false, string $value = null, boolean $local = false ) : integer | boolean
$types integer | array The type(s) of tokens to search for.
$start integer The position to start searching from in the token stack.
$end integer The end position to fail if no token is found. if not specified or null, end will default to the start of the token stack.
$exclude boolean If true, find the previous token that are NOT of the types specified in $types.
$value string The value that the token(s) must be equal to. If value is omitted, tokens with any value will be returned.
$local boolean If true, tokens outside the current statement will not be checked. IE. checking will stop at the previous semi-colon found.
return integer | boolean
 public function process(CodeSnifferFile $file, $stackPtr)
 {
     $tokens = $file->getTokens();
     $fileName = $file->getFilename();
     // Collect use statement aliases
     if ($tokens[$stackPtr]['code'] === T_USE) {
         /** function () use ($var) {} */
         $previousPtr = $file->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
         if ($tokens[$previousPtr]['code'] === T_CLOSE_PARENTHESIS) {
             return;
         }
         /** use Trait; */
         if ($file->findPrevious([T_CLASS, T_TRAIT], $stackPtr)) {
             return;
         }
         list($stackPtr, $namespaceAlias, $fullyQualifiedNamespace) = $this->getNamespace($stackPtr + 1, $file);
         if (!isset(static::$aliases[$fileName])) {
             static::$aliases[$fileName] = [];
         }
         static::$aliases[$fileName][] = $namespaceAlias;
         return;
     }
     // Check if aliased exist for caught exceptions
     $catchPtr = $tokens[$stackPtr]['parenthesis_opener'] + 1;
     $exceptionPtr = $file->findNext([T_CLASS, T_INTERFACE], $catchPtr, $tokens[$stackPtr]['parenthesis_closer'], true);
     $exceptionName = $tokens[$exceptionPtr]['content'];
     if (!in_array($exceptionName, static::$aliases[$fileName], false)) {
         $file->addError(sprintf('Trying to catch an undefined exception. Please add use-statement for "%s"', $exceptionName), $exceptionPtr);
     }
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the 
  *        document
  * @param int $stackPtr Position of the current token in the stack passed 
  *        in $tokens
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     switch ($tokens[$stackPtr]['type']) {
         case 'T_BOOLEAN_AND':
         case 'T_BOOLEAN_OR':
             $error = 'Operators && and || are not allowed, use AND and OR instead';
             $phpcsFile->addError($error, $stackPtr);
             break;
         default:
             $beforePtr = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
             $afterPtr = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
             if ($tokens[$afterPtr]['type'] == 'T_VARIABLE') {
                 switch ($tokens[$beforePtr]['type']) {
                     case 'T_STRING':
                         $beforePtr = $phpcsFile->findPrevious(T_WHITESPACE, $beforePtr - 1, null, true);
                         if ($tokens[$beforePtr]['type'] == 'T_OBJECT_OPERATOR') {
                             break;
                         }
                     case 'T_FALSE':
                     case 'T_TRUE':
                     case 'T_NULL':
                         $error = 'Variables should precede constants in comparison operations';
                         $phpcsFile->addError($error, $stackPtr);
                         break;
                 }
             }
             break;
     }
 }
 /**
  * Processes this sniff, 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') {
         return;
     }
     $commentLine = $tokens[$stackPtr]['line'];
     $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
     if ($tokens[$lastContent]['line'] !== $commentLine) {
         return;
     }
     if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
         return;
     }
     // Special case for JS files.
     if ($tokens[$lastContent]['code'] === T_COMMA || $tokens[$lastContent]['code'] === T_SEMICOLON) {
         $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $lastContent - 1, null, true);
         if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
             return;
         }
     }
     $error = 'Comments may not appear after statements';
     $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found');
     if ($fix === true) {
         $phpcsFile->fixer->addNewlineBefore($stackPtr);
     }
 }
 /**
  * Processes this sniff, 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $next = $phpcsFile->findNext(T_INLINE_HTML, $stackPtr + 1, null, true);
     if ($next !== false) {
         return;
     }
     $has_html = $phpcsFile->findPrevious(T_INLINE_HTML, $stackPtr - 1);
     $prev = $phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1);
     if ($has_html !== false && $prev !== false && $tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
         // allow closing tag for single line PHP blocks in HTML files
         return;
     }
     // We've found the last closing tag in the file so the only thing
     // potentially remaining is inline HTML. Now we need to figure out
     // whether or not it's just a bunch of whitespace.
     $content = '';
     for ($i = $stackPtr + 1; $i < $phpcsFile->numTokens; $i++) {
         $content .= $tokens[$i]['content'];
     }
     // Check if the remaining inline HTML is just whitespace.
     $content = trim($content);
     if (empty($content)) {
         $error = 'A closing tag is not permitted at the end of a PHP file';
         $phpcsFile->addError($error, $stackPtr, 'NotAllowed');
     }
 }
	/**
	 * 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.
	 *
	 * @return void
	 */
	public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
	{
		$tokens = $phpcsFile->getTokens();

		$prev = $phpcsFile->findPrevious(T_SEMICOLON, ($stackPtr - 1));
		if ($prev === false) {
			return;
		}

		// Ignore multiple statements in a FOR condition.
		if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
			foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) {
				$owner = $tokens[$bracket]['parenthesis_owner'];
				if ($tokens[$owner]['code'] === T_FOR) {
					return;
				}
			}
		}

		if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {

			$prevOpen = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
			$nextEnd = $phpcsFile->findNext(T_CLOSE_TAG, ($stackPtr + 1));
			if ($tokens[$prevOpen]['line'] === $tokens[$stackPtr]['line'] && $tokens[$nextEnd]['line'] === $tokens[$stackPtr]['line']) {
				return; // Ignore if it is in a template (open and close tag in the same line)
			}
			else {
				$error = 'Each PHP statement must be on a line by itself';
				$phpcsFile->addWarning($error, $stackPtr);
				return;
			}
		}

	}//end process()
 /**
  * Process the sniff. Will be engaged when one of the tokens from ::register() is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile An instance of the current source file being scanned.
  * @param int $stackPtr The position of the encountered token in the provided file.
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Nothing to do if the file is already in the global namespace.
     if ($phpcsFile->findPrevious(T_NAMESPACE, $stackPtr) === false) {
         return;
     }
     // Only proceed with checking the matched namespaced string if is not part of a `namespace Vendor\Foo;` or a `use Vendor\Bar as Baz;` statement.
     if ($phpcsFile->findPrevious([T_NAMESPACE, T_USE], $stackPtr - 1, null, false, null, true) === false) {
         $nextNonClassSegment = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING], $stackPtr + 1, null, true);
         $lastNsSeperator = $phpcsFile->findPrevious(T_NS_SEPARATOR, $nextNonClassSegment);
         // Only report for the last backslash matched in a single namespace string. (This sniff will trigger on each slash from `new \Some\Vendor\Lib();`, so this makes sure we don't report 3 errors for that same statement.)
         if ($lastNsSeperator === $stackPtr) {
             $start = $phpcsFile->findPrevious([T_NS_SEPARATOR, T_STRING], $stackPtr - 1, null, true) + 1;
             $end = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING], $start + 1, null, true);
             $class = '';
             for ($i = $start; $i < $end; $i++) {
                 $class .= $tokens[$i]['content'];
             }
             $tClass = $phpcsFile->findPrevious(T_CLASS, $stackPtr - 1);
             // Check if the code is attempting to extend a class with the same name.
             if ($tClass !== false) {
                 $newClass = $phpcsFile->findNext(T_STRING, $tClass);
                 if ($tokens[$newClass]['content'] == $tokens[$end - 1]['content']) {
                     return;
                 }
                 $err = 'Namespaced class (%s) must be imported before use.';
                 $data = [$class];
                 $phpcsFile->addError($err, $stackPtr, 'ClassMustBeImported', $data);
             }
         }
     }
 }
 /**
  * Processes the function tokens within the class.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  * @param int                  $stackPtr  The position where the token was found.
  * @param int                  $currScope The current scope opener token.
  *
  * @return void
  */
 protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
 {
     $tokens = $phpcsFile->getTokens();
     $methodName = $phpcsFile->getDeclarationName($stackPtr);
     if ($methodName === null) {
         // Ignore closures.
         return;
     }
     $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
     if ($modifier === false || $tokens[$modifier]['line'] !== $tokens[$stackPtr]['line']) {
         $error = 'Visibility must be declared on method "%s"';
         $data = array($methodName);
         $previous = $phpcsFile->findPrevious(array(T_WHITESPACE), $stackPtr - 1, null, true);
         // Only correct the trivial cases for now
         if (!$modifier && $tokens[$modifier]['line'] === $tokens[$stackPtr]['line']) {
             $phpcsFile->addFixableError($error, $stackPtr, 'Missing', $data);
             $visbility = 'public';
             $name = substr($tokens[$stackPtr]['content'], 1);
             $totalUnderscores = 0;
             while (strpos($name, '_') === 0) {
                 $totalUnderscores++;
                 $name = substr($name, 1);
             }
             if ($totalUnderscores > 1) {
                 $visbility = 'private';
             } elseif ($totalUnderscores > 0) {
                 $visbility = 'protected';
             }
         } else {
             $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
         }
         //TODO
     }
 }
 /**
  * @param \PHP_CodeSniffer_File $phpcsFile
  * @param int $stackPtr
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = PHP_CodeSniffer_Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         // Inline comments might just be closing comments for
         // control structures or functions instead of function comments
         // using the wrong comment type. If there is other code on the line,
         // assume they relate to that code.
         $prev = $phpcsFile->findPrevious($find, $commentEnd - 1, null, true);
         if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
             $commentEnd = $prev;
         }
     }
     if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) {
         if (array_key_exists('scope_opener', $tokens[$stackPtr]) && $this->functionHasReturn($phpcsFile, $stackPtr)) {
             $phpcsFile->addError('Function has return keyword but no doc block', $stackPtr);
             return;
         }
         if ($this->functionHasParams($phpcsFile, $stackPtr)) {
             $phpcsFile->addError('Function has parameters but no doc block', $stackPtr);
         }
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $prev = $phpcsFile->findPrevious(T_SEMICOLON, $stackPtr - 1);
     if ($prev === false) {
         return;
     }
     // Ignore multiple statements in a FOR condition.
     if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
         foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) {
             if (isset($tokens[$bracket]['parenthesis_owner']) === false) {
                 // Probably a closure sitting inside a function call.
                 continue;
             }
             $owner = $tokens[$bracket]['parenthesis_owner'];
             if ($tokens[$owner]['code'] === T_FOR) {
                 return;
             }
         }
     }
     if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
         $inline_html = $phpcsFile->findPrevious(T_INLINE_HTML, $stackPtr - 1);
         if ($inline_html !== false && $tokens[$inline_html]['line'] === $tokens[$stackPtr]['line']) {
             return;
         }
         $error = 'Each PHP statement must be on a line by itself';
         $phpcsFile->addError($error, $stackPtr, 'SameLine');
         return;
     }
 }
 /**
  * Processes the function tokens within the class.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  * @param int                  $stackPtr  The position where the token was found.
  *
  * @return void
  */
 protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
     if ($modifier === false || $tokens[$modifier]['line'] !== $tokens[$stackPtr]['line']) {
         $error = 'Scope modifier not specified for member variable "%s"';
         $previous = $phpcsFile->findPrevious(array(T_WHITESPACE), $stackPtr - 1, null, true);
         $data = array($tokens[$stackPtr]['content']);
         if ($previous && $tokens[$previous]['code'] === T_VAR) {
             $phpcsFile->addFixableError($error, $stackPtr, 'Missing', $data);
             if ($phpcsFile->fixer->enabled === true) {
                 $visbility = 'public';
                 $name = substr($tokens[$stackPtr]['content'], 1);
                 $totalUnderscores = 0;
                 while (strpos($name, '_') === 0) {
                     $totalUnderscores++;
                     $name = substr($name, 1);
                 }
                 if ($totalUnderscores > 1) {
                     $visbility = 'private';
                 } elseif ($totalUnderscores > 0) {
                     $visbility = 'protected';
                 }
                 $phpcsFile->fixer->replaceToken($previous, $visbility);
             }
         } else {
             $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
         }
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $tokenizer = $phpcsFile->tokenizerType;
     $openBracket = $tokens[$stackPtr]['parenthesis_opener'];
     $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
     if ($tokens[$stackPtr]['code'] === T_FOR) {
         // We only want to check the condition in FOR loops.
         $start = $phpcsFile->findNext(T_SEMICOLON, $openBracket + 1);
         $end = $phpcsFile->findPrevious(T_SEMICOLON, $closeBracket - 1);
     } else {
         $start = $openBracket;
         $end = $closeBracket;
     }
     for ($i = $start + 1; $i < $end; $i++) {
         if ($tokens[$i]['code'] === T_STRING && in_array($tokens[$i]['content'], $this->forbiddenFunctions[$tokenizer])) {
             $functionName = $tokens[$i]['content'];
             if ($tokenizer === 'JS') {
                 // Needs to be in the form object.function to be valid.
                 $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i - 1, null, true);
                 if ($prev === false || $tokens[$prev]['code'] !== T_OBJECT_OPERATOR) {
                     continue;
                 }
                 $functionName = 'object.' . $functionName;
             } else {
                 $functionName .= '()';
             }
             $error = 'The use of %s inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead';
             $data = array($functionName);
             $phpcsFile->addError($error, $i, 'Found', $data);
         }
         //end if
     }
     //end for
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile
  * @param int $stackPtr
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $functionToken = $phpcsFile->findNext(T_FUNCTION, $stackPtr);
     if ($functionToken === false) {
         return;
     }
     $nameToken = $phpcsFile->findNext(T_STRING, $functionToken);
     if (in_array($tokens[$nameToken]['content'], $this->magicMethods) === false) {
         return;
     }
     $scopeToken = $phpcsFile->findPrevious(array(T_PUBLIC, T_PROTECTED, T_PRIVATE), $nameToken, $stackPtr);
     if ($scopeToken === false) {
         return;
     }
     if ($tokens[$scopeToken]['type'] != 'T_PUBLIC') {
         $error = "Magic methods must be public (since PHP 5.3) !";
         $phpcsFile->addError($error, $stackPtr);
     }
     $staticToken = $phpcsFile->findPrevious(T_STATIC, $scopeToken, $scopeToken - 2);
     if ($staticToken === false) {
         return;
     } else {
         $error = "Magic methods can not be static (since PHP 5.3) !";
         $phpcsFile->addError($error, $stackPtr);
     }
 }
 /**
  * Processes the tokens that this sniff is interested in.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
  * @param int                  $stackPtr  The position in the stack where
  *                                        the token was found.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $utils = Security_Sniffs_UtilsFactory::getInstance();
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr]['content'] == "'#value'" || $tokens[$stackPtr]['content'] == '"#value"') {
         $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr);
         $next = $phpcsFile->findNext(array_merge(PHP_CodeSniffer_Tokens::$bracketTokens, PHP_CodeSniffer_Tokens::$emptyTokens, PHP_CodeSniffer_Tokens::$assignmentTokens), $stackPtr + 1, $closer + 1, true);
         if ($next == $closer && $tokens[$next]['code'] == T_SEMICOLON) {
             // Case of $label = $element['#value'];
             $next = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $next);
             $next = $phpcsFile->findPrevious(T_VARIABLE, $next);
             $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSWarFormValue');
         } elseif ($next && $utils::is_token_user_input($tokens[$next])) {
             $phpcsFile->addError('XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSErrFormValue');
         } elseif ($next && PHP_CodeSniffer::getConfigData('ParanoiaMode')) {
             if (in_array($tokens[$next]['content'], $utils::getXSSMitigationFunctions())) {
                 $n = $phpcsFile->findNext($utils::getVariableTokens(), $next + 1, $closer);
                 if ($n) {
                     $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$n]['content'], $n, 'D7XSSWarFormValue');
                 }
             } else {
                 $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSWarFormValue');
             }
         }
     }
 }
 /**
  * @inheritdoc
  */
 public function process(\PHP_CodeSniffer_File $phpCsFile, $stackPointer)
 {
     $tokens = $phpCsFile->getTokens();
     $prevIndex = $phpCsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPointer - 1, null, true);
     if (!in_array($tokens[$prevIndex]['code'], [T_TRUE, T_FALSE, T_NULL, T_LNUMBER, T_CONSTANT_ENCAPSED_STRING])) {
         return;
     }
     $leftIndexEnd = $prevIndex;
     $leftIndexStart = $prevIndex;
     $prevIndex = $phpCsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $prevIndex - 1, null, true);
     if (!$prevIndex) {
         return;
     }
     if ($this->isGivenKind(PHP_CodeSniffer_Tokens::$arithmeticTokens, $tokens[$prevIndex])) {
         return;
     }
     if ($this->isGivenKind([T_STRING_CONCAT], $tokens[$prevIndex])) {
         return;
     }
     $fixable = true;
     $error = 'Usage of Yoda conditions is not allowed. Switch the expression order.';
     $prevContent = $tokens[$prevIndex]['content'];
     if (!$this->isGivenKind(PHP_CodeSniffer_Tokens::$assignmentTokens, $tokens[$prevIndex]) && !$this->isGivenKind(PHP_CodeSniffer_Tokens::$booleanOperators, $tokens[$prevIndex]) && $prevContent !== '(') {
         // Not fixable
         $phpCsFile->addError($error, $stackPointer);
         return;
     }
     //TODO
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $token = $tokens[$stackPtr];
     // exclude function definitions, class methods, and namespaced calls
     if ($token['code'] == T_STRING && ($prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true)) && (in_array($tokens[$prev]['code'], array(T_FUNCTION, T_DOUBLE_COLON, T_OBJECT_OPERATOR)) || $tokens[$prev]['code'] == T_NS_SEPARATOR && ($pprev = $phpcsFile->findPrevious(T_WHITESPACE, $prev - 1, null, true)) && $tokens[$pprev]['code'] == T_STRING)) {
         return;
     }
     $exclude = explode(',', $this->exclude);
     $groups = $this->getGroups();
     if (empty($groups)) {
         return;
     }
     foreach ($groups as $groupName => $group) {
         if (in_array($groupName, $exclude)) {
             continue;
         }
         $functions = implode('|', $group['functions']);
         $functions = preg_replace('#[^\\.]\\*#', '.*', $functions);
         // So you can use * instead of .*
         if (preg_match('#\\b(' . $functions . ')\\b#', $token['content']) < 1) {
             continue;
         }
         if ($group['type'] == 'warning') {
             $addWhat = array($phpcsFile, 'addWarning');
         } else {
             $addWhat = array($phpcsFile, 'addError');
         }
         call_user_func($addWhat, $group['message'], $stackPtr, $groupName, array($token['content']));
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = PHP_CodeSniffer_Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     // Get class name
     $className = $tokens[$stackPtr + 2]['content'];
     // Currently only run on migrations
     if (!preg_match("/Migration[^\\s]*/", $className)) {
         return;
     }
     $docTokens = array(T_COMMENT, T_DOC_COMMENT_STAR, T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_TAG, T_DOC_COMMENT_OPEN_TAG, T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STRING);
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if (!in_array($tokens[$commentEnd]['code'], $docTokens)) {
         $phpcsFile->addError('Missing migration class doc comment', $stackPtr, 'Missing');
         return;
     }
     // Get doc block comment
     $commentLocation = $phpcsFile->findPrevious(T_DOC_COMMENT_STRING, $commentEnd);
     $commentString = $tokens[$commentLocation]['content'];
     // Make sure its not default from stub
     if (preg_match("/Migration\\sscript\\sfor\\s\\.\\.\\./", $commentString)) {
         $phpcsFile->addError('Please complete migration doc block comment.', $stackPtr, 'Missing');
         return;
     }
 }
 /**
  * Processes this function call.
  *
  * @param PHP_CodeSniffer_File $phpcsFile
  *   The file being scanned.
  * @param int $stackPtr
  *   The position of the function call in the stack.
  * @param int $openBracket
  *   The position of the opening parenthesis in the stack.
  * @param int $closeBracket
  *   The position of the closing parenthesis in the stack.
  * @param Drupal_Sniffs_Semantics_FunctionCallSniff $sniff
  *   Can be used to retreive the function's arguments with the getArgument()
  *   method.
  *
  * @return void
  */
 public function processFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $closeBracket, Drupal_Sniffs_Semantics_FunctionCallSniff $sniff)
 {
     $tokens = $phpcsFile->getTokens();
     // We assume that the sequence '#default_value' => variable_get(...)
     // indicates a variable that the module owns.
     $arrow = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true);
     if ($arrow === false || $tokens[$arrow]['code'] !== T_DOUBLE_ARROW) {
         return;
     }
     $arrayKey = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrow - 1, null, true);
     if ($arrayKey === false || $tokens[$arrayKey]['code'] !== T_CONSTANT_ENCAPSED_STRING || substr($tokens[$arrayKey]['content'], 1, -1) !== '#default_value') {
         return;
     }
     $argument = $sniff->getArgument(1);
     // Variable name is not a literal string, so we return early.
     if ($argument === false || $tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
         return;
     }
     $moduleName = DrupalPractice_Project::getName($phpcsFile);
     if ($moduleName === false) {
         return;
     }
     $variableName = substr($tokens[$argument['start']]['content'], 1, -1);
     if (strpos($variableName, $moduleName) !== 0) {
         $warning = 'All variables defined by your module must be prefixed with your module\'s name to avoid name collisions with others. Expected start with "%s" but found "%s"';
         $data = array($moduleName, $variableName);
         $phpcsFile->addWarning($warning, $argument['start'], 'VariableName', $data);
     }
 }
 /**
  * Processes normal variables.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  * @param int $stackPtr The position where the token was found.
  *
  * @return void
  */
 protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $variableName = $tokens[$stackPtr]['content'];
     $scopeIdentifier = $phpcsFile->getFilename() . $variableName;
     $level = $tokens[$stackPtr]['level'];
     $functionIndex = $phpcsFile->findPrevious(T_FUNCTION, $stackPtr);
     $lastScopeOpen = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeOpeners, $stackPtr);
     //Inline scope openers do not increment the level value
     $scopeOpenDistance = $tokens[$stackPtr]['line'] - $tokens[$lastScopeOpen]['line'];
     if (in_array($tokens[$lastScopeOpen]['code'], PHP_CodeSniffer_Tokens::$scopeOpeners) === true && ($scopeOpenDistance === 1 || $scopeOpenDistance === 0) && $tokens[$stackPtr]['level'] === $tokens[$lastScopeOpen]['level']) {
         ++$level;
     }
     if ($functionIndex !== false && array_key_exists('scope_closer', $tokens[$functionIndex]) && $tokens[$functionIndex]['scope_closer'] > $stackPtr) {
         //Member variables are always ok
         if ($variableName === '$this') {
             return;
         }
         // find previous non-whitespace token. if it's a double colon, assume static class var
         $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], $stackPtr - 1, null, true);
         if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) {
             return;
         }
         $scopeIdentifier .= $tokens[$functionIndex]['scope_condition'];
     }
     //If this is the first time we've seen this variable in this file/function store the scope depth.
     if (array_key_exists($scopeIdentifier, $this->_variableScopes) === false) {
         $this->_variableScopes[$scopeIdentifier] = $level;
     } elseif ($this->_variableScopes[$scopeIdentifier] > $level) {
         //Verify that the variables we've seen are not appearing in higher scopes.
         $phpcsFile->addWarning("Variable '{$variableName}' is in the wrong scope.", $stackPtr, 'Found');
     }
 }
Example #19
0
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Ignore this.something and other uses of "this" that are not
     // direct assignments.
     $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     if ($tokens[$next]['code'] !== T_SEMICOLON) {
         if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
             return;
         }
     }
     // Something must be assigned to "this".
     $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
     if ($tokens[$prev]['code'] !== T_EQUAL) {
         return;
     }
     // A variable needs to be assigned to "this".
     $prev = $phpcsFile->findPrevious(T_WHITESPACE, $prev - 1, null, true);
     if ($tokens[$prev]['code'] !== T_STRING) {
         return;
     }
     // We can only assign "this" to a var called "self".
     if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') {
         $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"';
         $phpcsFile->addError($error, $prev, 'NotSelf');
     }
 }
 /**
  * Processes the tokens that this sniff is interested in.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
  * @param int                  $stackPtr  The position in the stack where
  *                                        the token was found.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     if ($next === false) {
         return;
     }
     if ($tokens[$next]['code'] !== T_CLOSE_TAG) {
         $found = $tokens[$next]['line'] - $tokens[$stackPtr]['line'] - 1;
         if ($found !== 1) {
             $error = 'Expected one blank line after closing brace of class definition; %s found';
             $data = array($found);
             $phpcsFile->addError($error, $stackPtr, 'SpacingAfterClose', $data);
         }
     }
     // Ignore nested style definitions from here on. The spacing before the closing brace
     // (a single blank line) will be enforced by the above check, which ensures there is a
     // blank line after the last nested class.
     $found = $phpcsFile->findPrevious(T_CLOSE_CURLY_BRACKET, $stackPtr - 1, $tokens[$stackPtr]['bracket_opener']);
     if ($found !== false) {
         return;
     }
     $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true);
     if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line'] - 1) {
         $num = $tokens[$stackPtr]['line'] - $tokens[$prev]['line'] - 1;
         $error = 'Expected 0 blank lines before closing brace of class definition; %s found';
         $data = array($num);
         $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeClose', $data);
     }
 }
 /**
  * Processes the function tokens within the class.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  * @param int                  $stackPtr  The position where the token was found.
  *
  * @return void
  */
 protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Detect multiple properties defined at the same time. Throw an error
     // for this, but also only process the first property in the list so we don't
     // repeat errors.
     $find = PHP_CodeSniffer_Tokens::$scopeModifiers;
     $find = array_merge($find, array(T_VARIABLE, T_VAR, T_SEMICOLON));
     $prev = $phpcsFile->findPrevious($find, $stackPtr - 1);
     if ($tokens[$prev]['code'] === T_VARIABLE) {
         return;
     }
     if ($tokens[$prev]['code'] === T_VAR) {
         $error = 'The var keyword must not be used to declare a property';
         $phpcsFile->addError($error, $stackPtr, 'VarUsed');
     }
     $next = $phpcsFile->findNext(array(T_VARIABLE, T_SEMICOLON), $stackPtr + 1);
     if ($tokens[$next]['code'] === T_VARIABLE) {
         $error = 'There must not be more than one property declared per statement';
         $phpcsFile->addError($error, $stackPtr, 'Multiple');
     }
     $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
     if ($modifier === false || $tokens[$modifier]['line'] !== $tokens[$stackPtr]['line']) {
         $error = 'Visibility must be declared on property "%s"';
         $data = array($tokens[$stackPtr]['content']);
         $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data);
     }
     $propertyName = ltrim($tokens[$stackPtr]['content'], '$');
     if (PHP_CodeSniffer::isCamelCaps($propertyName, false, true, false) === false) {
         $error = 'Property name "%s" is not in camel caps format';
         $errorData = array($tokens[$stackPtr]['content']);
         $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
     }
 }
 /**
  * Processes the function tokens within the class.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  * @param int                  $stackPtr  The position where the token was found.
  *
  * @return void
  */
 protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // if ($tokens[$stackPtr]['content'][1] === '_') {
     // $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility';
     // $data  = array($tokens[$stackPtr]['content']);
     // $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data);
     // }
     // Detect multiple properties defined at the same time. Throw an error
     // for this, but also only process the first property in the list so we don't
     // repeat errors.
     $find = PHP_CodeSniffer_Tokens::$scopeModifiers;
     $find = array_merge($find, array(T_VARIABLE, T_VAR, T_SEMICOLON));
     $prev = $phpcsFile->findPrevious($find, $stackPtr - 1);
     if ($tokens[$prev]['code'] === T_VARIABLE) {
         return;
     }
     if ($tokens[$prev]['code'] === T_VAR) {
         $error = 'The var keyword must not be used to declare a property';
         $phpcsFile->addError($error, $stackPtr, 'VarUsed');
     }
     $next = $phpcsFile->findNext(array(T_VARIABLE, T_SEMICOLON), $stackPtr + 1);
     if ($tokens[$next]['code'] === T_VARIABLE) {
         $error = 'There must not be more than one property declared per statement';
         $phpcsFile->addError($error, $stackPtr, 'Multiple');
     }
     $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
     if ($modifier === false || $tokens[$modifier]['line'] !== $tokens[$stackPtr]['line']) {
         $error = 'Visibility must be declared on property "%s"';
         $data = array($tokens[$stackPtr]['content']);
         $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data);
     }
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
  * @param int                  $stackPtr  The position of the current token in
  *                                        the stack passed in $tokens.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $current = $stackPtr;
     $openingBrace = $phpcsFile->findNext([T_OPEN_CURLY_BRACKET], $current, null);
     $firstMethodComment = $phpcsFile->findNext([T_DOC_COMMENT_OPEN_TAG], $openingBrace);
     if ($tokens[$openingBrace]['line'] > $tokens[$firstMethodComment]['line']) {
         return;
     }
     $elementToCheck = $firstMethodComment;
     $trait = $phpcsFile->findPrevious(T_USE, $firstMethodComment);
     if (true === is_int($trait)) {
         $elementToCheck = $trait;
     }
     $constant = $phpcsFile->findNext([T_CONST], $openingBrace);
     $use = $phpcsFile->findNext([T_USE], $openingBrace, $firstMethodComment);
     if (false !== $constant && $constant > $openingBrace && $constant < $firstMethodComment) {
         $elementBeforeConstant = $phpcsFile->findPrevious([T_WHITESPACE], $openingBrace, $constant, true);
         if (false != $use && $tokens[$openingBrace]['line'] + 1 !== $tokens[$use]['line']) {
             $phpcsFile->addError('Remove blank line before use Statement', $use);
         }
         if (false === $use && false === $elementBeforeConstant && $tokens[$openingBrace]['line'] + 1 != $tokens[$constant]['line']) {
             $phpcsFile->addError('Remove blank line before const Statement', $constant);
         }
         if ($use != false && $tokens[$phpcsFile->findPrevious([T_USE], $constant, $openingBrace)]['line'] + 2 !== $tokens[$constant]['line']) {
             $phpcsFile->addError('Only one blank line before constant statement is allowed', $constant);
         }
         return;
     }
     if (1 < $tokens[$elementToCheck]['line'] - $tokens[$openingBrace]['line']) {
         $phpcsFile->addError('Remove blank line before.', $elementToCheck);
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     if ($tokens[$stackPtr]['code'] === T_CASE && isset($tokens[$stackPtr]['scope_closer'])) {
         //			$internalCase = $phpcsFile->findNext(T_CASE, $stackPtr + 1, $tokens[$stackPtr]['scope_closer']);
         //			if ($internalCase !== false) {
         //				$comment = $phpcsFile->findNext(T_COMMENT, $stackPtr + 1, $internalCase - 1);
         //				if ($comment === false) {
         //					$phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.5.12') . '"case" has not break and has not any comment', $stackPtr);
         //				}
         //			}
         $switch = $phpcsFile->findPrevious(T_SWITCH, $stackPtr - 1);
         if ($switch !== false) {
             $nextCase = $phpcsFile->findNext(array(T_CASE, T_DEFAULT), $stackPtr + 1, $tokens[$switch]['scope_closer']);
             if ($nextCase !== false) {
                 $prevBreak = $phpcsFile->findPrevious(T_BREAK, $nextCase - 1, $stackPtr);
                 if ($prevBreak !== false) {
                     $breakWS = $phpcsFile->findNext(T_WHITESPACE, $prevBreak + 1, $nextCase - 1);
                     if ($breakWS !== false) {
                         $str = $phpcsFile->getTokensAsString($breakWS, $nextCase - $breakWS - 1);
                         if (!preg_match("/^\n\n[ ]*\$/Ss", $str)) {
                             $breakWS = false;
                         }
                     }
                     if ($breakWS === false) {
                         $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.5.14') . '"case" must has empty line between current "case" and previous "break"', $stackPtr);
                     }
                 }
             }
         }
     } elseif ($tokens[$stackPtr]['code'] === T_DEFAULT) {
     }
 }
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * Operations to check for:
  * $i = 1 + 1;
  * $i = $i + 1;
  * $i = (1 + 1) - 1;
  *
  * Operations to ignore:
  * array($i => -1);
  * $i = -1;
  * range(-10, -1);
  *
  * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  * @param int                  $stackPtr  The position of the current token in
  *                                        the stack passed in $tokens.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $has_equality_token = in_array($tokens[$stackPtr - 2]['code'], PHP_CodeSniffer_Tokens::$equalityTokens);
     // Ensure this is a construct to check.
     $lastSyntaxItem = $phpcsFile->findPrevious(array(T_WHITESPACE), $stackPtr - 1, $tokens[$stackPtr]['column'] * -1, true, NULL, true);
     $needs_operator_suffix = in_array($tokens[$lastSyntaxItem]['code'], array(T_LNUMBER, T_DNUMBER, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET, T_VARIABLE, T_STRING, T_CONSTANT_ENCAPSED_STRING));
     $needs_operator_prefix = !in_array($tokens[$lastSyntaxItem]['code'], array(T_OPEN_PARENTHESIS, T_EQUAL));
     if ($needs_operator_suffix && ($tokens[$stackPtr - 2]['code'] !== T_EQUAL && $tokens[$stackPtr - 2]['code'] !== T_DOUBLE_ARROW && !$has_equality_token && !($tokens[$stackPtr]['code'] === T_EQUAL && $tokens[$stackPtr + 1]['code'] === T_BITWISE_AND) && ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE || $tokens[$stackPtr + 1]['content'] != ' '))) {
         $error = 'An operator statement must be followed by a single space';
         $phpcsFile->addError($error, $stackPtr);
     }
     if ($needs_operator_prefix) {
         $error = false;
         if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) {
             $error = true;
         } else {
             if ($tokens[$stackPtr - 1]['content'] !== ' ' && $tokens[$stackPtr]['code'] !== T_EQUAL) {
                 $nonWhiteSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true);
                 // Make sure that the previous operand is on the same line before
                 // throwing an error.
                 if ($tokens[$nonWhiteSpace]['line'] === $tokens[$stackPtr]['line']) {
                     $error = true;
                 }
             }
         }
         if ($error === true) {
             $error = 'There must be a single space before an operator statement';
             $phpcsFile->addError($error, $stackPtr);
         }
     }
     //end if
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // We are only interested in function/class/interface doc block comments.
     $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true);
     $ignore = array(T_CLASS, T_INTERFACE, T_FUNCTION, T_PUBLIC, T_PRIVATE, T_PROTECTED, T_STATIC, T_ABSTRACT);
     if (in_array($tokens[$nextToken]['code'], $ignore) === false) {
         // Could be a file comment.
         $prevToken = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true);
         if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) {
             return;
         }
     }
     // We only want to get the first comment in a block. If there is
     // a comment on the line before this one, return.
     $docComment = $phpcsFile->findPrevious(T_DOC_COMMENT, $stackPtr - 1);
     if ($docComment !== false) {
         if ($tokens[$docComment]['line'] === $tokens[$stackPtr]['line'] - 1) {
             return;
         }
     }
     $comments = array($stackPtr);
     $currentComment = $stackPtr;
     $lastComment = $stackPtr;
     while (($currentComment = $phpcsFile->findNext(T_DOC_COMMENT, $currentComment + 1)) !== false) {
         if ($tokens[$lastComment]['line'] === $tokens[$currentComment]['line'] - 1) {
             $comments[] = $currentComment;
             $lastComment = $currentComment;
         } else {
             break;
         }
     }
     // The $comments array now contains pointers to each token in the
     // comment block.
     $requiredColumn = strpos($tokens[$stackPtr]['content'], '*');
     $requiredColumn += $tokens[$stackPtr]['column'];
     foreach ($comments as $commentPointer) {
         // Check the spacing after each asterisk.
         $content = $tokens[$commentPointer]['content'];
         $firstChar = substr($content, 0, 1);
         $lastChar = substr($content, -1);
         if ($firstChar === '/' || $lastChar !== '/') {
             continue;
         }
         $count = substr_count($content, '*');
         if ($count < 2) {
             continue;
         }
         $error = 'Expected 1 asterisk on closing line; %s found';
         $data = array($count);
         $fix = $phpcsFile->addFixableError($error, $commentPointer, 'SpaceBeforeTag', $data);
         if ($fix === true && $phpcsFile->fixer->enabled === true) {
             $pos = strpos($content, '*');
             $content = substr($content, 0, $pos + 1) . substr($content, $pos + $count);
             $phpcsFile->fixer->replaceToken($commentPointer, $content);
         }
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = PHP_CodeSniffer_Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         // Inline comments might just be closing comments for
         // control structures or functions instead of function comments
         // using the wrong comment type. If there is other code on the line,
         // assume they relate to that code.
         $prev = $phpcsFile->findPrevious($find, $commentEnd - 1, null, true);
         if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
             $commentEnd = $prev;
         }
     }
     if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) {
         $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
         $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no');
         return;
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes');
     }
     if ($tokens[$commentEnd]['code'] === T_COMMENT) {
         $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle');
         return;
     }
     if ($tokens[$commentEnd]['line'] !== $tokens[$stackPtr]['line'] - 1) {
         $error = 'There must be no blank lines after the function comment';
         $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
     }
     $commentStart = $tokens[$commentEnd]['comment_opener'];
     foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
         if ($tokens[$tag]['content'] === '@see') {
             // Make sure the tag isn't empty.
             $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
             if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
                 $error = 'Content missing for @see tag in function comment';
                 $phpcsFile->addError($error, $tag, 'EmptySees');
             }
         }
         // Ongr checks inheritdoc comment.
         if ($tokens[$tag]['content'] === '@inheritdoc') {
             $error = 'You must use {@inheritdoc}';
             $fix = $phpcsFile->addFixableError($error, $tag, 'WrongInheritDocStyle');
             if ($fix === true) {
                 $phpcsFile->fixer->replaceToken($tag, '{@inheritdoc}');
             }
             return;
         }
     }
     $this->processReturn($phpcsFile, $stackPtr, $commentStart);
     $this->processThrows($phpcsFile, $stackPtr, $commentStart);
     $this->processDeprecated($phpcsFile, $stackPtr, $commentStart);
     $this->processParams($phpcsFile, $stackPtr, $commentStart);
     $this->processComments($phpcsFile, $stackPtr, $commentStart);
 }
 /**
  * Processes this sniff, 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // We are only interested in Action classes.
     $classNameToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
     $className = $tokens[$classNameToken]['content'];
     if (substr($className, -7) !== 'Actions') {
         return;
     }
     $foundFunctions = array();
     $foundCalls = array();
     // Find all static method calls in the form self::method() in the class.
     $classEnd = $tokens[$stackPtr]['scope_closer'];
     for ($i = $classNameToken + 1; $i < $classEnd; $i++) {
         if ($tokens[$i]['code'] !== T_DOUBLE_COLON) {
             if ($tokens[$i]['code'] === T_FUNCTION) {
                 // Cache the function information.
                 $funcName = $phpcsFile->findNext(T_STRING, $i + 1);
                 $funcScope = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $i - 1);
                 $foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']);
             }
             continue;
         }
         $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $i - 1, null, true);
         if ($tokens[$prevToken]['content'] !== 'self') {
             continue;
         }
         $funcNameToken = $phpcsFile->findNext(T_WHITESPACE, $i + 1, null, true);
         if ($tokens[$funcNameToken]['code'] === T_VARIABLE) {
             // We are only interested in function calls.
             continue;
         }
         $funcName = $tokens[$funcNameToken]['content'];
         // We've found the function, now we need to find it and see if it is
         // public, private or protected. If it starts with an underscore we
         // can assume it is private.
         if ($funcName[0] === '_') {
             continue;
         }
         $foundCalls[$i] = $funcName;
     }
     //end for
     $errorClassName = substr($className, 0, -7);
     foreach ($foundCalls as $token => $funcName) {
         if (isset($foundFunctions[$funcName]) === false) {
             // Function was not in this class, might have come from the parent.
             // Either way, we can't really check this.
             continue;
         } else {
             if ($foundFunctions[$funcName] === 'public') {
                 $error = "Static calls to public methods in Action classes must not use the self keyword; use {$errorClassName}::{$funcName}() instead";
                 $phpcsFile->addError($error, $token);
             }
         }
     }
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     $find = PHP_CodeSniffer_Tokens::$methodPrefixes;
     $find[] = T_WHITESPACE;
     $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true);
     // If the token that we found was a class or a function, then this
     // function has no doc comment.
     $code = $tokens[$commentEnd]['code'];
     // REPLACED
     $this->_methodName = $phpcsFile->getDeclarationName($stackPtr);
     if ($code === T_COMMENT) {
         // Inline comments might just be closing comments for
         // control structures or functions instead of function comments
         // using the wrong comment type. If there is other code on the line,
         // assume they relate to that code.
         $prev = $phpcsFile->findPrevious($find, $commentEnd - 1, null, true);
         if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
             $commentEnd = $prev;
         }
     }
     if ($code !== T_DOC_COMMENT_CLOSE_TAG && $code !== T_COMMENT) {
         // EDITED: Constructor must not have comment
         if ($this->_methodName !== '__construct' && $this->_methodName !== '__destruct' && substr($this->_methodName, 0, 6) !== 'inject') {
             $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
             $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no');
         }
         return;
     } else {
         $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes');
     }
     if ($code === T_COMMENT) {
         if ($this->_methodName !== '__construct' && $this->_methodName !== '__destruct' && substr($this->_methodName, 0, 6) !== 'inject') {
             $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle');
         }
         return;
     }
     if ($tokens[$commentEnd]['line'] !== $tokens[$stackPtr]['line'] - 1) {
         $error = 'There must be no blank lines after the function comment';
         $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
     }
     $commentStart = $tokens[$commentEnd]['comment_opener'];
     foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
         if ($tokens[$tag]['content'] === '@see') {
             // Make sure the tag isn't empty.
             $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
             if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
                 $error = 'Content missing for @see tag in function comment';
                 $phpcsFile->addError($error, $tag, 'EmptySees');
             }
         }
     }
     $this->processReturn($phpcsFile, $stackPtr, $commentStart);
     $this->processThrows($phpcsFile, $stackPtr, $commentStart);
     $this->processParams($phpcsFile, $stackPtr, $commentStart);
 }
 /**
  * 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.
  *
  * @return void
  */
 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 {
     $tokens = $phpcsFile->getTokens();
     // Skip tokens that are the names of functions or classes
     // within their definitions. For example: function myFunction...
     // "myFunction" is T_STRING but we should skip because it is not a
     // function or method *call*.
     $functionName = $stackPtr;
     $findTokens = array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, array(T_BITWISE_AND));
     $functionKeyword = $phpcsFile->findPrevious($findTokens, $stackPtr - 1, null, true);
     if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) {
         return;
     }
     // If the next non-whitespace token after the function or method call
     // is not an opening parenthesis then it cant really be a *call*.
     $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $functionName + 1, null, true);
     if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
         return;
     }
     $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
     $nextSeparator = $openBracket;
     while (($nextSeparator = $phpcsFile->findNext(T_VARIABLE, $nextSeparator + 1, $closeBracket)) !== false) {
         // Make sure the variable belongs directly to this function call
         // and is not inside a nested function call or array.
         $brackets = $tokens[$nextSeparator]['nested_parenthesis'];
         $lastBracket = array_pop($brackets);
         if ($lastBracket !== $closeBracket) {
             continue;
         }
         // Checking this: $value = my_function(...[*]$arg...).
         $tokenBefore = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $nextSeparator - 1, null, true);
         if ($tokens[$tokenBefore]['code'] === T_BITWISE_AND) {
             // Checking this: $value = my_function(...[*]&$arg...).
             $tokenBefore = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $tokenBefore - 1, null, true);
             // We have to exclude all uses of T_BITWISE_AND that are not
             // references. We use a blacklist approach as we prefer false
             // positives to not identifying a pass-by-reference call at all.
             // The blacklist may not yet be complete.
             switch ($tokens[$tokenBefore]['code']) {
                 case T_VARIABLE:
                 case T_CLOSE_PARENTHESIS:
                 case T_LNUMBER:
                     // In these cases T_BITWISE_AND represents
                     // the bitwise and operator.
                     continue;
                 default:
                     // T_BITWISE_AND represents a pass-by-reference.
                     $error = 'Call-time pass-by-reference calls are prohibited';
                     $phpcsFile->addError($error, $tokenBefore, 'NotAllowed');
                     break;
             }
         }
         //end if
     }
     //end while
 }