Skip to content

Commit 7c5de1d

Browse files
committed
Moved UselessCastRule to strict-rules
1 parent 15b1470 commit 7c5de1d

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

rules.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rules:
1212
- PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule
1313
- PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule
1414
- PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule
15+
- PHPStan\Rules\Cast\UselessCastRule
1516
- PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
1617
- PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule
1718
- PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule

src/Rules/Cast/UselessCastRule.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Cast;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\Cast;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Type\ErrorType;
9+
use PHPStan\Type\TypeUtils;
10+
use PHPStan\Type\VerbosityLevel;
11+
12+
class UselessCastRule implements \PHPStan\Rules\Rule
13+
{
14+
15+
public function getNodeType(): string
16+
{
17+
return Cast::class;
18+
}
19+
20+
/**
21+
* @param \PhpParser\Node\Expr\Cast $node
22+
* @param \PHPStan\Analyser\Scope $scope
23+
* @return string[] errors
24+
*/
25+
public function processNode(Node $node, Scope $scope): array
26+
{
27+
$castType = $scope->getType($node);
28+
if ($castType instanceof ErrorType) {
29+
return [];
30+
}
31+
$castType = TypeUtils::generalizeType($castType);
32+
33+
$expressionType = $scope->getType($node->expr);
34+
if ($castType->isSuperTypeOf($expressionType)->yes()) {
35+
return [
36+
sprintf(
37+
'Casting to %s something that\'s already %s.',
38+
$castType->describe(VerbosityLevel::typeOnly()),
39+
$expressionType->describe(VerbosityLevel::typeOnly())
40+
),
41+
];
42+
}
43+
44+
return [];
45+
}
46+
47+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Cast;
4+
5+
class UselessCastRuleTest extends \PHPStan\Testing\RuleTestCase
6+
{
7+
8+
protected function getRule(): \PHPStan\Rules\Rule
9+
{
10+
return new UselessCastRule();
11+
}
12+
13+
public function testUselessCast(): void
14+
{
15+
require_once __DIR__ . '/data/useless-cast.php';
16+
$this->analyse(
17+
[__DIR__ . '/data/useless-cast.php'],
18+
[
19+
[
20+
'Casting to int something that\'s already int.',
21+
7,
22+
],
23+
[
24+
'Casting to string something that\'s already string.',
25+
9,
26+
],
27+
[
28+
'Casting to stdClass something that\'s already stdClass.',
29+
10,
30+
],
31+
[
32+
'Casting to float something that\'s already float.',
33+
27,
34+
],
35+
[
36+
'Casting to string something that\'s already string.',
37+
46,
38+
],
39+
]
40+
);
41+
}
42+
43+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace UselessCast;
4+
5+
function () {
6+
$foo = (int) '5';
7+
$foo = (int) 5;
8+
$foo = (string) 5;
9+
$foo = (string) '5';
10+
$foo = (object) new \stdClass();
11+
12+
/** @var string|null $nullableString */
13+
$nullableString = 'foo';
14+
$foo = (string) $nullableString;
15+
16+
$foo = (float) (6 / 2);
17+
18+
$width = 1;
19+
$scale = 2.0;
20+
$width *= $scale;
21+
echo (int) $width;
22+
23+
/** @var string|mixed $stringOrMixed */
24+
$stringOrMixed = doFoo();
25+
(string) $stringOrMixed;
26+
27+
$foo = (float) (100.0 / 25.432);
28+
29+
(int) "blabla";
30+
};
31+
32+
function foo(string &$input) {
33+
$input = 1;
34+
}
35+
36+
function () {
37+
$s = '';
38+
foo($s);
39+
(string) $s;
40+
};
41+
42+
function () {
43+
/** @var int|string $s */
44+
$s = doFoo();
45+
if (!is_numeric($s)) {
46+
(string) $s;
47+
}
48+
};

0 commit comments

Comments
 (0)