Skip to content

Commit

Permalink
[Arguments] Handle by pass 2nd argument default value on ArgumentAdde…
Browse files Browse the repository at this point in the history
…rRector (#1946)

* [Arguments] Handle by pass 2nd argument on ArgumentAdderRector

* [Arguments] Handle by pass 2nd argument on ArgumentAdderRector

* Fixed 🎉
  • Loading branch information
samsonasik committed Mar 18, 2022
1 parent dd842d6 commit 2d3419b
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Fixture;

use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeMultiArg;

class ByPass2ndArgValue
{
public function run()
{
$containerBuilder = new SomeMultiArg();
$containerBuilder->run(1);
}
}

?>
-----
<?php

namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Fixture;

use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeMultiArg;

class ByPass2ndArgValue
{
public function run()
{
$containerBuilder = new SomeMultiArg();
$containerBuilder->run(1, 2, 4);
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source;

class SomeMultiArg
{
public function run($a = 1, $b = 2, $c = 3)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rector\Arguments\ValueObject\ArgumentAdder;
use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeClass;
use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeContainerBuilder;
use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeMultiArg;
use Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\Source\SomeParentClient;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

Expand Down Expand Up @@ -52,5 +53,6 @@
ArgumentAddingScope::SCOPE_CLASS_METHOD
),
new ArgumentAdder(SomeClass::class, 'withoutTypeOrDefaultValue', 0, 'arguments', [], $arrayType),
new ArgumentAdder(SomeMultiArg::class, 'run', 2, 'c', 4),
]);
};
60 changes: 52 additions & 8 deletions rules/Arguments/Rector/ClassMethod/ArgumentAdderRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use PhpParser\BuilderHelpers;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
Expand All @@ -22,6 +24,7 @@
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
Expand All @@ -42,7 +45,8 @@ final class ArgumentAdderRector extends AbstractRector implements ConfigurableRe

public function __construct(
private readonly ArgumentAddingScope $argumentAddingScope,
private readonly ChangedArgumentsDetector $changedArgumentsDetector
private readonly ChangedArgumentsDetector $changedArgumentsDetector,
private readonly AstResolver $astResolver
) {
}

Expand Down Expand Up @@ -162,16 +166,54 @@ private function processPositionWithDefaultValues(

if ($node instanceof ClassMethod) {
$this->addClassMethodParam($node, $argumentAdder, $defaultValue, $argumentType, $position);
} elseif ($node instanceof StaticCall) {
return;
}

if ($node instanceof StaticCall) {
$this->processStaticCall($node, $position, $argumentAdder);
} else {
$arg = new Arg(BuilderHelpers::normalizeValue($defaultValue));
if (isset($node->args[$position])) {
return;
return;
}

$this->processMethodCall($node, $defaultValue, $position);
}

private function processMethodCall(MethodCall $methodCall, mixed $defaultValue, int $position): void
{
$arg = new Arg(BuilderHelpers::normalizeValue($defaultValue));
if (isset($methodCall->args[$position])) {
return;
}

$this->fillGapBetweenWithDefaultValue($methodCall, $position);

$methodCall->args[$position] = $arg;
$this->haveArgumentsChanged = true;
}

private function fillGapBetweenWithDefaultValue(MethodCall | StaticCall $node, int $position): void
{
$lastPosition = count($node->getArgs()) - 1;

if ($position <= $lastPosition) {
return;
}

if ($position - $lastPosition === 1) {
return;
}

$classMethod = $this->astResolver->resolveClassMethodFromCall($node);
if (! $classMethod instanceof ClassMethod) {
return;
}

for ($index = $lastPosition + 1; $index < $position; ++$index) {
$param = $classMethod->params[$index];
if (! $param->default instanceof Expr) {
throw new ShouldNotHappenException('Previous position does not has default value');
}

$node->args[$position] = $arg;
$this->haveArgumentsChanged = true;
$node->args[$index] = new Arg(new ConstFetch(new Name($this->print($param->default))));
}
}

Expand Down Expand Up @@ -255,6 +297,8 @@ private function processStaticCall(StaticCall $staticCall, int $position, Argume
return;
}

$this->fillGapBetweenWithDefaultValue($staticCall, $position);

$staticCall->args[$position] = new Arg(new Variable($argumentName));
$this->haveArgumentsChanged = true;
}
Expand Down

0 comments on commit 2d3419b

Please sign in to comment.