Source for file UseDeclarationSniff.php
Documentation is available at UseDeclarationSniff.php
* Ensures USE blocks are declared correctly.
* @author Greg Sherwood <gsherwood@squiz.net>
* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
class UseDeclarationSniff implements Sniff
* Returns an array of tokens this test wants to listen for.
public function register ()
* Processes this test, when one of its tokens is encountered.
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token in
* the stack passed in $tokens.
public function process (File $phpcsFile, $stackPtr)
if ($this->shouldIgnoreUse ($phpcsFile, $stackPtr) === true ) {
$tokens = $phpcsFile->getTokens ();
// One space after the use keyword.
if ($tokens[($stackPtr + 1 )]['content'] !== ' ') {
$error = 'There must be a single space after the USE keyword';
$fix = $phpcsFile->addFixableError ($error, $stackPtr, 'SpaceAfterUse');
$phpcsFile->fixer ->replaceToken (($stackPtr + 1 ), ' ');
// Only one USE declaration allowed per statement.
&& $tokens[$next]['code'] !== T_CLOSE_TAG
$error = 'There must be one USE keyword per declaration';
$fix = $phpcsFile->addFixableError ($error, $stackPtr, 'MultipleDeclarations');
if ($tokens[$next]['code'] === T_COMMA) {
$phpcsFile->fixer ->replaceToken ($next, ';'. $phpcsFile->eolChar. 'use ');
$baseUse = rtrim($phpcsFile->getTokensAsString ($stackPtr, ($next - $stackPtr)));
$phpcsFile->fixer ->beginChangeset ();
// Remove base use statement.
for ($i = $stackPtr; $i <= $next; $i++ ) {
$phpcsFile->fixer ->replaceToken ($i, '');
// Convert grouped use statements into full use statements.
$next = $phpcsFile->findNext (Tokens ::$emptyTokens, ($next + 1 ), $closingCurly, true );
$whitespace = $phpcsFile->findPrevious (T_WHITESPACE , ($next - 1 ), null , true );
for ($i = ($whitespace + 1 ); $i < $next; $i++ ) {
$phpcsFile->fixer ->replaceToken ($i, '');
if ($tokens[$next]['code'] === T_CONST || $tokens[$next]['code'] === T_FUNCTION ) {
$phpcsFile->fixer ->addContentBefore ($next, 'use ');
$next = $phpcsFile->findNext (Tokens ::$emptyTokens, ($next + 1 ), $closingCurly, true );
$phpcsFile->fixer ->addContentBefore ($next, str_replace('use ', '', $baseUse));
$phpcsFile->fixer ->addContentBefore ($next, $baseUse);
$next = $phpcsFile->findNext (T_COMMA, ($next + 1 ), $closingCurly);
$phpcsFile->fixer ->replaceToken ($next, ';'. $phpcsFile->eolChar );
} while ($next !== false );
$phpcsFile->fixer ->replaceToken ($closingCurly, '');
// Remove any trailing whitespace.
$next = $phpcsFile->findNext (T_SEMICOLON, $closingCurly);
$whitespace = $phpcsFile->findPrevious (T_WHITESPACE , ($closingCurly - 1 ), null , true );
for ($i = ($whitespace + 1 ); $i < $next; $i++ ) {
$phpcsFile->fixer ->replaceToken ($i, '');
$phpcsFile->fixer ->endChangeset ();
// Make sure this USE comes after the first namespace declaration.
$prev = $phpcsFile->findPrevious (T_NAMESPACE , ($stackPtr - 1 ));
$first = $phpcsFile->findNext (T_NAMESPACE , 1 );
$error = 'USE declarations must go after the first namespace declaration';
$phpcsFile->addError ($error, $stackPtr, 'UseAfterNamespace');
// Only interested in the last USE statement from here onwards.
$nextUse = $phpcsFile->findNext (T_USE , ($stackPtr + 1 ));
while ($this->shouldIgnoreUse ($phpcsFile, $nextUse) === true ) {
$nextUse = $phpcsFile->findNext (T_USE , ($nextUse + 1 ));
if ($nextUse === false ) {
if ($nextUse !== false ) {
$end = $phpcsFile->findNext (T_SEMICOLON, ($stackPtr + 1 ));
$next = $phpcsFile->findNext (T_WHITESPACE , ($end + 1 ), null , true );
if ($next === false || $tokens[$next]['code'] === T_CLOSE_TAG ) {
$diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1 );
$error = 'There must be one blank line after the last USE statement; %s found;';
$fix = $phpcsFile->addFixableError ($error, $stackPtr, 'SpaceAfterLastUse', $data);
$phpcsFile->fixer ->addNewline ($end);
$phpcsFile->fixer ->beginChangeset ();
for ($i = ($end + 1 ); $i < $next; $i++ ) {
if ($tokens[$i]['line'] === $tokens[$next]['line']) {
$phpcsFile->fixer ->replaceToken ($i, '');
$phpcsFile->fixer ->addNewline ($end);
$phpcsFile->fixer ->endChangeset ();
* Check if this use statement is part of the namespace block.
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token in
* the stack passed in $tokens.
private function shouldIgnoreUse ($phpcsFile, $stackPtr)
$tokens = $phpcsFile->getTokens ();
// Ignore USE keywords inside closures.
$next = $phpcsFile->findNext (T_WHITESPACE , ($stackPtr + 1 ), null , true );
// Ignore USE keywords for traits.
if ($phpcsFile->hasCondition ($stackPtr, array (T_CLASS , T_TRAIT )) === true ) {
Documentation generated on Mon, 11 Mar 2019 15:27:50 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|