Skip to content

Commit 0c679b5

Browse files
committed
FQCN improvements.
1 parent 4b4ed2f commit 0c679b5

File tree

1 file changed

+218
-1
lines changed

1 file changed

+218
-1
lines changed

PSR2R/Sniffs/Namespaces/NoInlineFullyQualifiedClassNameSniff.php

Lines changed: 218 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,19 @@ public function process(File $phpcsFile, $stackPtr) {
6262
$this->loadStatements($phpcsFile);
6363
$this->findSentinel($phpcsFile);
6464

65-
if ($tokens[$stackPtr]['code'] === T_CLASS) {
65+
if ($tokens[$stackPtr]['code'] === T_CLASS || $tokens[$stackPtr]['code'] === T_INTERFACE || $tokens[$stackPtr]['code'] === T_TRAIT) {
6666
$this->checkUseForClass($phpcsFile, $stackPtr);
6767
} elseif ($tokens[$stackPtr]['code'] === T_NEW) {
6868
$this->checkUseForNew($phpcsFile, $stackPtr);
6969
} elseif ($tokens[$stackPtr]['code'] === T_DOUBLE_COLON) {
7070
$this->checkUseForStatic($phpcsFile, $stackPtr);
71+
} elseif ($tokens[$stackPtr]['code'] === T_INSTANCEOF) {
72+
$this->checkUseForInstanceOf($phpcsFile, $stackPtr);
73+
} elseif ($tokens[$stackPtr]['code'] === T_CATCH || $tokens[$stackPtr]['code'] === T_CALLABLE) {
74+
$this->checkUseForCatchOrCallable($phpcsFile, $stackPtr);
7175
} else {
7276
$this->checkUseForSignature($phpcsFile, $stackPtr);
77+
$this->checkUseForReturnTypeHint($phpcsFile, $stackPtr);
7378
}
7479
$this->insertUseWhenSentinel($phpcsFile, $stackPtr);
7580
}
@@ -575,6 +580,218 @@ protected function checkUseForStatic(File $phpcsFile, $stackPtr) {
575580
$phpcsFile->fixer->endChangeset();
576581
}
577582

583+
/**
584+
* @param \PHP_CodeSniffer\Files\File $phpcsFile
585+
* @param int $stackPtr
586+
*
587+
* @return void
588+
*/
589+
protected function checkUseForInstanceOf(File $phpcsFile, $stackPtr) {
590+
$tokens = $phpcsFile->getTokens();
591+
592+
$classNameIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true);
593+
594+
$lastIndex = null;
595+
$i = $classNameIndex;
596+
$extractedUseStatement = '';
597+
$lastSeparatorIndex = null;
598+
while (true) {
599+
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING], $tokens[$i])) {
600+
break;
601+
}
602+
$lastIndex = $i;
603+
$extractedUseStatement .= $tokens[$i]['content'];
604+
605+
if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$i])) {
606+
$lastSeparatorIndex = $i;
607+
}
608+
++$i;
609+
}
610+
611+
if ($lastIndex === null || $lastSeparatorIndex === null) {
612+
return;
613+
}
614+
615+
$extractedUseStatement = ltrim($extractedUseStatement, '\\');
616+
617+
$className = '';
618+
for ($i = $lastSeparatorIndex + 1; $i <= $lastIndex; ++$i) {
619+
$className .= $tokens[$i]['content'];
620+
}
621+
622+
$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
623+
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'InstanceOf');
624+
if (!$fix) {
625+
return;
626+
}
627+
628+
$phpcsFile->fixer->beginChangeset();
629+
630+
$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);
631+
$firstSeparatorIndex = $classNameIndex;
632+
633+
for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
634+
$phpcsFile->fixer->replaceToken($k, '');
635+
}
636+
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');
637+
638+
if ($addedUseStatement['alias'] !== null) {
639+
$phpcsFile->fixer->replaceToken($lastIndex, $addedUseStatement['alias']);
640+
for ($k = $lastSeparatorIndex + 1; $k < $lastIndex; ++$k) {
641+
$phpcsFile->fixer->replaceToken($k, '');
642+
}
643+
}
644+
645+
$phpcsFile->fixer->endChangeset();
646+
}
647+
648+
/**
649+
* @param \PHP_CodeSniffer\Files\File $phpcsFile
650+
* @param int $stackPtr
651+
*
652+
* @return void
653+
*/
654+
public function checkUseForCatchOrCallable(File $phpcsFile, $stackPtr) {
655+
$tokens = $phpcsFile->getTokens();
656+
657+
$openParenthesisIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1);
658+
$closeParenthesisIndex = $tokens[$openParenthesisIndex]['parenthesis_closer'];
659+
$classNameIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $openParenthesisIndex + 1, null, true);
660+
661+
$lastIndex = null;
662+
$i = $classNameIndex;
663+
$extractedUseStatement = '';
664+
$lastSeparatorIndex = null;
665+
while ($i < $closeParenthesisIndex) {
666+
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING], $tokens[$i])) {
667+
break;
668+
}
669+
$lastIndex = $i;
670+
$extractedUseStatement .= $tokens[$i]['content'];
671+
672+
if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$i])) {
673+
$lastSeparatorIndex = $i;
674+
}
675+
++$i;
676+
}
677+
678+
if ($lastIndex === null || $lastSeparatorIndex === null) {
679+
return;
680+
}
681+
682+
$extractedUseStatement = ltrim($extractedUseStatement, '\\');
683+
684+
$className = '';
685+
for ($k = $lastSeparatorIndex + 1; $k <= $lastIndex; ++$k) {
686+
$className .= $tokens[$k]['content'];
687+
}
688+
689+
$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
690+
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'Catch');
691+
if (!$fix) {
692+
return;
693+
}
694+
695+
$startIndex = $openParenthesisIndex;
696+
697+
$phpcsFile->fixer->beginChangeset();
698+
699+
$firstSeparatorIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex + 1, null, true);
700+
701+
$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);
702+
703+
for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
704+
$phpcsFile->fixer->replaceToken($k, '');
705+
}
706+
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');
707+
708+
if ($addedUseStatement['alias'] !== null) {
709+
$phpcsFile->fixer->replaceToken($firstSeparatorIndex + 1, $addedUseStatement['alias']);
710+
for ($i = $firstSeparatorIndex + 2; $i <= $lastIndex; ++$i) {
711+
$phpcsFile->fixer->replaceToken($i, '');
712+
}
713+
}
714+
715+
$phpcsFile->fixer->endChangeset();
716+
}
717+
718+
/**
719+
* @param \PHP_CodeSniffer\Files\File $phpcsFile
720+
* @param int $stackPtr
721+
*
722+
* @return void
723+
*/
724+
protected function checkUseForReturnTypeHint(File $phpcsFile, $stackPtr) {
725+
$tokens = $phpcsFile->getTokens();
726+
727+
$openParenthesisIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1);
728+
$closeParenthesisIndex = $tokens[$openParenthesisIndex]['parenthesis_closer'];
729+
730+
$colonIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $closeParenthesisIndex + 1, null, true);
731+
if (!$colonIndex) {
732+
return;
733+
}
734+
735+
$startIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $colonIndex + 1, $colonIndex + 3, true);
736+
if (!$startIndex) {
737+
return;
738+
}
739+
740+
if ($tokens[$startIndex]['type'] === 'T_NULLABLE') {
741+
$startIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex + 1, $startIndex + 3, true);
742+
}
743+
744+
$lastIndex = null;
745+
$j = $startIndex;
746+
$extractedUseStatement = '';
747+
$lastSeparatorIndex = null;
748+
while (true) {
749+
if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING, T_RETURN_TYPE], $tokens[$j])) {
750+
break;
751+
}
752+
753+
$lastIndex = $j;
754+
$extractedUseStatement .= $tokens[$j]['content'];
755+
if ($this->isGivenKind([T_NS_SEPARATOR], $tokens[$j])) {
756+
$lastSeparatorIndex = $j;
757+
}
758+
++$j;
759+
}
760+
761+
if ($lastIndex === null || $lastSeparatorIndex === null) {
762+
return;
763+
}
764+
765+
$extractedUseStatement = ltrim($extractedUseStatement, '\\');
766+
$className = '';
767+
for ($k = $lastSeparatorIndex + 1; $k <= $lastIndex; ++$k) {
768+
$className .= $tokens[$k]['content'];
769+
}
770+
771+
$error = 'Use statement ' . $extractedUseStatement . ' for class ' . $className . ' should be in use block.';
772+
$fix = $phpcsFile->addFixableError($error, $colonIndex, 'ReturnSignature');
773+
if (!$fix) {
774+
return;
775+
}
776+
777+
$phpcsFile->fixer->beginChangeset();
778+
779+
$firstSeparatorIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $startIndex, null, true);
780+
781+
$addedUseStatement = $this->addUseStatement($className, $extractedUseStatement);
782+
783+
for ($k = $lastSeparatorIndex; $k > $firstSeparatorIndex; --$k) {
784+
$phpcsFile->fixer->replaceToken($k, '');
785+
}
786+
$phpcsFile->fixer->replaceToken($firstSeparatorIndex, '');
787+
788+
if ($addedUseStatement['alias'] !== null) {
789+
$phpcsFile->fixer->replaceToken($lastIndex, $addedUseStatement['alias']);
790+
}
791+
792+
$phpcsFile->fixer->endChangeset();
793+
}
794+
578795
/**
579796
* @param \PHP_CodeSniffer\Files\File $phpcsFile
580797
* @param int $stackPtr

0 commit comments

Comments
 (0)