diff --git a/phpstan.neon b/phpstan.neon index 0258b5d11d2..cf4cabbb2af 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -265,6 +265,11 @@ parameters: # see https://github.com/rectorphp/rector-src/actions/runs/11798721617/job/32865546672?pr=6422#step:5:110 - '#Doing instanceof PHPStan\\Type\\.+ is error\-prone and deprecated#' + # BC layer on Rector deprecation + - + path: src/Configuration/RectorConfigBuilder.php + identifier: classConstant.deprecatedInterface + # allowed internally only - message: '#Fetching (deprecated )?class constant (.*?) of (deprecated )?class (Rector\\Set\\ValueObject\\DowngradeLevelSetList|Rector\\Symfony\\Set\\(.*?))#' diff --git a/src/Configuration/RectorConfigBuilder.php b/src/Configuration/RectorConfigBuilder.php index 974356973ec..730eb13d6c1 100644 --- a/src/Configuration/RectorConfigBuilder.php +++ b/src/Configuration/RectorConfigBuilder.php @@ -4,6 +4,7 @@ namespace Rector\Configuration; +use PhpParser\NodeVisitor; use Rector\Bridge\SetProviderCollector; use Rector\Bridge\SetRectorsResolver; use Rector\Caching\Contract\ValueObject\Storage\CacheStorageInterface; @@ -18,11 +19,13 @@ use Rector\Configuration\Levels\LevelRulesResolver; use Rector\Configuration\Parameter\SimpleParameterProvider; use Rector\Console\Notifier; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Contract\Rector\RectorInterface; use Rector\Doctrine\Set\DoctrineSetList; use Rector\Enum\Config\Defaults; use Rector\Exception\Configuration\InvalidConfigurationException; +use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver; use Rector\Php80\Rector\Class_\AnnotationToAttributeRector; use Rector\Php80\ValueObject\AnnotationToAttribute; @@ -1217,11 +1220,33 @@ public function withTreatClassesAsFinal(bool $isTreatClassesAsFinal = true): sel public function registerService(string $className, ?string $alias = null, ?string $tag = null): self { + // BC layer since 2.2.9 + if ($tag === ScopeResolverNodeVisitorInterface::class) { + $tag = DecoratingNodeVisitorInterface::class; + } + $this->registerServices[] = new RegisteredService($className, $alias, $tag); return $this; } + /** + * DX helper + * @see https://getrector.com/documentation/creating-a-node-visitor + */ + public function registerDecoratingNodeVisitor(string $decoratingNodeVisitorClass): self + { + Assert::isAOf($decoratingNodeVisitorClass, NodeVisitor::class); + + $this->registerServices[] = new RegisteredService( + $decoratingNodeVisitorClass, + null, + DecoratingNodeVisitorInterface::class + ); + + return $this; + } + public function withDowngradeSets( bool $php84 = false, bool $php83 = false, diff --git a/src/Contract/PhpParser/DecoratingNodeVisitorInterface.php b/src/Contract/PhpParser/DecoratingNodeVisitorInterface.php new file mode 100644 index 00000000000..5a8ee5704ee --- /dev/null +++ b/src/Contract/PhpParser/DecoratingNodeVisitorInterface.php @@ -0,0 +1,16 @@ +> + * @var array> */ - private const SCOPE_RESOLVER_NODE_VISITOR_CLASSES = [ + private const DECORATING_NODE_VISITOR_CLASSES = [ ArgNodeVisitor::class, AssignedToNodeVisitor::class, ByRefReturnNodeVisitor::class, @@ -660,13 +660,13 @@ static function ( ); $rectorConfig->when(PHPStanNodeScopeResolver::class) - ->needs('$nodeVisitors') - ->giveTagged(ScopeResolverNodeVisitorInterface::class); + ->needs('$decoratingNodeVisitors') + ->giveTagged(DecoratingNodeVisitorInterface::class); $this->registerTagged( $rectorConfig, - self::SCOPE_RESOLVER_NODE_VISITOR_CLASSES, - ScopeResolverNodeVisitorInterface::class + self::DECORATING_NODE_VISITOR_CLASSES, + DecoratingNodeVisitorInterface::class ); $this->createPHPStanServices($rectorConfig); diff --git a/src/NodeTypeResolver/PHPStan/Scope/Contract/NodeVisitor/ScopeResolverNodeVisitorInterface.php b/src/NodeTypeResolver/PHPStan/Scope/Contract/NodeVisitor/ScopeResolverNodeVisitorInterface.php index 560440bc2e1..df374f9627e 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/Contract/NodeVisitor/ScopeResolverNodeVisitorInterface.php +++ b/src/NodeTypeResolver/PHPStan/Scope/Contract/NodeVisitor/ScopeResolverNodeVisitorInterface.php @@ -6,6 +6,9 @@ use PhpParser\NodeVisitor; +/** + * @deprecated Since 2.2.9. Use \Rector\Contract\PhpParser\DecoratingNodeVisitorInterface instead + */ interface ScopeResolverNodeVisitorInterface extends NodeVisitor { } diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php index 831b2e3f78d..a970e8bcf19 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php @@ -11,10 +11,10 @@ use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; -final class ArgNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class ArgNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function enterNode(Node $node): ?Node { diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.php index a501c2ca1e8..6bab84300a7 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.php @@ -11,13 +11,13 @@ use PhpParser\Node\Expr\AssignRef; use PhpParser\Node\Expr\List_; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; /** * Inspired by https://github.com/phpstan/phpstan-src/blob/1.7.x/src/Parser/NewAssignedToPropertyVisitor.php */ -final class AssignedToNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class AssignedToNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function enterNode(Node $node): ?Node { diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php index 1b182a6aad9..6950ee01d2f 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php @@ -10,11 +10,11 @@ use PhpParser\Node\Stmt\Return_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; -final class ByRefReturnNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class ByRefReturnNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function __construct( private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php index 335feffd4cc..1ebe2f2747f 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php @@ -11,11 +11,11 @@ use PhpParser\Node\Expr\Variable; use PhpParser\Node\FunctionLike; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; -final class ByRefVariableNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class ByRefVariableNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function __construct( private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.php index a798e3a3d9b..50dff6b611b 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.php @@ -34,11 +34,11 @@ use PhpParser\Node\Stmt\While_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; -final class ContextNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class ContextNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function __construct( private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php index 1e3c096b2f3..b6f4d03e7ef 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php @@ -12,12 +12,12 @@ use PhpParser\Node\Stmt\Global_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; -final class GlobalVariableNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class GlobalVariableNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function __construct( private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/NameNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/NameNodeVisitor.php index cd5461a87cd..3ef20792238 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/NameNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/NameNodeVisitor.php @@ -11,10 +11,10 @@ use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; -final class NameNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class NameNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function enterNode(Node $node): ?Node { diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php index fa3556bf986..2986a40ebb0 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php @@ -12,12 +12,12 @@ use PhpParser\Node\Stmt\Static_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; -final class StaticVariableNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface +final class StaticVariableNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface { public function __construct( private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser diff --git a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php index 895b1efe969..4ae80808728 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php +++ b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php @@ -102,10 +102,10 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\ObjectType; use PHPStan\Type\TypeCombinator; +use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface; use Rector\NodeAnalyzer\ClassAnalyzer; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpParser\Node\CustomNode\FileWithoutNamespace; use Rector\Util\Reflection\PrivatesAccessor; use Webmozart\Assert\Assert; @@ -124,18 +124,19 @@ private NodeTraverser $nodeTraverser; /** - * @param ScopeResolverNodeVisitorInterface[] $nodeVisitors + * @param DecoratingNodeVisitorInterface[] $decoratingNodeVisitors */ public function __construct( private NodeScopeResolver $nodeScopeResolver, private ReflectionProvider $reflectionProvider, - iterable $nodeVisitors, + iterable $decoratingNodeVisitors, private ScopeFactory $scopeFactory, private PrivatesAccessor $privatesAccessor, private NodeNameResolver $nodeNameResolver, private ClassAnalyzer $classAnalyzer ) { - $this->nodeTraverser = new NodeTraverser(...$nodeVisitors); + // @todo make use of immutable, to avoid tedious traversing + $this->nodeTraverser = new NodeTraverser(...$decoratingNodeVisitors); } /**