Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a670a59

Browse files
UselessCastRule - respect treatPhpDocTypesAsCertain
1 parent 08f2e51 commit a670a59

File tree

5 files changed

+96
-7
lines changed

5 files changed

+96
-7
lines changed

‎composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
],
88
"require": {
99
"php": "~7.1",
10-
"phpstan/phpstan": "^0.12"
10+
"phpstan/phpstan": "^0.12.6"
1111
},
1212
"require-dev": {
1313
"consistence/coding-standard": "^3.0.1",

‎rules.neon

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ rules:
1717
- PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule
1818
- PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule
1919
- PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule
20-
- PHPStan\Rules\Cast\UselessCastRule
2120
- PHPStan\Rules\Classes\RequireParentConstructCallRule
2221
- PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
2322
- PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule
@@ -45,6 +44,14 @@ rules:
4544
services:
4645
-
4746
class: PHPStan\Rules\BooleansInConditions\BooleanRuleHelper
47+
48+
-
49+
class: PHPStan\Rules\Cast\UselessCastRule
50+
arguments:
51+
treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain%
52+
tags:
53+
- phpstan.rules.rule
54+
4855
-
4956
class: PHPStan\Rules\Operators\OperatorRuleHelper
5057
-

‎src/Rules/Cast/UselessCastRule.php

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@
55
use PhpParser\Node;
66
use PhpParser\Node\Expr\Cast;
77
use PHPStan\Analyser\Scope;
8+
use PHPStan\Rules\RuleError;
9+
use PHPStan\Rules\RuleErrorBuilder;
810
use PHPStan\Type\ErrorType;
911
use PHPStan\Type\TypeUtils;
1012
use PHPStan\Type\VerbosityLevel;
1113

1214
class UselessCastRule implements \PHPStan\Rules\Rule
1315
{
1416

17+
/** @var bool */
18+
private $treatPhpDocTypesAsCertain;
19+
20+
public function __construct(bool $treatPhpDocTypesAsCertain)
21+
{
22+
$this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain;
23+
}
24+
1525
public function getNodeType(): string
1626
{
1727
return Cast::class;
@@ -20,7 +30,7 @@ public function getNodeType(): string
2030
/**
2131
* @param \PhpParser\Node\Expr\Cast $node
2232
* @param \PHPStan\Analyser\Scope $scope
23-
* @return string[] errors
33+
* @return RuleError[] errors
2434
*/
2535
public function processNode(Node $node, Scope $scope): array
2636
{
@@ -30,14 +40,30 @@ public function processNode(Node $node, Scope $scope): array
3040
}
3141
$castType = TypeUtils::generalizeType($castType);
3242

33-
$expressionType = $scope->getType($node->expr);
43+
if ($this->treatPhpDocTypesAsCertain) {
44+
$expressionType = $scope->getType($node->expr);
45+
} else {
46+
$expressionType = $scope->getNativeType($node->expr);
47+
}
3448
if ($castType->isSuperTypeOf($expressionType)->yes()) {
49+
$addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node, $castType): RuleErrorBuilder {
50+
if (!$this->treatPhpDocTypesAsCertain) {
51+
return $ruleErrorBuilder;
52+
}
53+
54+
$expressionTypeWithoutPhpDoc = $scope->getNativeType($node->expr);
55+
if ($castType->isSuperTypeOf($expressionTypeWithoutPhpDoc)->yes()) {
56+
return $ruleErrorBuilder;
57+
}
58+
59+
return $ruleErrorBuilder->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.');
60+
};
3561
return [
36-
sprintf(
62+
$addTip(RuleErrorBuilder::message(sprintf(
3763
'Casting to %s something that\'s already %s.',
3864
$castType->describe(VerbosityLevel::typeOnly()),
3965
$expressionType->describe(VerbosityLevel::typeOnly())
40-
),
66+
)))->build(),
4167
];
4268
}
4369

‎tests/Rules/Cast/UselessCastRuleTest.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,23 @@
55
class UselessCastRuleTest extends \PHPStan\Testing\RuleTestCase
66
{
77

8+
/** @var bool */
9+
private $treatPhpDocTypesAsCertain;
10+
811
protected function getRule(): \PHPStan\Rules\Rule
912
{
10-
return new UselessCastRule();
13+
return new UselessCastRule($this->treatPhpDocTypesAsCertain);
14+
}
15+
16+
protected function shouldTreatPhpDocTypesAsCertain(): bool
17+
{
18+
return $this->treatPhpDocTypesAsCertain;
1119
}
1220

1321
public function testUselessCast(): void
1422
{
1523
require_once __DIR__ . '/data/useless-cast.php';
24+
$this->treatPhpDocTypesAsCertain = true;
1625
$this->analyse(
1726
[__DIR__ . '/data/useless-cast.php'],
1827
[
@@ -40,4 +49,31 @@ public function testUselessCast(): void
4049
);
4150
}
4251

52+
public function testDoNotReportPhpDoc(): void
53+
{
54+
$this->treatPhpDocTypesAsCertain = false;
55+
$this->analyse([__DIR__ . '/data/useless-cast-not-phpdoc.php'], [
56+
[
57+
'Casting to int something that\'s already int.',
58+
16,
59+
],
60+
]);
61+
}
62+
63+
public function testReportPhpDoc(): void
64+
{
65+
$this->treatPhpDocTypesAsCertain = true;
66+
$this->analyse([__DIR__ . '/data/useless-cast-not-phpdoc.php'], [
67+
[
68+
'Casting to int something that\'s already int.',
69+
16,
70+
],
71+
[
72+
'Casting to int something that\'s already int.',
73+
17,
74+
'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.',
75+
],
76+
]);
77+
}
78+
4379
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace UselessCastNotPhpDoc;
4+
5+
class Foo
6+
{
7+
8+
/**
9+
* @param int $phpDocInteger
10+
*/
11+
public function doFoo(
12+
int $realInteger,
13+
$phpDocInteger
14+
): void
15+
{
16+
$foo = (int) $realInteger;
17+
$bar = (int) $phpDocInteger;
18+
}
19+
20+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /