Skip to content

Commit 364ad3e

Browse files
committed
Updated Rector to commit a181f3feb3bb9fdd5c1913afc1272a47521004e2
rectorphp/rector-src@a181f3f [PostRector] Skip inline {@see } used use statement on remove unused imports (#8080)
1 parent 55aabe0 commit 364ad3e

4 files changed

Lines changed: 73 additions & 5 deletions

File tree

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = 'a7b3eb3a76e0591713ee30e7a869b8942ddfca40';
22+
public const PACKAGE_VERSION = 'a181f3feb3bb9fdd5c1913afc1272a47521004e2';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2026-06-23 12:23:20';
27+
public const RELEASE_DATE = '2026-06-24 14:45:58';
2828
/**
2929
* @var int
3030
*/

src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare (strict_types=1);
44
namespace Rector\BetterPhpDocParser\PhpDocInfo;
55

6+
use RectorPrefix202606\Nette\Utils\Strings;
67
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
78
use PHPStan\PhpDocParser\Ast\Node;
89
use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
@@ -33,6 +34,7 @@
3334
use Rector\BetterPhpDocParser\ValueObject\Type\ShortenedIdentifierTypeNode;
3435
use Rector\Exception\ShouldNotHappenException;
3536
use Rector\PhpDocParser\PhpDocParser\PhpDocNodeTraverser;
37+
use Rector\StaticTypeMapper\Naming\NameScopeFactory;
3638
use Rector\StaticTypeMapper\StaticTypeMapper;
3739
use Rector\Validation\RectorAssert;
3840
use RectorPrefix202606\Webmozart\Assert\InvalidArgumentException;
@@ -65,6 +67,15 @@ final class PhpDocInfo
6567
* @readonly
6668
*/
6769
private PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder;
70+
/**
71+
* @readonly
72+
*/
73+
private NameScopeFactory $nameScopeFactory;
74+
/**
75+
* @see https://regex101.com/r/7GCrlj/2
76+
* @var string
77+
*/
78+
private const INLINE_GENERIC_USES_CLASS_REFERENCE_REGEX = '#\{@(?:uses|used-by|see)\s+(?<class_name>[^}\s]+)#';
6879
/**
6980
* @var array<class-string<PhpDocTagValueNode>, string>
7081
*/
@@ -74,14 +85,15 @@ final class PhpDocInfo
7485
* @readonly
7586
*/
7687
private PhpDocNode $originalPhpDocNode;
77-
public function __construct(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator, StaticTypeMapper $staticTypeMapper, \PhpParser\Node $node, AnnotationNaming $annotationNaming, PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder)
88+
public function __construct(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator, StaticTypeMapper $staticTypeMapper, \PhpParser\Node $node, AnnotationNaming $annotationNaming, PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder, NameScopeFactory $nameScopeFactory)
7889
{
7990
$this->phpDocNode = $phpDocNode;
8091
$this->betterTokenIterator = $betterTokenIterator;
8192
$this->staticTypeMapper = $staticTypeMapper;
8293
$this->node = $node;
8394
$this->annotationNaming = $annotationNaming;
8495
$this->phpDocNodeByTypeFinder = $phpDocNodeByTypeFinder;
96+
$this->nameScopeFactory = $nameScopeFactory;
8597
$this->originalPhpDocNode = clone $phpDocNode;
8698
if (!$betterTokenIterator->containsTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
8799
$this->isSingleLine = \true;
@@ -411,6 +423,27 @@ public function getGenericTagClassNames(): array
411423
}
412424
return $resolvedClasses;
413425
}
426+
/**
427+
* @return string[]
428+
*/
429+
public function getInlineGenericUsesTagClassNames(): array
430+
{
431+
$printedPhpDocNode = (string) $this->phpDocNode;
432+
if (strpos($printedPhpDocNode, '{') === \false) {
433+
return [];
434+
}
435+
$matches = Strings::matchAll($printedPhpDocNode, self::INLINE_GENERIC_USES_CLASS_REFERENCE_REGEX);
436+
$classNames = [];
437+
foreach ($matches as $match) {
438+
$reference = $match['class_name'];
439+
$resolvedClassNames = $this->resolveInlineGenericUsesReferenceClassNames($reference);
440+
if ($resolvedClassNames === []) {
441+
continue;
442+
}
443+
$classNames = array_merge($classNames, $resolvedClassNames);
444+
}
445+
return array_unique($classNames);
446+
}
414447
/**
415448
* @return string[]
416449
*/
@@ -468,6 +501,33 @@ private function resolveNameForPhpDocTagValueNode(PhpDocTagValueNode $phpDocTagV
468501
}
469502
return null;
470503
}
504+
/**
505+
* @return string[]
506+
*/
507+
private function resolveInlineGenericUsesReferenceClassNames(string $reference): array
508+
{
509+
$reference = explode('|', $reference, 2)[0];
510+
$reference = explode('::', $reference, 2)[0];
511+
$referenceToResolve = $reference;
512+
$reference = ltrim($reference, '\\');
513+
try {
514+
RectorAssert::className($reference);
515+
} catch (InvalidArgumentException $exception) {
516+
return [];
517+
}
518+
// fqcn not reference to any use statements
519+
if (strncmp($referenceToResolve, '\\', strlen('\\')) === 0) {
520+
return [$referenceToResolve];
521+
}
522+
$nameScope = $this->nameScopeFactory->createNameScopeFromNodeWithoutTemplateTypes($this->node);
523+
$resolvedClassName = $nameScope->resolveStringName($referenceToResolve);
524+
if (strpos($reference, '\\') !== \false) {
525+
// Keep both forms: resolved class for namespace-aware matching and original class
526+
// for alias-partial matching in unused import checks.
527+
return array_unique([$resolvedClassName, $reference]);
528+
}
529+
return [$resolvedClassName];
530+
}
471531
/**
472532
* @return \PHPStan\Type\MixedType|\PHPStan\Type\Type
473533
*/

