Skip to content

Commit

Permalink
use BetterNodeFinder over attribute approach; current node tree is mo…
Browse files Browse the repository at this point in the history
…re reliable and will update after node refresh
  • Loading branch information
TomasVotruba committed Nov 6, 2021
1 parent cdcc69f commit 0032e1f
Show file tree
Hide file tree
Showing 80 changed files with 217 additions and 247 deletions.
2 changes: 0 additions & 2 deletions .phpstorm.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
\PhpParser\Node::getAttribute(),
0,
\Rector\NodeTypeResolver\Node\AttributeKey::SCOPE,
\Rector\NodeTypeResolver\Node\AttributeKey::CLASS_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::CLASS_NAME,
\Rector\NodeTypeResolver\Node\AttributeKey::METHOD_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE,
Expand All @@ -73,7 +72,6 @@
\PhpParser\Node::setAttribute(),
0,
\Rector\NodeTypeResolver\Node\AttributeKey::SCOPE,
\Rector\NodeTypeResolver\Node\AttributeKey::CLASS_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::CLASS_NAME,
\Rector\NodeTypeResolver\Node\AttributeKey::METHOD_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE,
Expand Down
2 changes: 1 addition & 1 deletion build/target-repository/docs/how_it_works.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ foreach ($fileInfos as $fileInfo) {
### 2.1 Prepare Phase

- Files are parsed by [`nikic/php-parser`](https://github.com/nikic/PHP-Parser), 4.0 that supports writing modified tree back to a file
- Then nodes (array of objects by parser) are traversed by `StandaloneTraverseNodeTraverser` to prepare their metadata, e.g. the class name, the method node the node is in, the namespace name etc. added by `$node->setAttribute(Attribute::CLASS_NODE, 'value')`.
- Then nodes (array of objects by parser) are traversed by `StandaloneTraverseNodeTraverser` to prepare their metadata, e.g. the class name, the method node the node is in, the namespace name etc. added by `$node->setAttribute('key', 'value')`.

### 2.2 Rectify Phase

Expand Down
9 changes: 9 additions & 0 deletions packages/NodeTypeResolver/Node/AttributeKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Rector\NodeTypeResolver\Node;

use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Symplify\SmartFileSystem\SmartFileInfo;

/**
Expand All @@ -28,11 +30,18 @@ final class AttributeKey
public const USE_NODES = 'useNodes';

/**
* @deprecated Use
* @see BetterNodeFinder and
* @see NodeNameResolver to find your parent nodes.
*
* @var string
*/
public const CLASS_NAME = 'className';

/**
* @deprecated Use
* @see BetterNodeFinder to find your parent nodes.
*
* @var string
*/
public const CLASS_NODE = 'class_node';
Expand Down
8 changes: 5 additions & 3 deletions packages/NodeTypeResolver/NodeTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use PHPStan\Type\UnionType;
use Rector\Core\Configuration\RenamedClassesDataCollector;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector;
Expand Down Expand Up @@ -71,6 +72,7 @@ public function __construct(
private AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector,
private IdentifierTypeResolver $identifierTypeResolver,
private RenamedClassesDataCollector $renamedClassesDataCollector,
private BetterNodeFinder $betterNodeFinder,
array $nodeTypeResolvers
) {
foreach ($nodeTypeResolvers as $nodeTypeResolver) {
Expand Down Expand Up @@ -324,12 +326,12 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType
return $this->isObjectType($node->class, $objectType);
}

$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
if (! $classLike instanceof Class_) {
$class = $this->betterNodeFinder->findParentType($node, Class_::class);
if (! $class instanceof Class_) {
return false;
}

return $this->isObjectType($classLike, $objectType);
return $this->isObjectType($class, $objectType);
}

private function isUnionTypeable(Type $first, Type $second): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\Type;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Symfony\Contracts\Service\Attribute\Required;

final class ClassMethodOrClassConstTypeResolver implements NodeTypeResolverInterface
{
private NodeTypeResolver $nodeTypeResolver;

public function __construct(
private BetterNodeFinder $betterNodeFinder
) {
}

#[Required]
public function autowireClassMethodOrClassConstTypeResolver(NodeTypeResolver $nodeTypeResolver): void
{
Expand All @@ -39,7 +44,7 @@ public function getNodeClasses(): array
*/
public function resolve(Node $node): Type
{
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
if (! $classLike instanceof ClassLike) {
// anonymous class
return new ObjectWithoutClassType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand All @@ -27,7 +29,8 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface

public function __construct(
private NodeNameResolver $nodeNameResolver,
private ReflectionProvider $reflectionProvider
private ReflectionProvider $reflectionProvider,
private BetterNodeFinder $betterNodeFinder
) {
}

Expand Down Expand Up @@ -59,10 +62,11 @@ public function resolve(Node $node): Type
/** @var Scope|null $scope */
$scope = $node->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
$classNode = $node->getAttribute(AttributeKey::CLASS_NODE);
$class = $this->betterNodeFinder->findParentType($node, Class_::class);

// fallback to class, since property fetches are not scoped by PHPStan
if ($classNode instanceof ClassLike) {
$scope = $classNode->getAttribute(AttributeKey::SCOPE);
if ($class instanceof ClassLike) {
$scope = $class->getAttribute(AttributeKey::SCOPE);
}

if (! $scope instanceof Scope) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ private function processClass(Node $node): void
$this->setClassNodeAndName($node);
}

$node->setAttribute(AttributeKey::CLASS_NODE, $this->classLike);
$node->setAttribute(AttributeKey::CLASS_NAME, $this->className);
}

Expand Down
13 changes: 6 additions & 7 deletions packages/NodeTypeResolver/TypeAnalyzer/ArrayTypeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
use PHPStan\Type\Accessory\HasOffsetType;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\ArrayType;
Expand All @@ -19,8 +18,8 @@
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\PregMatchTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeResolver;

Expand All @@ -29,7 +28,8 @@ final class ArrayTypeAnalyzer
public function __construct(
private NodeNameResolver $nodeNameResolver,
private NodeTypeResolver $nodeTypeResolver,
private PregMatchTypeCorrector $pregMatchTypeCorrector
private PregMatchTypeCorrector $pregMatchTypeCorrector,
private BetterNodeFinder $betterNodeFinder,
) {
}

Expand Down Expand Up @@ -96,13 +96,12 @@ private function isPropertyFetchWithArrayDefault(Node $node): bool
return false;
}

/** @var Class_|Trait_|Interface_|null $classLike */
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
if ($classLike instanceof Interface_) {
return false;
}

if ($classLike === null) {
if (! $classLike instanceof ClassLike) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\ReadWrite\Contract\ReadNodeAnalyzerInterface;

final class LocalPropertyFetchReadNodeAnalyzer implements ReadNodeAnalyzerInterface
{
public function __construct(
private JustReadExprAnalyzer $justReadExprAnalyzer,
private PropertyFetchFinder $propertyFetchFinder,
private NodeNameResolver $nodeNameResolver
private NodeNameResolver $nodeNameResolver,
private BetterNodeFinder $betterNodeFinder
) {
}

Expand All @@ -32,7 +33,7 @@ public function supports(Node $node): bool
*/
public function isRead(Node $node): bool
{
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
$class = $this->betterNodeFinder->findParentType($node, Class_::class);
if (! $class instanceof Class_) {
// assume worse to keep node protected
return true;
Expand Down
14 changes: 10 additions & 4 deletions packages/StaticTypeMapper/Naming/NameScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\StaticTypeMapper\StaticTypeMapper;
use Symfony\Contracts\Service\Attribute\Required;
Expand All @@ -27,15 +28,19 @@ final class NameScopeFactory

private PhpDocInfoFactory $phpDocInfoFactory;

private BetterNodeFinder $betterNodeFinder;

// This is needed to avoid circular references

#[Required]
public function autowireNameScopeFactory(
PhpDocInfoFactory $phpDocInfoFactory,
StaticTypeMapper $staticTypeMapper
StaticTypeMapper $staticTypeMapper,
BetterNodeFinder $betterNodeFinder,
): void {
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->staticTypeMapper = $staticTypeMapper;
$this->betterNodeFinder = $betterNodeFinder;
}

public function createNameScopeFromNodeWithoutTemplateTypes(Node $node): NameScope
Expand Down Expand Up @@ -104,10 +109,11 @@ private function templateTemplateTypeMap(Node $node): TemplateTypeMap
{
$nodeTemplateTypes = $this->resolveTemplateTypesFromNode($node);

$class = $node->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);

$classTemplateTypes = [];
if ($class instanceof ClassLike) {
$classTemplateTypes = $this->resolveTemplateTypesFromNode($class);
if ($classLike instanceof ClassLike) {
$classTemplateTypes = $this->resolveTemplateTypesFromNode($classLike);
}

$templateTypes = array_merge($nodeTemplateTypes, $classTemplateTypes);
Expand Down

This file was deleted.

3 changes: 1 addition & 2 deletions rules/Arguments/Rector/ClassMethod/ArgumentAdderRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use Rector\Core\Enum\ObjectReference;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
Expand Down Expand Up @@ -152,7 +151,7 @@ private function isObjectTypeMatch(MethodCall | StaticCall | ClassMethod $node,

// ClassMethod
/** @var Class_|null $classLike */
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($node, Class_::class);

// anonymous class
if (! $classLike instanceof Class_) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use PHPStan\Type\Type;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Type\StaticTypeAnalyzer;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand Down Expand Up @@ -170,7 +169,7 @@ private function matchTruableIf(Expr|Stmt $node): If_|null

private function resolvePropertyFetchType(PropertyFetch $propertyFetch): Type
{
$classLike = $propertyFetch->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($propertyFetch, Class_::class);
if (! $classLike instanceof Class_) {
return new MixedType();
}
Expand Down
3 changes: 1 addition & 2 deletions rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

Expand Down Expand Up @@ -62,7 +61,7 @@ public function getNodeTypes(): array
*/
public function refactor(Node $node): ?Node
{
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
$class = $this->betterNodeFinder->findParentType($node, Class_::class);
if (! $class instanceof Class_) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ private function isConstructorWithStaticFactory(ClassMethod $classMethod, string
return false;
}

$classLike = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
$classLike = $this->betterNodeFinder->findParentType($classMethod, Class_::class);
$classLike = $this->betterNodeFinder->findParentType($classMethod, Class_::class);
if (! $classLike instanceof Class_) {
return false;
}
Expand Down
Loading

0 comments on commit 0032e1f

Please sign in to comment.