From feb66de72394b6ac228e8b7a1140991a7848c60c Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 5 Nov 2021 00:48:29 +0100 Subject: [PATCH 1/4] Add UseManipulatorTest --- ecs.php | 1 + .../UseAnalyzer/Fixture/some_uses.php.inc | 15 +++ .../UseAnalyzer/Source/FirstUsage.php | 10 ++ .../UseAnalyzer/UseAnalyzerTest.php | 75 +++++++++++ .../NodeAnalyzer/UseAnalyzer.php | 120 ++++++++++++++++++ .../ValueObject/NameAndParent.php | 2 +- .../Testing/TestingParser/TestingParser.php | 14 ++ .../ShortNameResolverTest.php | 21 +-- .../UseManipulator/UseManipulatorTest.php | 3 + rules/CodingStyle/Naming/NameRenamer.php | 2 +- rules/CodingStyle/Node/DocAliasResolver.php | 5 +- rules/CodingStyle/Node/UseManipulator.php | 100 --------------- .../Rector/Use_/RemoveUnusedAliasRector.php | 27 +--- 13 files changed, 253 insertions(+), 142 deletions(-) create mode 100644 packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/Fixture/some_uses.php.inc create mode 100644 packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/Source/FirstUsage.php create mode 100644 packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php create mode 100644 packages/NameImporting/NodeAnalyzer/UseAnalyzer.php rename {rules/CodingStyle => packages/NameImporting}/ValueObject/NameAndParent.php (91%) delete mode 100644 rules/CodingStyle/Node/UseManipulator.php diff --git a/ecs.php b/ecs.php index 0701a39cfaa..3c374ee0c9c 100644 --- a/ecs.php +++ b/ecs.php @@ -71,6 +71,7 @@ __DIR__ . '/packages-tests/BetterPhpDocParser/PhpDocInfo/PhpDocInfo/PhpDocInfoTest.php', __DIR__ . '/tests/PhpParser/Node/NodeFactoryTest.php', __DIR__ . '/packages-tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/StaticDoctrineAnnotationParserTest.php', + __DIR__ . '/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php', '*TypeResolverTest.php', __DIR__ . '/rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php', ], diff --git a/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/Fixture/some_uses.php.inc b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/Fixture/some_uses.php.inc new file mode 100644 index 00000000000..f7483e5a476 --- /dev/null +++ b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/Fixture/some_uses.php.inc @@ -0,0 +1,15 @@ +boot(); + + $this->useAnalyzer = $this->getService(UseAnalyzer::class); + $this->testingParser = $this->getService(TestingParser::class); + } + + /** + * @dataProvider provideData() + * + * @param class-string<\PhpParser\Node> $parentNodeType + */ + public function test( + string $filePath, + string $expectedShortName, + int $position, + \PhpParser\Node $expectedNameNode, + string $parentNodeType + ): void { + $file = $this->testingParser->parseFilePathToFile($filePath); + + $namesAndParentsByShortName = $this->useAnalyzer->resolveUsedNameNodes($file); + $this->assertArrayHasKey($expectedShortName, $namesAndParentsByShortName); + + $namesAndParents = $namesAndParentsByShortName[$expectedShortName]; + $this->assertArrayHasKey($position, $namesAndParents); + + $nameAndParent = $namesAndParents[$position]; + $this->assertInstanceOf(NameAndParent::class, $nameAndParent); + + // remove attributes for compare + $nameNode = $nameAndParent->getNameNode(); + $nameNode->setAttributes([]); + + $this->assertEquals($expectedNameNode, $nameNode); + + $this->assertInstanceOf($parentNodeType, $nameAndParent->getParentNode()); + } + + public function provideData(): Iterator + { + yield [ + __DIR__ . '/Fixture/some_uses.php.inc', + 'FirstUsage', + 0, + new FullyQualified(FirstUsage::class), + New_::class, + ]; + yield [__DIR__ . '/Fixture/some_uses.php.inc', 'SomeUses', 0, new Identifier('SomeUses'), Class_::class]; + } +} diff --git a/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php b/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php new file mode 100644 index 00000000000..4b08f61584b --- /dev/null +++ b/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php @@ -0,0 +1,120 @@ + + */ + public function resolveUsedNameNodes(File $file): array + { + $usedNamesByShortName = $this->resolveUsedNames($file); + $usedClassNamesByShortName = $this->resolveUsedClassNames($file); + $usedTraitNamesByShortName = $this->resolveTraitUseNames($file); + + return array_merge($usedNamesByShortName, $usedClassNamesByShortName, $usedTraitNamesByShortName); + } + + /** + * @return array + */ + private function resolveUsedNames(File $file): array + { + $namesAndParentsByShortName = []; + + /** @var Name[] $names */ + $names = $this->betterNodeFinder->findInstanceOf($file->getOldStmts(), Name::class); + + foreach ($names as $name) { + /** node name before becoming FQN - attribute from @see NameResolver */ + $originalName = $name->getAttribute(AttributeKey::ORIGINAL_NAME); + if (! $originalName instanceof Name) { + continue; + } + + $parentNode = $name->getAttribute(AttributeKey::PARENT_NODE); + if (! $parentNode instanceof Node) { + throw new ShouldNotHappenException(); + } + + $shortName = $originalName->toString(); + $namesAndParentsByShortName[$shortName][] = new NameAndParent($name, $parentNode); + } + + return $namesAndParentsByShortName; + } + + /** + * @return array + */ + private function resolveUsedClassNames(File $file): array + { + $namesAndParentsByShortName = []; + + /** @var ClassLike[] $classLikes */ + $classLikes = $this->betterNodeFinder->findClassLikes($file->getOldStmts()); + + foreach ($classLikes as $classLike) { + $classLikeName = $classLike->name; + if (! $classLikeName instanceof Identifier) { + continue; + } + + $name = $this->nodeNameResolver->getName($classLikeName); + if ($name === null) { + continue; + } + + $namesAndParentsByShortName[$name][] = new NameAndParent($classLikeName, $classLike); + } + + return $namesAndParentsByShortName; + } + + /** + * @return array + */ + private function resolveTraitUseNames(File $file): array + { + $namesAndParentsByShortName = []; + + /** @var Identifier[] $identifiers */ + $identifiers = $this->betterNodeFinder->findInstanceOf($file->getOldStmts(), Identifier::class); + + foreach ($identifiers as $identifier) { + $parentNode = $identifier->getAttribute(AttributeKey::PARENT_NODE); + if (! $parentNode instanceof UseUse) { + continue; + } + + $shortName = $identifier->name; + $namesAndParentsByShortName[$shortName][] = new NameAndParent($identifier, $parentNode); + } + + return $namesAndParentsByShortName; + } +} diff --git a/rules/CodingStyle/ValueObject/NameAndParent.php b/packages/NameImporting/ValueObject/NameAndParent.php similarity index 91% rename from rules/CodingStyle/ValueObject/NameAndParent.php rename to packages/NameImporting/ValueObject/NameAndParent.php index 77f49773944..737bdcfee15 100644 --- a/rules/CodingStyle/ValueObject/NameAndParent.php +++ b/packages/NameImporting/ValueObject/NameAndParent.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Rector\CodingStyle\ValueObject; +namespace Rector\NameImporting\ValueObject; use PhpParser\Node; use PhpParser\Node\Identifier; diff --git a/packages/Testing/TestingParser/TestingParser.php b/packages/Testing/TestingParser/TestingParser.php index 9af772d0cdc..e1ca760dd50 100644 --- a/packages/Testing/TestingParser/TestingParser.php +++ b/packages/Testing/TestingParser/TestingParser.php @@ -24,6 +24,17 @@ public function __construct( ) { } + public function parseFilePathToFile(string $filePath): File + { + $smartFileInfo = new SmartFileInfo($filePath); + $file = new File($smartFileInfo, $smartFileInfo->getContents()); + + $stmts = $this->rectorParser->parseFile($smartFileInfo); + $file->hydrateStmtsAndTokens($stmts, $stmts, []); + + return $file; + } + /** * @return Node[] */ @@ -40,6 +51,7 @@ public function parseFileToDecoratedNodes(string $file): array $file = new File($smartFileInfo, $smartFileInfo->getContents()); return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $nodes); } +<<<<<<< HEAD public function parseFilePathToFile(string $filePath): File { @@ -51,4 +63,6 @@ public function parseFilePathToFile(string $filePath): File return $file; } +======= +>>>>>>> b529e101b... add ShortNameResolverTest } diff --git a/rules-tests/CodingStyle/ClassNameImport/ShortNameResolver/ShortNameResolverTest.php b/rules-tests/CodingStyle/ClassNameImport/ShortNameResolver/ShortNameResolverTest.php index 501de6b33de..995f0303704 100644 --- a/rules-tests/CodingStyle/ClassNameImport/ShortNameResolver/ShortNameResolverTest.php +++ b/rules-tests/CodingStyle/ClassNameImport/ShortNameResolver/ShortNameResolverTest.php @@ -6,22 +6,20 @@ use Iterator; use Rector\CodingStyle\ClassNameImport\ShortNameResolver; -use Rector\Core\PhpParser\Parser\RectorParser; -use Rector\Core\ValueObject\Application\File; use Rector\Testing\PHPUnit\AbstractTestCase; -use Symplify\SmartFileSystem\SmartFileInfo; +use Rector\Testing\TestingParser\TestingParser; final class ShortNameResolverTest extends AbstractTestCase { private ShortNameResolver $shortNameResolver; - private RectorParser $rectorParser; + private TestingParser $testingParser; protected function setUp(): void { $this->boot(); $this->shortNameResolver = $this->getService(ShortNameResolver::class); - $this->rectorParser = $this->getService(RectorParser::class); + $this->testingParser = $this->getService(TestingParser::class); } /** @@ -30,7 +28,7 @@ protected function setUp(): void */ public function test(string $filePath, array $expectedShortNames): void { - $file = $this->createFileFromFilePath($filePath); + $file = $this->testingParser->parseFilePathToFile($filePath); $shortNames = $this->shortNameResolver->resolveFromFile($file); $this->assertSame($expectedShortNames, $shortNames); @@ -62,15 +60,4 @@ public function provideData(): Iterator 'SecondLog' => 'Rector\Tests\CodingStyle\ClassNameImport\ShortNameResolver\Source\SecondLog', ]]; } - - private function createFileFromFilePath(string $filePath): File - { - $smartFileInfo = new SmartFileInfo($filePath); - $file = new File($smartFileInfo, $smartFileInfo->getContents()); - - $stmts = $this->rectorParser->parseFile($smartFileInfo); - $file->hydrateStmtsAndTokens($stmts, $stmts, []); - - return $file; - } } diff --git a/rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php b/rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php index 57ba80b5612..3c85e00f5b4 100644 --- a/rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php +++ b/rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php @@ -35,7 +35,10 @@ protected function setUp(): void * @dataProvider provideData() * * @param class-string $parentNodeType +<<<<<<< HEAD * @param Identifier|FullyQualified $expectedNameNode +======= +>>>>>>> Add UseManipulatorTest */ public function test( string $filePath, diff --git a/rules/CodingStyle/Naming/NameRenamer.php b/rules/CodingStyle/Naming/NameRenamer.php index b486beb9e8c..544cf48e61f 100644 --- a/rules/CodingStyle/Naming/NameRenamer.php +++ b/rules/CodingStyle/Naming/NameRenamer.php @@ -17,7 +17,7 @@ use PhpParser\Node\Stmt\Interface_; use PhpParser\Node\Stmt\TraitUse; use PhpParser\Node\UnionType; -use Rector\CodingStyle\ValueObject\NameAndParent; +use Rector\NameImporting\ValueObject\NameAndParent; use Rector\NodeNameResolver\NodeNameResolver; final class NameRenamer diff --git a/rules/CodingStyle/Node/DocAliasResolver.php b/rules/CodingStyle/Node/DocAliasResolver.php index e4a3295e9d8..2982ef3cb74 100644 --- a/rules/CodingStyle/Node/DocAliasResolver.php +++ b/rules/CodingStyle/Node/DocAliasResolver.php @@ -11,6 +11,7 @@ use PHPStan\Type\UnionType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; +use Rector\Core\ValueObject\Application\File; use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType; use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser; @@ -31,11 +32,11 @@ public function __construct( /** * @return string[] */ - public function resolve(Node $node): array + public function resolve(File $file): array { $possibleDocAliases = []; - $this->simpleCallableNodeTraverser->traverseNodesWithCallable($node, function (Node $node) use ( + $this->simpleCallableNodeTraverser->traverseNodesWithCallable($file->getNewStmts(), function (Node $node) use ( &$possibleDocAliases ): void { $docComment = $node->getDocComment(); diff --git a/rules/CodingStyle/Node/UseManipulator.php b/rules/CodingStyle/Node/UseManipulator.php deleted file mode 100644 index 99dee3ecf60..00000000000 --- a/rules/CodingStyle/Node/UseManipulator.php +++ /dev/null @@ -1,100 +0,0 @@ -resolvedNodeNames = []; - - $this->resolveUsedNames($node); - $this->resolveUsedClassNames($node); - $this->resolveTraitUseNames($node); - - return $this->resolvedNodeNames; - } - - private function resolveUsedNames(Node $node): void - { - /** @var Name[] $namedNodes */ - $namedNodes = $this->betterNodeFinder->findInstanceOf($node, Name::class); - - foreach ($namedNodes as $namedNode) { - /** node name before becoming FQN - attribute from @see NameResolver */ - $originalName = $namedNode->getAttribute(AttributeKey::ORIGINAL_NAME); - if (! $originalName instanceof Name) { - continue; - } - - $parentNode = $namedNode->getAttribute(AttributeKey::PARENT_NODE); - if (! $parentNode instanceof Node) { - throw new ShouldNotHappenException(); - } - - $this->resolvedNodeNames[$originalName->toString()][] = new NameAndParent($namedNode, $parentNode); - } - } - - private function resolveUsedClassNames(Node $searchNode): void - { - /** @var ClassLike[] $classLikes */ - $classLikes = $this->betterNodeFinder->findClassLikes([$searchNode]); - - foreach ($classLikes as $classLike) { - $classLikeName = $classLike->name; - if (! $classLikeName instanceof Identifier) { - continue; - } - - $name = $this->nodeNameResolver->getName($classLikeName); - if ($name === null) { - continue; - } - - $this->resolvedNodeNames[$name][] = new NameAndParent($classLikeName, $classLike); - } - } - - private function resolveTraitUseNames(Node $searchNode): void - { - /** @var Identifier[] $identifiers */ - $identifiers = $this->betterNodeFinder->findInstanceOf($searchNode, Identifier::class); - - foreach ($identifiers as $identifier) { - $parentNode = $identifier->getAttribute(AttributeKey::PARENT_NODE); - if (! $parentNode instanceof UseUse) { - continue; - } - - $this->resolvedNodeNames[$identifier->name][] = new NameAndParent($identifier, $parentNode); - } - } -} diff --git a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php index c195e900e22..c840c722544 100644 --- a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php +++ b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php @@ -12,11 +12,11 @@ use Rector\CodingStyle\ClassNameImport\ClassNameImportSkipper; use Rector\CodingStyle\Naming\NameRenamer; use Rector\CodingStyle\Node\DocAliasResolver; -use Rector\CodingStyle\Node\UseManipulator; use Rector\CodingStyle\Node\UseNameAliasToNameResolver; -use Rector\CodingStyle\ValueObject\NameAndParent; use Rector\Core\PhpParser\NodeFinder\FullyQualifiedFromUseFinder; use Rector\Core\Rector\AbstractRector; +use Rector\NameImporting\NodeAnalyzer\UseAnalyzer; +use Rector\NameImporting\ValueObject\NameAndParent; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -27,7 +27,7 @@ final class RemoveUnusedAliasRector extends AbstractRector { /** - * @var NameAndParent[][] + * @var array */ private array $resolvedNodeNames = []; @@ -43,7 +43,7 @@ final class RemoveUnusedAliasRector extends AbstractRector public function __construct( private DocAliasResolver $docAliasResolver, - private UseManipulator $useManipulator, + private UseAnalyzer $useManipulator, private UseNameAliasToNameResolver $useNameAliasToNameResolver, private NameRenamer $nameRenamer, private ClassNameImportSkipper $classNameImportSkipper, @@ -94,13 +94,8 @@ public function refactor(Node $node): ?Node return null; } - $searchNode = $this->resolveSearchNode($node); - if (! $searchNode instanceof Node) { - return null; - } - - $this->resolvedNodeNames = $this->useManipulator->resolveUsedNameNodes($searchNode); - $this->resolvedDocPossibleAliases = $this->docAliasResolver->resolve($searchNode); + $this->resolvedNodeNames = $this->useManipulator->resolveUsedNameNodes($this->file); + $this->resolvedDocPossibleAliases = $this->docAliasResolver->resolve($this->file); $this->useNamesAliasToName = $this->useNameAliasToNameResolver->resolve($this->file); @@ -147,16 +142,6 @@ private function shouldSkipUse(Use_ $use): bool return ! $this->hasUseAlias($use); } - private function resolveSearchNode(Use_ $use): ?Node - { - $searchNode = $use->getAttribute(AttributeKey::PARENT_NODE); - if ($searchNode !== null) { - return $searchNode; - } - - return $use->getAttribute(AttributeKey::NEXT_NODE); - } - /** * @param string[] $values * @return string[] From e2bd57ed4cc791c7d6d4939ea65a272b9cd315e8 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 5 Nov 2021 00:31:54 +0100 Subject: [PATCH 2/4] rename vairabe --- .../UseAnalyzer/UseAnalyzerTest.php | 9 +- .../NodeAnalyzer/UseAnalyzer.php | 21 +++-- .../Testing/TestingParser/TestingParser.php | 14 ---- .../UseManipulator/Fixture/some_uses.php.inc | 15 ---- .../Node/UseManipulator/Source/FirstUsage.php | 10 --- .../UseManipulator/UseManipulatorTest.php | 83 ------------------- rules/CodingStyle/Node/DocAliasResolver.php | 5 +- .../Rector/Use_/RemoveUnusedAliasRector.php | 39 +++++++-- 8 files changed, 48 insertions(+), 148 deletions(-) delete mode 100644 rules-tests/CodingStyle/Node/UseManipulator/Fixture/some_uses.php.inc delete mode 100644 rules-tests/CodingStyle/Node/UseManipulator/Source/FirstUsage.php delete mode 100644 rules-tests/CodingStyle/Node/UseManipulator/UseManipulatorTest.php diff --git a/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php index 24763c6fb98..cce9c401353 100644 --- a/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php +++ b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php @@ -5,8 +5,10 @@ namespace Rector\Tests\NameImporting\NodeAnalyzer\UseAnalyzer; use Iterator; +use PhpParser\Node; use PhpParser\Node\Expr\New_; use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; use Rector\NameImporting\NodeAnalyzer\UseAnalyzer; @@ -32,18 +34,19 @@ protected function setUp(): void /** * @dataProvider provideData() * - * @param class-string<\PhpParser\Node> $parentNodeType + * @param class-string $parentNodeType */ public function test( string $filePath, string $expectedShortName, int $position, - \PhpParser\Node $expectedNameNode, + Name|Identifier $expectedNameNode, string $parentNodeType ): void { $file = $this->testingParser->parseFilePathToFile($filePath); + $firstStmt = $file->getOldStmts()[1]; - $namesAndParentsByShortName = $this->useAnalyzer->resolveUsedNameNodes($file); + $namesAndParentsByShortName = $this->useAnalyzer->resolveUsedNameNodes($firstStmt); $this->assertArrayHasKey($expectedShortName, $namesAndParentsByShortName); $namesAndParents = $namesAndParentsByShortName[$expectedShortName]; diff --git a/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php b/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php index 4b08f61584b..eef624eaf41 100644 --- a/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php +++ b/packages/NameImporting/NodeAnalyzer/UseAnalyzer.php @@ -11,7 +11,6 @@ use PhpParser\Node\Stmt\UseUse; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Node\BetterNodeFinder; -use Rector\Core\ValueObject\Application\File; use Rector\NameImporting\ValueObject\NameAndParent; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -30,11 +29,11 @@ public function __construct( /** * @return array */ - public function resolveUsedNameNodes(File $file): array + public function resolveUsedNameNodes(Node $node): array { - $usedNamesByShortName = $this->resolveUsedNames($file); - $usedClassNamesByShortName = $this->resolveUsedClassNames($file); - $usedTraitNamesByShortName = $this->resolveTraitUseNames($file); + $usedNamesByShortName = $this->resolveUsedNames($node); + $usedClassNamesByShortName = $this->resolveUsedClassNames($node); + $usedTraitNamesByShortName = $this->resolveTraitUseNames($node); return array_merge($usedNamesByShortName, $usedClassNamesByShortName, $usedTraitNamesByShortName); } @@ -42,12 +41,12 @@ public function resolveUsedNameNodes(File $file): array /** * @return array */ - private function resolveUsedNames(File $file): array + private function resolveUsedNames(Node $node): array { $namesAndParentsByShortName = []; /** @var Name[] $names */ - $names = $this->betterNodeFinder->findInstanceOf($file->getOldStmts(), Name::class); + $names = $this->betterNodeFinder->findInstanceOf($node, Name::class); foreach ($names as $name) { /** node name before becoming FQN - attribute from @see NameResolver */ @@ -71,12 +70,12 @@ private function resolveUsedNames(File $file): array /** * @return array */ - private function resolveUsedClassNames(File $file): array + private function resolveUsedClassNames(Node $node): array { $namesAndParentsByShortName = []; /** @var ClassLike[] $classLikes */ - $classLikes = $this->betterNodeFinder->findClassLikes($file->getOldStmts()); + $classLikes = $this->betterNodeFinder->findClassLikes($node); foreach ($classLikes as $classLike) { $classLikeName = $classLike->name; @@ -98,12 +97,12 @@ private function resolveUsedClassNames(File $file): array /** * @return array */ - private function resolveTraitUseNames(File $file): array + private function resolveTraitUseNames(Node $node): array { $namesAndParentsByShortName = []; /** @var Identifier[] $identifiers */ - $identifiers = $this->betterNodeFinder->findInstanceOf($file->getOldStmts(), Identifier::class); + $identifiers = $this->betterNodeFinder->findInstanceOf($node, Identifier::class); foreach ($identifiers as $identifier) { $parentNode = $identifier->getAttribute(AttributeKey::PARENT_NODE); diff --git a/packages/Testing/TestingParser/TestingParser.php b/packages/Testing/TestingParser/TestingParser.php index e1ca760dd50..70797ed9061 100644 --- a/packages/Testing/TestingParser/TestingParser.php +++ b/packages/Testing/TestingParser/TestingParser.php @@ -51,18 +51,4 @@ public function parseFileToDecoratedNodes(string $file): array $file = new File($smartFileInfo, $smartFileInfo->getContents()); return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $nodes); } -<<<<<<< HEAD - - public function parseFilePathToFile(string $filePath): File - { - $smartFileInfo = new SmartFileInfo($filePath); - $file = new File($smartFileInfo, $smartFileInfo->getContents()); - - $stmts = $this->rectorParser->parseFile($smartFileInfo); - $file->hydrateStmtsAndTokens($stmts, $stmts, []); - - return $file; - } -======= ->>>>>>> b529e101b... add ShortNameResolverTest } diff --git a/rules-tests/CodingStyle/Node/UseManipulator/Fixture/some_uses.php.inc b/rules-tests/CodingStyle/Node/UseManipulator/Fixture/some_uses.php.inc deleted file mode 100644 index 82466f52e27..00000000000 --- a/rules-tests/CodingStyle/Node/UseManipulator/Fixture/some_uses.php.inc +++ /dev/null @@ -1,15 +0,0 @@ -boot(); - - $this->useManipulator = $this->getService(UseManipulator::class); - $this->testingParser = $this->getService(TestingParser::class); - } - - /** - * @dataProvider provideData() - * - * @param class-string $parentNodeType -<<<<<<< HEAD - * @param Identifier|FullyQualified $expectedNameNode -======= ->>>>>>> Add UseManipulatorTest - */ - public function test( - string $filePath, - string $expectedShortName, - int $position, - Name|Identifier $expectedNameNode, - string $parentNodeType - ): void { - $file = $this->testingParser->parseFilePathToFile($filePath); - - $firstStmt = $file->getOldStmts()[1]; - - $namesAndParentsByShortName = $this->useManipulator->resolveUsedNameNodes($firstStmt); - $this->assertArrayHasKey($expectedShortName, $namesAndParentsByShortName); - - $namesAndParents = $namesAndParentsByShortName[$expectedShortName]; - $this->assertArrayHasKey($position, $namesAndParents); - - $nameAndParent = $namesAndParents[$position]; - $this->assertInstanceOf(NameAndParent::class, $nameAndParent); - - // remove attributes for compare - $nameNode = $nameAndParent->getNameNode(); - $nameNode->setAttributes([]); - - $this->assertEquals($expectedNameNode, $nameNode); - - $this->assertInstanceOf($parentNodeType, $nameAndParent->getParentNode()); - } - - public function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/some_uses.php.inc', - 'FirstUsage', - 0, - new FullyQualified(FirstUsage::class), - New_::class, - ]; - yield [__DIR__ . '/Fixture/some_uses.php.inc', 'SomeUses', 0, new Identifier('SomeUses'), Class_::class]; - } -} diff --git a/rules/CodingStyle/Node/DocAliasResolver.php b/rules/CodingStyle/Node/DocAliasResolver.php index 2982ef3cb74..e4a3295e9d8 100644 --- a/rules/CodingStyle/Node/DocAliasResolver.php +++ b/rules/CodingStyle/Node/DocAliasResolver.php @@ -11,7 +11,6 @@ use PHPStan\Type\UnionType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; -use Rector\Core\ValueObject\Application\File; use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType; use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser; @@ -32,11 +31,11 @@ public function __construct( /** * @return string[] */ - public function resolve(File $file): array + public function resolve(Node $node): array { $possibleDocAliases = []; - $this->simpleCallableNodeTraverser->traverseNodesWithCallable($file->getNewStmts(), function (Node $node) use ( + $this->simpleCallableNodeTraverser->traverseNodesWithCallable($node, function (Node $node) use ( &$possibleDocAliases ): void { $docComment = $node->getDocComment(); diff --git a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php index c840c722544..90400a016b5 100644 --- a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php +++ b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php @@ -29,7 +29,7 @@ final class RemoveUnusedAliasRector extends AbstractRector /** * @var array */ - private array $resolvedNodeNames = []; + private array $resolvedNamesAndParentsByShortName = []; /** * @var array @@ -43,7 +43,7 @@ final class RemoveUnusedAliasRector extends AbstractRector public function __construct( private DocAliasResolver $docAliasResolver, - private UseAnalyzer $useManipulator, + private UseAnalyzer $useAnalyzer, private UseNameAliasToNameResolver $useNameAliasToNameResolver, private NameRenamer $nameRenamer, private ClassNameImportSkipper $classNameImportSkipper, @@ -94,15 +94,23 @@ public function refactor(Node $node): ?Node return null; } - $this->resolvedNodeNames = $this->useManipulator->resolveUsedNameNodes($this->file); - $this->resolvedDocPossibleAliases = $this->docAliasResolver->resolve($this->file); + $searchNode = $this->resolveSearchNode($node); + if (! $searchNode instanceof \PhpParser\Node) { + return null; + } + $this->resolvedNamesAndParentsByShortName = $this->useAnalyzer->resolveUsedNameNodes($searchNode); + $this->resolvedDocPossibleAliases = $this->docAliasResolver->resolve($searchNode); $this->useNamesAliasToName = $this->useNameAliasToNameResolver->resolve($this->file); // lowercase $this->resolvedDocPossibleAliases = $this->lowercaseArray($this->resolvedDocPossibleAliases); - $this->resolvedNodeNames = array_change_key_case($this->resolvedNodeNames, CASE_LOWER); + $this->resolvedNamesAndParentsByShortName = array_change_key_case( + $this->resolvedNamesAndParentsByShortName, + CASE_LOWER + ); + $this->useNamesAliasToName = array_change_key_case($this->useNamesAliasToName, CASE_LOWER); foreach ($node->uses as $use) { @@ -120,7 +128,7 @@ public function refactor(Node $node): ?Node } // only last name is used → no need for alias - if (isset($this->resolvedNodeNames[$lowercasedLastName])) { + if (isset($this->resolvedNamesAndParentsByShortName[$lowercasedLastName])) { $use->alias = null; continue; } @@ -158,7 +166,7 @@ private function shouldSkip(Use_ $use, string $lastName, string $aliasName): boo $loweredAliasName = strtolower($aliasName); // both are used → nothing to remove - if (isset($this->resolvedNodeNames[$loweredLastName], $this->resolvedNodeNames[$loweredAliasName])) { + if (isset($this->resolvedNamesAndParentsByShortName[$loweredLastName], $this->resolvedNamesAndParentsByShortName[$loweredAliasName])) { return true; } @@ -191,11 +199,14 @@ private function refactorAliasName(Use_ $use, string $fullUseUseName, string $la } $loweredFullUseUseName = strtolower($fullUseUseName); - if (! isset($this->resolvedNodeNames[$loweredFullUseUseName])) { + if (! isset($this->resolvedNamesAndParentsByShortName[$loweredFullUseUseName])) { return; } - $this->nameRenamer->renameNameNode($this->resolvedNodeNames[$loweredFullUseUseName], $lastName); + $this->nameRenamer->renameNameNode( + $this->resolvedNamesAndParentsByShortName[$loweredFullUseUseName], + $lastName + ); $useUse->alias = null; } @@ -209,4 +220,14 @@ private function hasUseAlias(Use_ $use): bool return false; } + + private function resolveSearchNode(Use_ $use): ?Node + { + $searchNode = $use->getAttribute(AttributeKey::PARENT_NODE); + if ($searchNode !== null) { + return $searchNode; + } + + return $use->getAttribute(AttributeKey::NEXT_NODE); + } } From a5df45b6152bfd1a67363a8268bed23135ee1d09 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 5 Nov 2021 00:11:30 +0000 Subject: [PATCH 3/4] [ci-review] Rector Rectify --- .../NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php index cce9c401353..3df482c841c 100644 --- a/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php +++ b/packages-tests/NameImporting/NodeAnalyzer/UseAnalyzer/UseAnalyzerTest.php @@ -35,6 +35,7 @@ protected function setUp(): void * @dataProvider provideData() * * @param class-string $parentNodeType + * @param Identifier|FullyQualified $expectedNameNode */ public function test( string $filePath, From df690c0a843658456fc067f31e4eda620ed5a2d4 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 5 Nov 2021 00:13:46 +0000 Subject: [PATCH 4/4] [ci-review] Rector Rectify --- rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php index 90400a016b5..93cffe091e5 100644 --- a/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php +++ b/rules/CodingStyle/Rector/Use_/RemoveUnusedAliasRector.php @@ -95,7 +95,7 @@ public function refactor(Node $node): ?Node } $searchNode = $this->resolveSearchNode($node); - if (! $searchNode instanceof \PhpParser\Node) { + if (! $searchNode instanceof Node) { return null; }