src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
1616
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
1717
use Rector\NodeTypeResolver\Node\AttributeKey;
18+
use Rector\StaticTypeMapper\Naming\NameScopeFactory;
1819
use Rector\StaticTypeMapper\StaticTypeMapper;
1920
final class PhpDocInfoFactory
2021
{
@@ -42,18 +43,23 @@ final class PhpDocInfoFactory
4243
* @readonly
4344
*/
4445
private PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder;
46+
/**
47+
* @readonly
48+
*/
49+
private NameScopeFactory $nameScopeFactory;
4550
/**
4651
* @var array<int, PhpDocInfo>
4752
*/
4853
private array $phpDocInfosByObjectId = [];
49-
public function __construct(PhpDocNodeMapper $phpDocNodeMapper, Lexer $lexer, BetterPhpDocParser $betterPhpDocParser, StaticTypeMapper $staticTypeMapper, AnnotationNaming $annotationNaming, PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder)
54+
public function __construct(PhpDocNodeMapper $phpDocNodeMapper, Lexer $lexer, BetterPhpDocParser $betterPhpDocParser, StaticTypeMapper $staticTypeMapper, AnnotationNaming $annotationNaming, PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder, NameScopeFactory $nameScopeFactory)
5055
{
5156
$this->phpDocNodeMapper = $phpDocNodeMapper;
5257
$this->lexer = $lexer;
5358
$this->betterPhpDocParser = $betterPhpDocParser;
5459
$this->staticTypeMapper = $staticTypeMapper;
5560
$this->annotationNaming = $annotationNaming;
5661
$this->phpDocNodeByTypeFinder = $phpDocNodeByTypeFinder;
62+
$this->nameScopeFactory = $nameScopeFactory;
5763
}
5864
public function createFromNodeOrEmpty(Node $node): \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo
5965
{
@@ -121,7 +127,7 @@ private function setPositionOfLastToken(PhpDocNode $phpDocNode): void
121127
private function createFromPhpDocNode(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator, Node $node): \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo
122128
{
123129
$this->phpDocNodeMapper->transform($phpDocNode, $betterTokenIterator);
124-
$phpDocInfo = new \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo($phpDocNode, $betterTokenIterator, $this->staticTypeMapper, $node, $this->annotationNaming, $this->phpDocNodeByTypeFinder);
130+
$phpDocInfo = new \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo($phpDocNode, $betterTokenIterator, $this->staticTypeMapper, $node, $this->annotationNaming, $this->phpDocNodeByTypeFinder, $this->nameScopeFactory);
125131
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
126132
return $phpDocInfo;
127133
}

src/PostRector/Rector/UnusedImportRemovingPostRector.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ private function findNamesInDocBlocks($rootNode): array
139139
$names = array_merge($names, $constFetchNodeNames);
140140
$genericTagClassNames = $phpDocInfo->getGenericTagClassNames();
141141
$names = array_merge($names, $genericTagClassNames);
142+
$inlineGenericUsesTagClassNames = $phpDocInfo->getInlineGenericUsesTagClassNames();
143+
$names = array_merge($names, $inlineGenericUsesTagClassNames);
142144
$arrayItemTagClassNames = $phpDocInfo->getArrayItemNodeClassNames();
143145
$names = array_merge($names, $arrayItemTagClassNames);
144146
}

0 commit comments

Comments
 (0)