Skip to content

Commit

Permalink
[Naming] Remove parent lookup on UseImportsResolver (#4367)
Browse files Browse the repository at this point in the history
* [Naming] Remove parent lookup on UseImportsResolver

* [ci-review] Rector Rectify

* clean up

* [ci-review] Rector Rectify

* Fix with traverse

* Fix file object null

* Fix test

* [ci-review] Rector Rectify

* phpstan

* Fix

* Fix

* phpstan

* hydrate must be after decorated

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Jun 27, 2023
1 parent b408d9e commit 40a1f34
Show file tree
Hide file tree
Showing 17 changed files with 97 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private function _resolveTagFullyQualifiedName(

$tag = ltrim($tag, '@');

$uses = $this->useImportsResolver->resolveForNode($node);
$uses = $this->useImportsResolver->resolve();
$fullyQualifiedClass = $this->resolveFullyQualifiedClass($uses, $node, $tag, $returnNullOnUnknownClass);

if ($fullyQualifiedClass === null) {
Expand Down
10 changes: 8 additions & 2 deletions packages/FileSystemRector/Parser/FileInfoParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpParser\Node\Stmt;
use Rector\Core\PhpParser\NodeTraverser\FileWithoutNamespaceNodeTraverser;
use Rector\Core\PhpParser\Parser\RectorParser;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\ValueObject\Application\File;
use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator;

Expand All @@ -19,7 +20,8 @@ final class FileInfoParser
public function __construct(
private readonly NodeScopeAndMetadataDecorator $nodeScopeAndMetadataDecorator,
private readonly FileWithoutNamespaceNodeTraverser $fileWithoutNamespaceNodeTraverser,
private readonly RectorParser $rectorParser
private readonly RectorParser $rectorParser,
private readonly CurrentFileProvider $currentFileProvider
) {
}

Expand All @@ -33,7 +35,11 @@ public function parseFileInfoToNodesAndDecorate(string $filePath): array
$stmts = $this->fileWithoutNamespaceNodeTraverser->traverse($stmts);

$file = new File($filePath, FileSystem::read($filePath));
$stmts = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $stmts);

return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $stmts);
$file->hydrateStmtsAndTokens($stmts, $stmts, []);
$this->currentFileProvider->setFile($file);

return $stmts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private function resolveNamespacedName(
return $name;
}

$uses = $this->useImportsResolver->resolveForNode($phpParserNode);
$uses = $this->useImportsResolver->resolve();
$scope = $phpParserNode->getAttribute(AttributeKey::SCOPE);

if (! $scope instanceof Scope) {
Expand Down
2 changes: 1 addition & 1 deletion packages/PostRector/Collector/UseNodesToAddCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function getUseImportTypesByNode(File $file, Node $node): array
$filePath = $file->getFilePath();
$objectTypes = $this->useImportTypesInFilePath[$filePath] ?? [];

$uses = $this->useImportsResolver->resolveForNode($node);
$uses = $this->useImportsResolver->resolve();

foreach ($uses as $use) {
$prefix = $this->useImportsResolver->resolvePrefix($use);
Expand Down
2 changes: 1 addition & 1 deletion packages/PostRector/Rector/NameImportingPostRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private function processNodeName(Name $name, File $file): ?Node
}

/** @var Use_[]|GroupUse[] $currentUses */
$currentUses = $this->useImportsResolver->resolveForNode($name);
$currentUses = $this->useImportsResolver->resolve();

if ($this->shouldImportName($name, $currentUses)) {
$nameInUse = $this->resolveNameInUse($name, $currentUses);
Expand Down
2 changes: 1 addition & 1 deletion packages/PostRector/Rector/UseAddingPostRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private function resolveNodesWithImportedUses(
$useImportTypes = $this->filterOutNonNamespacedNames($useImportTypes);

// then add, to prevent adding + removing false positive of same short use
return $this->useImportsAdder->addImportsToStmts($nodes, $useImportTypes, $functionUseImportTypes);
return $this->useImportsAdder->addImportsToStmts($namespace, $nodes, $useImportTypes, $functionUseImportTypes);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/StaticTypeMapper/Naming/NameScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function createNameScopeFromNodeWithoutTemplateTypes(Node $node): NameSco
$scope = $node->getAttribute(AttributeKey::SCOPE);
$namespace = $scope instanceof Scope ? $scope->getNamespace() : null;

$uses = $this->useImportsResolver->resolveForNode($node);
$uses = $this->useImportsResolver->resolve();
$usesAliasesToNames = $this->resolveUseNamesByAlias($uses);

if ($scope instanceof Scope && $scope->getClassReflection() instanceof ClassReflection) {
Expand Down
15 changes: 13 additions & 2 deletions packages/Testing/TestingParser/TestingParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Rector\Core\Configuration\Option;
use Rector\Core\Configuration\Parameter\ParameterProvider;
use Rector\Core\PhpParser\Parser\RectorParser;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\ValueObject\Application\File;
use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator;

Expand All @@ -21,6 +22,7 @@ public function __construct(
private readonly ParameterProvider $parameterProvider,
private readonly RectorParser $rectorParser,
private readonly NodeScopeAndMetadataDecorator $nodeScopeAndMetadataDecorator,
private readonly CurrentFileProvider $currentFileProvider
) {
}

Expand All @@ -29,7 +31,10 @@ public function parseFilePathToFile(string $filePath): File
$file = new File($filePath, FileSystem::read($filePath));

$stmts = $this->rectorParser->parseFile($filePath);
$stmts = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $stmts);

$file->hydrateStmtsAndTokens($stmts, $stmts, []);
$this->currentFileProvider->setFile($file);

return $file;
}
Expand All @@ -41,9 +46,15 @@ public function parseFileToDecoratedNodes(string $filePath): array
{
$this->parameterProvider->changeParameter(Option::SOURCE, [$filePath]);

$nodes = $this->rectorParser->parseFile($filePath);
$stmts = $this->rectorParser->parseFile($filePath);

$file = new File($filePath, FileSystem::read($filePath));
return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $nodes);

$stmts = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($file, $stmts);
$file->hydrateStmtsAndTokens($stmts, $stmts, []);

$this->currentFileProvider->setFile($file);

return $stmts;
}
}
6 changes: 6 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,9 @@ parameters:

# for symfony configs check
- '#Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\tagged_iterator not found#'

-
message: '#Parameters should use "PhpParser\\Node\\Expr\\Variable\|array" types as the only types passed to this method#'
path: src/PhpParser/Node/BetterNodeFinder.php

- '#The "Rector\\Core\\ValueObject\\Application\\File" class always calls "hydrateStmtsAndTokens\(\)" setters, better move it to constructor#'
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function testUsesFromProperty(string $filePath): void
$firstProperty = $this->betterNodeFinder->findFirstInstanceOf($nodes, Property::class);
$this->assertInstanceOf(Property::class, $firstProperty);

$resolvedUses = $this->useImportsResolver->resolveForNode($firstProperty);
$resolvedUses = $this->useImportsResolver->resolve();

$stringUses = [];

Expand Down
14 changes: 11 additions & 3 deletions rules/CodingStyle/Application/UseImportsAdder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use PhpParser\Node\Stmt\Use_;
use PHPStan\Type\ObjectType;
use Rector\CodingStyle\ClassNameImport\UsedImportsResolver;
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
Expand All @@ -32,7 +33,7 @@ public function __construct(
* @param array<FullyQualifiedObjectType|AliasedObjectType> $functionUseImportTypes
* @return Stmt[]
*/
public function addImportsToStmts(array $stmts, array $useImportTypes, array $functionUseImportTypes): array
public function addImportsToStmts(FileWithoutNamespace $fileWithoutNamespace, array $stmts, array $useImportTypes, array $functionUseImportTypes): array
{
$existingUseImportTypes = $this->usedImportsResolver->resolveForStmts($stmts);
$existingFunctionUseImports = $this->usedImportsResolver->resolveFunctionImportsForStmts($stmts);
Expand Down Expand Up @@ -62,14 +63,20 @@ public function addImportsToStmts(array $stmts, array $useImportTypes, array $fu

array_splice($stmts, $key + 1, 0, $nodesToAdd);

return $stmts;
$fileWithoutNamespace->stmts = $stmts;
$fileWithoutNamespace->stmts = array_values($fileWithoutNamespace->stmts);

return $fileWithoutNamespace->stmts;
}
}

$this->mirrorUseComments($stmts, $newUses);

// make use stmts first
return array_merge($newUses, $stmts);
$fileWithoutNamespace->stmts = array_merge($newUses, $stmts);
$fileWithoutNamespace->stmts = array_values($fileWithoutNamespace->stmts);

return $fileWithoutNamespace->stmts;
}

/**
Expand Down Expand Up @@ -104,6 +111,7 @@ public function addImportsToNamespace(
$this->mirrorUseComments($namespace->stmts, $newUses);

$namespace->stmts = array_merge($newUses, $namespace->stmts);
$namespace->stmts = array_values($namespace->stmts);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion rules/Naming/Naming/AliasNameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function __construct(

public function resolveByName(Name $name): ?string
{
$uses = $this->useImportsResolver->resolveForNode($name);
$uses = $this->useImportsResolver->resolve();
$nameString = $name->toString();

foreach ($uses as $use) {
Expand Down
59 changes: 47 additions & 12 deletions rules/Naming/Naming/UseImportsResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,63 @@
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
use Rector\Core\PhpParser\NodeTraverser\FileWithoutNamespaceNodeTraverser;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\ValueObject\Application\File;

final class UseImportsResolver
{
public function __construct(
private readonly BetterNodeFinder $betterNodeFinder
private readonly CurrentFileProvider $currentFileProvider,
private readonly FileWithoutNamespaceNodeTraverser $fileWithoutNamespaceNodeTraverser
) {
}

private function resolveNamespace(): Namespace_|FileWithoutNamespace|null
{
/** @var File|null $file */
$file = $this->currentFileProvider->getFile();
if (! $file instanceof File) {
return null;
}

$newStmts = $file->getNewStmts();

if ($newStmts === []) {
return null;
}

$namespaces = array_filter($newStmts, static fn(Stmt $stmt): bool => $stmt instanceof Namespace_);

// multiple namespaces is not supported
if (count($namespaces) > 1) {
return null;
}

$currentNamespace = current($namespaces);
if ($currentNamespace instanceof Namespace_) {
return $currentNamespace;
}

$currentStmt = current($newStmts);
if (! $currentStmt instanceof FileWithoutNamespace) {
$newStmts = $this->fileWithoutNamespaceNodeTraverser->traverse($newStmts);
/** @var FileWithoutNamespace $currentStmt */
$currentStmt = current($newStmts);

return $currentStmt;
}

return $currentStmt;
}

