Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Symfony] Fix is submitted #2076

Merged
merged 2 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ private function shouldSkip(string $lastName, string $aliasName): bool
}

/**
* @return string[]
* @return string[][]
*/
private function collectUseNamesAliasToName(Use_ $use): array
{
Expand Down
109 changes: 96 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,31 +50,113 @@ 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)) {
/** @var Variable $variable */
$variable = $node->var;
if ($this->isIsSubmittedByAlreadyCalledOnVariable($variable)) {
return null;
}

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

return new BooleanAnd(
$this->createMethodCall($variableName, 'isSubmitted'),
$this->createMethodCall($variableName, 'isValid')
);
}

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

if ($node->getAttribute(AttributeKey::PREVIOUS_NODE) !== null) {
return null;
if (! $this->isObjectType($methodCall->var, Form::class)) {
return true;
}

$variableName = $this->getName($node->var);
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 null;
return true;
}

return new BooleanAnd(
$this->createMethodCall($variableName, 'isSubmitted'),
$this->createMethodCall($variableName, 'isValid')
);
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;
}

private function isIsSubmittedByAlreadyCalledOnVariable(Variable $variable): bool
{
$previousMethodCallNamesOnVariable = $this->findMethodCallNamesOnVariable($variable);

// already checked by isSubmitted()
return in_array('isSubmitted', $previousMethodCallNamesOnVariable, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,3 @@ class SkipNegativeIfsController
}
}
}

?>
-----
<?php

namespace Rector\Symfony\Tests\Rector\Form\FormIsValidRector\Fixture;

use Symfony\Component\Form\Form;

class SkipNegativeIfsController
{
public function action()
{
$form = new Form();

if (!$form->isSubmitted() || !$form->isValid()) {
$this->doSomething();
}
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,3 @@ class SkipNestedIfsController
}
}
}

?>
-----
<?php

namespace Rector\Symfony\Tests\Rector\Form\FormIsValidRector\Fixture;

use Symfony\Component\Form\Form;

class SkipNestedIfsController
{
public function action()
{
$form = new Form();

if ($form->isSubmitted()) {
if ($form->isValid()) {
$this->processForm($form);
}
$this->doSomethingMore();
}
}
}

?>