Skip to content

Commit

Permalink
[Traverser] Add BreakingRemovalGuardNodeVisitor to reduce parent attr…
Browse files Browse the repository at this point in the history
…ibute usage on BreakingRemovalGuard (#3978)

* [Traverser] Add BreakingRemovalGuardNodeVisitor to reduce parent attribute usage on BreakingRemovalGuard

* child of

* flip

* add return

* fix phpstan

* [ci-review] Rector Rectify

* rename attrbiute

* fix phpstan

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Jun 4, 2023
1 parent 919c052 commit 02b9331
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 49 deletions.
53 changes: 4 additions & 49 deletions packages/NodeRemoval/BreakingRemovalGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
namespace Rector\NodeRemoval;

use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\While_;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;

Expand All @@ -23,17 +19,13 @@ public function ensureNodeCanBeRemove(Node $node): void
return;
}

// validate the node can be removed
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if (! $parentNode instanceof Node) {
throw new ShouldNotHappenException();
}

/** @var string $childOfNodeType */
$childOfNodeType = $node->getAttribute(AttributeKey::CHILD_OF_NODE_TYPE);
throw new ShouldNotHappenException(sprintf(
'Node "%s" on line %d is child of "%s", so it cannot be removed as it would break PHP code. Change or remove the parent node instead.',
$node::class,
$node->getLine(),
$parentNode::class
$childOfNodeType
));
}

Expand All @@ -42,43 +34,6 @@ public function ensureNodeCanBeRemove(Node $node): void
*/
public function isLegalNodeRemoval(Node $node): bool
{
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof If_ && $parentNode->cond === $node) {
return false;
}

if ($parentNode instanceof BooleanNot) {
$parentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
}

if ($parentNode instanceof Assign) {
return false;
}

if ($this->isIfCondition($node)) {
return false;
}

return ! $this->isWhileCondition($node);
}

private function isIfCondition(Node $node): bool
{
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if (! $parentNode instanceof If_) {
return false;
}

return $parentNode->cond === $node;
}

private function isWhileCondition(Node $node): bool
{
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if (! $parentNode instanceof While_) {
return false;
}

return $parentNode->cond === $node;
return $node->getAttribute(AttributeKey::IS_BREAKING_REMOVAL_NODE) !== true;
}
}
10 changes: 10 additions & 0 deletions packages/NodeTypeResolver/Node/AttributeKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,14 @@ final class AttributeKey
* @var string
*/
public const STMT_KEY = 'stmt_key';

/**
* @var string
*/
public const IS_BREAKING_REMOVAL_NODE = 'is_breaking_removal_node';

/**
* @var string
*/
public const CHILD_OF_NODE_TYPE = 'child_of_node_type';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;

use PhpParser\Node;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\While_;
use PhpParser\NodeVisitorAbstract;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface;

final class BreakingRemovalGuardNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface
{
public function enterNode(Node $node): ?Node
{
if ($node instanceof If_) {
$node->cond->setAttribute(AttributeKey::IS_BREAKING_REMOVAL_NODE, true);
$node->cond->setAttribute(AttributeKey::CHILD_OF_NODE_TYPE, If_::class);

return null;
}

if ($node instanceof BooleanNot) {
$node->expr->setAttribute(AttributeKey::IS_BREAKING_REMOVAL_NODE, true);
$node->expr->setAttribute(AttributeKey::CHILD_OF_NODE_TYPE, BooleanNot::class);

return null;
}

if ($node instanceof While_) {
$node->cond->setAttribute(AttributeKey::IS_BREAKING_REMOVAL_NODE, true);
$node->cond->setAttribute(AttributeKey::CHILD_OF_NODE_TYPE, While_::class);
}

return null;
}
}

0 comments on commit 02b9331

Please sign in to comment.