/**
* @return Use_[]|GroupUse[]
*/
public function resolveForNode(Node $node): array
public function resolve(): array
{
$namespace = $this->betterNodeFinder->findParentByTypes(
$node,
[Namespace_::class, FileWithoutNamespace::class]
);
$namespace = $this->resolveNamespace();
if (! $namespace instanceof Node) {
return [];
}
Expand All @@ -42,12 +80,9 @@ public function resolveForNode(Node $node): array
* @api
* @return Use_[]
*/
public function resolveBareUsesForNode(Node $node): array
public function resolveBareUses(): array
{
$namespace = $this->betterNodeFinder->findParentByTypes(
$node,
[Namespace_::class, FileWithoutNamespace::class]
);
$namespace = $this->resolveNamespace();
if (! $namespace instanceof Node) {
return [];
}
Expand Down
2 changes: 1 addition & 1 deletion rules/Php80/Rector/Class_/AnnotationToAttributeRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public function refactor(Node $node): ?Node
return null;
}

$uses = $this->useImportsResolver->resolveBareUsesForNode($node);
$uses = $this->useImportsResolver->resolveBareUses();

// 1. bare tags without annotation class, e.g. "@inject"
$genericAttributeGroups = $this->processGenericTags($phpDocInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public function refactor(Node $node): ?Node
return null;
}

$uses = $this->useImportsResolver->resolveBareUsesForNode($node);
$uses = $this->useImportsResolver->resolveBareUses();

$attributeGroups = $this->transformDoctrineAnnotationClassesToAttributeGroups($phpDocInfo, $uses);
if ($attributeGroups === []) {
Expand Down
2 changes: 1 addition & 1 deletion rules/Renaming/NodeManipulator/ClassRenamer.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ private function isValidClassNameChange(Name $name, Class_ $class, ClassReflecti

private function isValidUseImportChange(string $newName, UseUse $useUse): bool
{
$uses = $this->useImportsResolver->resolveForNode($useUse);
$uses = $this->useImportsResolver->resolve();
if ($uses === []) {
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion rules/TypeDeclaration/PHPStan/ObjectTypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function narrowToFullyQualifiedOrAliasedObjectType(
}
}

$uses = $this->useImportsResolver->resolveForNode($node);
$uses = $this->useImportsResolver->resolve();
if ($uses === []) {
if (! $this->reflectionProvider->hasClass($objectType->getClassName())) {
return new NonExistingObjectType($objectType->getClassName());
Expand Down

0 comments on commit 40a1f34

Please sign in to comment.