Skip to content

Commit

Permalink
Fix missing stmt on adding a new node (#6383)
Browse files Browse the repository at this point in the history
Co-authored-by: kaizen-ci <info@kaizen-ci.org>
  • Loading branch information
TomasVotruba and kaizen-ci authored May 7, 2021
1 parent 20f9bb7 commit b1b5f95
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 5 deletions.
26 changes: 22 additions & 4 deletions packages/PostRector/Collector/NodesToAddCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Rector\ChangesReporting\Collector\RectorChangeCollector;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PostRector\Contract\Collector\NodeCollectorInterface;

Expand All @@ -37,10 +38,19 @@ final class NodesToAddCollector implements NodeCollectorInterface
*/
private $rectorChangeCollector;

public function __construct(BetterNodeFinder $betterNodeFinder, RectorChangeCollector $rectorChangeCollector)
{
/**
* @var BetterStandardPrinter
*/
private $betterStandardPrinter;

public function __construct(
BetterNodeFinder $betterNodeFinder,
RectorChangeCollector $rectorChangeCollector,
BetterStandardPrinter $betterStandardPrinter
) {
$this->betterNodeFinder = $betterNodeFinder;
$this->rectorChangeCollector = $rectorChangeCollector;
$this->betterStandardPrinter = $betterStandardPrinter;
}

public function isActive(): bool
Expand Down Expand Up @@ -132,14 +142,22 @@ private function resolveNearestExpressionPosition(Node $node): string
return spl_object_hash($node);
}

$currentStmt = $node->getAttribute(AttributeKey::CURRENT_STATEMENT);
if ($currentStmt instanceof Stmt) {
return spl_object_hash($currentStmt);
}

$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
if ($parent instanceof Return_) {
return spl_object_hash($parent);
}

$foundNode = $this->betterNodeFinder->findParentTypes($node, [Expression::class, Stmt::class]);
if ($foundNode === null) {
$foundNode = $node;

if (! $foundNode instanceof Stmt) {
$printedNode = $this->betterStandardPrinter->print($node);
$errorMessage = sprintf('Could not find parent Stmt of "%s" node', $printedNode);
throw new ShouldNotHappenException($errorMessage);
}

return spl_object_hash($foundNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public function refactor(Node $node): ?Node
private function refactorArrayKeyFirst(FuncCall $funcCall): FuncCall
{
$array = $funcCall->args[0]->value;

$resetFuncCall = $this->nodeFactory->createFuncCall('reset', [$array]);
$this->addNodeBeforeNode($resetFuncCall, $funcCall);

Expand Down
2 changes: 1 addition & 1 deletion src/Rector/AbstractRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
AttributeKey::USE_NODES,
AttributeKey::SCOPE,
AttributeKey::RESOLVED_NAME,
AttributeKey::PARENT_NODE,
];

/**
Expand Down Expand Up @@ -350,7 +351,6 @@ final public function enterNode(Node $node)

// update parents relations
$this->connectParentNodes($node);

$this->mirrorAttributes($originalAttributes, $node);
}

Expand Down
33 changes: 33 additions & 0 deletions tests/Issues/CovariantTrioTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\Core\Tests\Issues;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class CovariantTrioTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/covariant_trio.php';
}
}
33 changes: 33 additions & 0 deletions tests/Issues/Fixture/coariant_mixture.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Core\Tests\Issues\Fixture;

final class CoriantMixture
{
private function parseArgument(string $token, array $all)
{
if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) {
}
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\Fixture;

final class CoriantMixture
{
/**
* @param string $token
*/
private function parseArgument($token, array $all)
{
reset($all);
if (($inputArgument = isset($all[$key = key($all)]) ? $all[$key = key($all)] : null) && 'command' === $inputArgument->getName()) {
}
}
}

?>
94 changes: 94 additions & 0 deletions tests/Issues/Fixture/input_interface.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

class ArgvInput extends Input
{
/**
* Parses an argument.
*
* @throws RuntimeException When too many arguments are given
*/
private function parseArgument(string $token, array $all)
{
if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) {
}
}

/**
* {@inheritdoc}
*/
public function hasParameterOption($values, bool $onlyParams = false)
{
}
}

abstract class Input implements InputInterface
{

}

class ArrayInput extends Input
{
public function hasParameterOption($values, bool $onlyParams = false)
{

}
}

interface InputInterface
{
public function hasParameterOption($values, bool $onlyParams = false);
}

?>
-----
<?php

class ArgvInput extends Input
{
/**
* Parses an argument.
*
* @throws RuntimeException When too many arguments are given
* @param string $token
*/
private function parseArgument($token, array $all)
{
reset($all);
if (($inputArgument = isset($all[$key = key($all)]) ? $all[$key = key($all)] : null) && 'command' === $inputArgument->getName()) {
}
}

/**
* {@inheritdoc}
* @param bool $onlyParams
*/
public function hasParameterOption($values, $onlyParams = false)
{
}
}

abstract class Input implements InputInterface
{

}

class ArrayInput extends Input
{
/**
* @param bool $onlyParams
*/
public function hasParameterOption($values, $onlyParams = false)
{

}
}

interface InputInterface
{
/**
* @param bool $onlyParams
*/
public function hasParameterOption($values, $onlyParams = false);
}

?>
20 changes: 20 additions & 0 deletions tests/Issues/config/covariant_trio.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\DowngradePhp70\Rector\Coalesce\DowngradeNullCoalesceRector;
use Rector\DowngradePhp70\Rector\FunctionLike\DowngradeTypeDeclarationRector;
use Rector\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_70);

$services = $containerConfigurator->services();
$services->set(DowngradeArrayKeyFirstLastRector::class);
$services->set(DowngradeTypeDeclarationRector::class);
$services->set(DowngradeNullCoalesceRector::class);
};

0 comments on commit b1b5f95

Please sign in to comment.