Skip to content

Commit

Permalink
[CodeQuality] Add TernaryEmptyArrayArrayDimFetchToCoalesceRector (#3027)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Nov 1, 2022
1 parent 7b7d5a4 commit 9e4a9c0
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 2 deletions.
25 changes: 23 additions & 2 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# 399 Rules Overview
# 400 Rules Overview

<br>

## Categories

- [Arguments](#arguments) (5)

- [CodeQuality](#codequality) (76)
- [CodeQuality](#codequality) (77)

- [CodingStyle](#codingstyle) (36)

Expand Down Expand Up @@ -1640,6 +1640,27 @@ Switch negated ternary condition rector

<br>

### TernaryEmptyArrayArrayDimFetchToCoalesceRector

Change ternary empty on array property with array dim fetch to coalesce operator

- class: [`Rector\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector`](../rules/CodeQuality/Rector/Ternary/TernaryEmptyArrayArrayDimFetchToCoalesceRector.php)

```diff
final class SomeClass
{
private array $items = [];

public function run()
{
- return ! empty($this->items) ? $this->items[0] : 'default';
+ return $this->items[0] ?? 'default';
}
}
```

<br>

### TernaryFalseExpressionToIfRector

Change ternary with false to if and explicit call
Expand Down
3 changes: 3 additions & 0 deletions config/set/code-quality.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Rector\CodeQuality\Rector\Array_\CallableThisArrayToAnonymousFunctionRector;

use Rector\CodeQuality\Rector\Assign\CombinedAssignRector;
use Rector\CodeQuality\Rector\Assign\SplitListAssignToSeparateLineRector;
use Rector\CodeQuality\Rector\BooleanAnd\SimplifyEmptyArrayCheckRector;
Expand Down Expand Up @@ -75,6 +76,7 @@
use Rector\CodeQuality\Rector\Ternary\ArrayKeyExistsTernaryThenValueToCoalescingRector;
use Rector\CodeQuality\Rector\Ternary\SimplifyTautologyTernaryRector;
use Rector\CodeQuality\Rector\Ternary\SwitchNegatedTernaryRector;
use Rector\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector;
use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector;
use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector;
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector;
Expand Down Expand Up @@ -193,4 +195,5 @@
SimplifyIfExactValueReturnValueRector::class,
SimplifyUselessLastVariableAssignRector::class,
]);
$rectorConfig->rule(TernaryEmptyArrayArrayDimFetchToCoalesceRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector\Fixture;

final class SkipNonArray
{
private $items;

public function run()
{
return ! empty($this->items) ? $this->items[0] : 'default';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector\Fixture;

final class SkipOnlyEmpty
{
private array $items = [];

public function run()
{
return empty($this->items) ? $this->items[0] : 'default';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector\Fixture;

final class SomeClass
{
private array $items = [];

public function run()
{
return ! empty($this->items) ? $this->items[0] : 'default';
}
}

?>
-----
<?php

namespace Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector\Fixture;

final class SomeClass
{
private array $items = [];

public function run()
{
return $this->items[0] ?? 'default';
}
}

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

declare(strict_types=1);

namespace Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class TernaryEmptyArrayArrayDimFetchToCoalesceRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

/**
* @return Iterator<string>
*/
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,11 @@
<?php

declare(strict_types=1);

use Rector\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector;

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(TernaryEmptyArrayArrayDimFetchToCoalesceRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace Rector\CodeQuality\Rector\Ternary;

use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Empty_;
use PhpParser\Node\Expr\Ternary;
use PHPStan\Type\ArrayType;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Tests\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector\TernaryEmptyArrayArrayDimFetchToCoalesceRectorTest
*/
final class TernaryEmptyArrayArrayDimFetchToCoalesceRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change ternary empty on array property with array dim fetch to coalesce operator', [
new CodeSample(
<<<'CODE_SAMPLE'
final class SomeClass
{
private array $items = [];
public function run()
{
return ! empty($this->items) ? $this->items[0] : 'default';
}
}
CODE_SAMPLE

,
<<<'CODE_SAMPLE'
final class SomeClass
{
private array $items = [];
public function run()
{
return $this->items[0] ?? 'default';
}
}
CODE_SAMPLE
),
]);
}

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

/**
* @param Ternary $node
*/
public function refactor(Node $node): ?Node
{
if (! $node->cond instanceof BooleanNot) {
return null;
}

$negagedExpr = $node->cond->expr;
if (! $negagedExpr instanceof Empty_) {
return null;
}

$emptyExprType = $this->getType($negagedExpr->expr);
if (! $emptyExprType instanceof ArrayType) {
return null;
}

if (! $node->if instanceof ArrayDimFetch) {
return null;
}

$dimFetchVar = $node->if->var;
if (! $this->nodeComparator->areNodesEqual($negagedExpr->expr, $dimFetchVar)) {
return null;
}

return new Coalesce($node->if, $node->else);
}
}

0 comments on commit 9e4a9c0

Please sign in to comment.