Skip to content

Commit c5fa47c

Browse files
author
Dmitriy Dymarchuk
authored
Find unnecessary ternary operators
1 parent 334898a commit c5fa47c

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

rules.neon

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ rules:
4141
- PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule
4242
- PHPStan\Rules\VariableVariables\VariableVariablesRule
4343

44+
conditionalTags:
45+
PHPStan\Rules\Operators\OperandsInTernaryOperatorRule:
46+
phpstan.rules.rule: %featureToggles.bleedingEdge%
47+
4448
services:
49+
-
50+
class: PHPStan\Rules\Operators\OperandsInTernaryOperatorRule
51+
4552
-
4653
class: PHPStan\Rules\BooleansInConditions\BooleanRuleHelper
4754

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Operators;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\Ternary;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Type\ConstantType;
10+
use PHPStan\Type\VerbosityLevel;
11+
12+
/**
13+
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\Expr\Ternary>
14+
*/
15+
class OperandsInTernaryOperatorRule implements Rule
16+
{
17+
18+
public function getNodeType(): string
19+
{
20+
return Ternary::class;
21+
}
22+
23+
public function processNode(Node $node, Scope $scope): array
24+
{
25+
$ifType = $node->if === null ? $scope->getType($node->cond) : $scope->getType($node->if);
26+
$elseType = $scope->getType($node->else);
27+
if ($ifType instanceof ConstantType && $elseType instanceof ConstantType) {
28+
if ($ifType->equals($elseType)) {
29+
return [sprintf(
30+
'If and else parts of ternary operator are equal (%s).',
31+
$ifType->describe(VerbosityLevel::value())
32+
)];
33+
}
34+
}
35+
36+
return [];
37+
}
38+
39+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Operators;
4+
5+
use PHPStan\Rules\Rule;
6+
7+
/**
8+
* @extends \PHPStan\Testing\RuleTestCase<OperandsInTernaryOperatorRule>
9+
*/
10+
class OperandsInTernaryOperatorRuleTest extends \PHPStan\Testing\RuleTestCase
11+
{
12+
13+
protected function getRule(): Rule
14+
{
15+
return new OperandsInTernaryOperatorRule();
16+
}
17+
18+
public function testRule(): void
19+
{
20+
$this->analyse([__DIR__ . '/data/operators.php'], [
21+
[
22+
'If and else parts of ternary operator are equal (true).',
23+
113,
24+
],
25+
[
26+
'If and else parts of ternary operator are equal (array()).',
27+
118,
28+
],
29+
[
30+
'If and else parts of ternary operator are equal (\'string_val\').',
31+
119,
32+
],
33+
[
34+
'If and else parts of ternary operator are equal (array(23, 24)).',
35+
121,
36+
],
37+
[
38+
'If and else parts of ternary operator are equal (array(1 => 1)).',
39+
122,
40+
],
41+
]);
42+
}
43+
44+
}

tests/Rules/Operators/data/operators.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,18 @@ function (array $array, int $int, $mixed) {
109109

110110
explode($mixed, $mixed) + $int;
111111
};
112+
113+
foo() ? true : true;
114+
foo() ? true : null;
115+
foo() ? $object : true;
116+
foo() ? $object : false;
117+
foo() ? $object : null;
118+
foo() ? [] : [];
119+
foo() ? 'string_val' : 'string_val';
120+
foo() ? [23, 24] : [23, 25];
121+
foo() ? [23, 24] : [23, 24];
122+
foo() ? [1 => 1] : ['1' => 1];
123+
foo() ? [1 => 1] : ['asd' => 1];
124+
$object ?: $object;
125+
foo() ? false : true;
126+
foo() ? true : false;

0 commit comments

Comments
 (0)