Skip to content

Commit

Permalink
fix isSubmitted() previous calls for FormIsValidRector
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Oct 2, 2019
1 parent f3783ac commit 0062079
Showing 1 changed file with 92 additions and 13 deletions.
105 changes: 92 additions & 13 deletions packages/Symfony/src/Rector/Form/FormIsValidRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
Expand Down Expand Up @@ -49,25 +50,20 @@ public function getNodeTypes(): array
*/
public function refactor(Node $node): ?Node
{
// skip just added calls
if ($node->getAttribute(AttributeKey::ORIGINAL_NODE) === null) {
if ($this->shouldSkipMethodCall($node)) {
return null;
}

if (! $this->isObjectType($node, Form::class)) {
return null;
}
/** @var Variable $variable */
$variable = $node->var;

if (! $this->isName($node, 'isValid')) {
return null;
}
/** @var string $variableName */
$variableName = $this->getName($node->var);

if ($node->getAttribute(AttributeKey::PREVIOUS_NODE) !== null) {
return null;
}
$previousCalls = $this->findMethodCallNamesOnVariable($variable);

$variableName = $this->getName($node->var);
if ($variableName === null) {
// already checked by isSubmitted()
if (in_array('isSubmitted', $previousCalls, true)) {
return null;
}

Expand All @@ -76,4 +72,87 @@ public function refactor(Node $node): ?Node
$this->createMethodCall($variableName, 'isValid')
);
}

private function shouldSkipMethodCall(MethodCall $methodCall): bool
{
// skip just added calls
if ($methodCall->getAttribute(AttributeKey::ORIGINAL_NODE) === null) {
return true;
}

if (! $this->isObjectType($methodCall->var, Form::class)) {
return true;
}

if (! $this->isName($methodCall->name, 'isValid')) {
return true;
}

if ($methodCall->getAttribute(AttributeKey::PREVIOUS_NODE) !== null) {
return true;
}

$variableName = $this->getName($methodCall->var);
if ($variableName === null) {
return true;
}

return false;
}

/**
* @return string[]
*/
private function findMethodCallNamesOnVariable(Variable $variable): array
{
/** @var Node|null $parentNode */
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode === null) {
return [];
}

$variableName = $this->getName($variable);
if ($variableName === null) {
return [];
}

$previousMethodCallNames = [];

do {
$methodCallNames = $this->collectMethodCallsOnVariableName($parentNode, $variableName);
$previousMethodCallNames = array_merge($previousMethodCallNames, $methodCallNames);

$parentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
} while ($parentNode instanceof Node && ! $parentNode instanceof Node\FunctionLike);

return array_unique($previousMethodCallNames);
}

/**
* @return string[]
*/
private function collectMethodCallsOnVariableName(Node $node, string $variableName): array
{
$methodCallNames = [];
$this->traverseNodesWithCallable($node, function (Node $node) use ($variableName, &$methodCallNames) {
if (! $node instanceof MethodCall) {
return null;
}

if (! $this->isName($node->var, $variableName)) {
return null;
}

$methodName = $this->getName($node->name);
if ($methodName === null) {
return null;
}

$methodCallNames[] = $methodName;

return null;
});

return $methodCallNames;
}
}

0 comments on commit 0062079

Please sign in to comment.