Skip to content

Commit

Permalink
Merge pull request #16 from php-fig-rectified/master-fqcn
Browse files Browse the repository at this point in the history
FQCN improvements.
  • Loading branch information
dereuromark authored May 16, 2019
2 parents 4b4ed2f + 0c679b5 commit 3dcb12c
Showing 1 changed file with 218 additions and 1 deletion.
219 changes: 218 additions & 1 deletion PSR2R/Sniffs/Namespaces/NoInlineFullyQualifiedClassNameSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,19 @@ public function process(File $phpcsFile, $stackPtr) {
$this->loadStatements($phpcsFile);
$this->findSentinel($phpcsFile);

if ($tokens[$stackPtr]['code'] === T_CLASS) {
if ($tokens[$stackPtr]['code'] === T_CLASS || $tokens[$stackPtr]['code'] === T_INTERFACE || $tokens[$stackPtr]['code'] === T_TRAIT) {
$this->checkUseForClass($phpcsFile, $stackPtr);
} elseif ($tokens[$stackPtr]['code'] === T_NEW) {
$this->checkUseForNew($phpcsFile, $stackPtr);
} elseif ($tokens[$stackPtr]['code'] === T_DOUBLE_COLON) {
$this->checkUseForStatic($phpcsFile, $stackPtr);
} elseif ($tokens[$stackPtr]['code'] === T_INSTANCEOF) {
$this->checkUseForInstanceOf($phpcsFile, $stackPtr);
} elseif ($tokens[$stackPtr]['code'] === T_CATCH || $tokens[$stackPtr]['code'] === T_CALLABLE) {
$this->checkUseForCatchOrCallable($phpcsFile, $stackPtr);
} else {
$this->checkUseForSignature($phpcsFile, $stackPtr);
$this->checkUseForReturnTypeHint($phpcsFile, $stackPtr);
}
$this->insertUseWhenSentinel($phpcsFile, $stackPtr);
}
Expand Down Expand Up @@ -575,6 +580,218 @@ protected function checkUseForStatic(File $phpcsFile, $stackPtr) {
$phpcsFile->fixer->endChangeset();
}

/**
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $stackPtr
*
* @return void
*/
protected function checkUseForInstanceOf(File $phpcsFile, $stackPtr) {
$tokens = $phpcsFile->getTokens();

$classNameIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true);

$lastIndex = null;
$i = $classNameIndex;
$extractedUseStatement = '';
$lastSeparatorIndex = null;
while (true) {
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING], $tokens[$i])) {
break;
}
$lastIndex = $i;
$extractedUseStatement .= $tokens[$i]['content'];

if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$i])) {
$lastSeparatorIndex = $i;
}
++$i;
}

if ($lastIndex === null || $lastSeparatorIndex === null) {
return;
}

$extractedUseStatement = ltrim($extractedUseStatement, '\\');

$className = '';
for ($i = $lastSeparatorIndex + 1; $i <= $lastIndex; ++$i) {
$className .= $tokens[$i]['content'];
}

$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'InstanceOf');
if (!$fix) {
return;
}

$phpcsFile->fixer->beginChangeset();

$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);
$firstSeparatorIndex = $classNameIndex;

for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
$phpcsFile->fixer->replaceToken($k, '');
}
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');

if ($addedUseStatement['alias'] !== null) {
$phpcsFile->fixer->replaceToken($lastIndex, $addedUseStatement['alias']);
for ($k = $lastSeparatorIndex + 1; $k < $lastIndex; ++$k) {
$phpcsFile->fixer->replaceToken($k, '');
}
}

$phpcsFile->fixer->endChangeset();
}

/**
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $stackPtr
*
* @return void
*/
public function checkUseForCatchOrCallable(File $phpcsFile, $stackPtr) {
$tokens = $phpcsFile->getTokens();

$openParenthesisIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1);
$closeParenthesisIndex = $tokens[$openParenthesisIndex]['parenthesis_closer'];
$classNameIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $openParenthesisIndex + 1, null, true);

$lastIndex = null;
$i = $classNameIndex;
$extractedUseStatement = '';
$lastSeparatorIndex = null;
while ($i < $closeParenthesisIndex) {
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING], $tokens[$i])) {
break;
}
$lastIndex = $i;
$extractedUseStatement .= $tokens[$i]['content'];

if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$i])) {
$lastSeparatorIndex = $i;
}
++$i;
}

if ($lastIndex === null || $lastSeparatorIndex === null) {
return;
}

$extractedUseStatement = ltrim($extractedUseStatement, '\\');

$className = '';
for ($k = $lastSeparatorIndex + 1; $k <= $lastIndex; ++$k) {
$className .= $tokens[$k]['content'];
}

$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'Catch');
if (!$fix) {
return;
}

$startIndex = $openParenthesisIndex;

$phpcsFile->fixer->beginChangeset();

$firstSeparatorIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex + 1, null, true);

$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);

for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
$phpcsFile->fixer->replaceToken($k, '');
}
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');

if ($addedUseStatement['alias'] !== null) {
$phpcsFile->fixer->replaceToken($firstSeparatorIndex + 1, $addedUseStatement['alias']);
for ($i = $firstSeparatorIndex + 2; $i <= $lastIndex; ++$i) {
$phpcsFile->fixer->replaceToken($i, '');
}
}

$phpcsFile->fixer->endChangeset();
}

/**
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $stackPtr
*
* @return void
*/
protected function checkUseForReturnTypeHint(File $phpcsFile, $stackPtr) {
$tokens = $phpcsFile->getTokens();

$openParenthesisIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1);
$closeParenthesisIndex = $tokens[$openParenthesisIndex]['parenthesis_closer'];

$colonIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $closeParenthesisIndex + 1, null, true);
if (!$colonIndex) {
return;
}

$startIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $colonIndex + 1, $colonIndex + 3, true);
if (!$startIndex) {
return;
}

if ($tokens[$startIndex]['type'] === 'T_NULLABLE') {
$startIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex + 1, $startIndex + 3, true);
}

$lastIndex = null;
$j = $startIndex;
$extractedUseStatement = '';
$lastSeparatorIndex = null;
while (true) {
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING, T_RETURN_TYPE], $tokens[$j])) {
break;
}

$lastIndex = $j;
$extractedUseStatement .= $tokens[$j]['content'];
if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$j])) {
$lastSeparatorIndex = $j;
}
++$j;
}

if ($lastIndex === null || $lastSeparatorIndex === null) {
return;
}

$extractedUseStatement = ltrim($extractedUseStatement, '\\');
$className = '';
for ($k = $lastSeparatorIndex + 1; $k <= $lastIndex; ++$k) {
$className .= $tokens[$k]['content'];
}

$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
$fix = $phpcsFile->addFixableError($error, $colonIndex, 'ReturnSignature');
if (!$fix) {
return;
}

$phpcsFile->fixer->beginChangeset();

$firstSeparatorIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex, null, true);

$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);

for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
$phpcsFile->fixer->replaceToken($k, '');
}
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');

if ($addedUseStatement['alias'] !== null) {
$phpcsFile->fixer->replaceToken($lastIndex, $addedUseStatement['alias']);
}

$phpcsFile->fixer->endChangeset();
}

/**
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $stackPtr
Expand Down

0 comments on commit 3dcb12c

Please sign in to comment.