Skip to content

Commit

Permalink
[Php74] Add ParenthesizeNestedTernaryRector (#2859)
Browse files Browse the repository at this point in the history
* [Php74] Add ParenthesizeNestedTernaryRector

* phpstan

* [ci-review] Rector Rectify

* verify from parent

* different fixture files for detection

* phpstan

* more explanation

* more explanation

* rename fixture

* more explanation

* clean up comment

* regenerate docs

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Aug 31, 2022
1 parent 86ccf3f commit 6db4c0e
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 2 deletions.
17 changes: 15 additions & 2 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 400 Rules Overview
# 401 Rules Overview

<br>

Expand Down Expand Up @@ -44,7 +44,7 @@

- [Php73](#php73) (9)

- [Php74](#php74) (14)
- [Php74](#php74) (15)

- [Php80](#php80) (19)

Expand Down Expand Up @@ -5694,6 +5694,19 @@ Use null coalescing operator ??=

<br>

### ParenthesizeNestedTernaryRector

Add parentheses to nested ternary

- class: [`Rector\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector`](../rules/Php74/Rector/Ternary/ParenthesizeNestedTernaryRector.php)

```diff
-$value = $a ? $b : $a ?: null;
+$value = ($a ? $b : $a) ?: null;
```

<br>

### RealToFloatTypeCastRector

Change deprecated (real) to (float)
Expand Down
3 changes: 3 additions & 0 deletions config/set/php74.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
Expand Down Expand Up @@ -58,4 +59,6 @@
$rectorConfig->rule(CurlyToSquareBracketArrayStringRector::class);

$rectorConfig->rule(MoneyFormatToNumberFormatRector::class);

$rectorConfig->rule(ParenthesizeNestedTernaryRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function nestedTernaryNoParentheses()
{
$a = 1;
$b = 2;
$c = 3;

$value = $a ? $b : $a ?: null;
$value = $a ? $b : $a ? $c : null;
}

?>
-----
<?php

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function nestedTernaryNoParentheses()
{
$a = 1;
$b = 2;
$c = 3;

$value = ($a ? $b : $a) ?: null;
$value = ($a ? $b : $a) ? $c : null;
}

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

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function SkipNestedTernaryParenthesized()
{
$a = 1;
$b = 2;

$value = ($a ? $b : $a) ?: null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function SkipNestedTernaryParenthesizedElse()
{
1 ? 2 : (3 ? 4 : 5);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function SkipNestedTernaryParenthesizedIf()
{
(1 ? 2 : 3) ? 4 : 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\Fixture;

function skipNotNestedTernary()
{
$a = 1;
$b = 2;

$value = $a ? $b : $a;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector;

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

final class ParenthesizeNestedTernaryRectorTest 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/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(ParenthesizeNestedTernaryRector::class);
};
77 changes: 77 additions & 0 deletions rules/Php74/Rector/Ternary/ParenthesizeNestedTernaryRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace Rector\Php74\Rector\Ternary;

use PhpParser\Node;
use PhpParser\Node\Expr\Ternary;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php74\Tokenizer\ParenthesizedNestedTernaryAnalyzer;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://www.php.net/manual/en/migration74.deprecated.php
* @changelog https://3v4l.org/vhdlJ
* @see \Rector\Tests\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector\ParenthesizeNestedTernaryRectorTest
*/
final class ParenthesizeNestedTernaryRector extends AbstractRector implements MinPhpVersionInterface
{
public function __construct(private readonly ParenthesizedNestedTernaryAnalyzer $parenthesizedNestedTernaryAnalyzer)
{
}

public function provideMinPhpVersion(): int
{
return PhpVersionFeature::DEPRECATE_NESTED_TERNARY;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Add parentheses to nested ternary',
[
new CodeSample(
<<<'CODE_SAMPLE'
$value = $a ? $b : $a ?: null;
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$value = ($a ? $b : $a) ?: null;
CODE_SAMPLE
),
]
);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Ternary::class];
}

/**
* @param Ternary $node
*/
public function refactor(Node $node): ?Node
{
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);

if (! $parentNode instanceof Ternary) {
return null;
}

if ($this->parenthesizedNestedTernaryAnalyzer->isParenthesized($this->file, $parentNode)) {
return null;
}

$node->setAttribute(AttributeKey::ORIGINAL_NODE, null);
return $node;
}
}
19 changes: 19 additions & 0 deletions rules/Php74/Tokenizer/ParenthesizedNestedTernaryAnalyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Rector\Php74\Tokenizer;

use PhpParser\Node\Expr\Ternary;
use Rector\Core\ValueObject\Application\File;

final class ParenthesizedNestedTernaryAnalyzer
{
public function isParenthesized(File $file, Ternary $ternary): bool
{
$oldTokens = $file->getOldTokens();
$startTokenPos = $ternary->getStartTokenPos();

return isset($oldTokens[$startTokenPos]) && $oldTokens[$startTokenPos] === '(';
}
}
5 changes: 5 additions & 0 deletions src/ValueObject/PhpVersionFeature.php
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ final class PhpVersionFeature
*/
public const EXPORT_TO_REFLECTION_FUNCTION = PhpVersion::PHP_74;

/**
* @var int
*/
public const DEPRECATE_NESTED_TERNARY = PhpVersion::PHP_74;

/**
* @var int
*/
Expand Down

0 comments on commit 6db4c0e

Please sign in to comment.