Skip to content

Commit d0a77d1

Browse files
committed
Report deprecated casts in PHP 8.5
1 parent 099b87a commit d0a77d1

File tree

5 files changed

+161
-0
lines changed

5 files changed

+161
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ lint:
116116
--exclude tests/PHPStan/Rules/Functions/data/closure-typehints-nodiscard.php \
117117
--exclude tests/PHPStan/Rules/Functions/data/typehints-nodiscard.php \
118118
--exclude tests/PHPStan/Rules/Methods/data/typehints-nodiscard.php \
119+
--exclude tests/PHPStan/Rules/Cast/data/deprecated-cast.php \
119120
src tests
120121

121122
install-paratest:

src/Php/PhpVersion.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,9 @@ public function supportsNoDiscardAttribute(): bool
439439
return $this->versionId >= 80500;
440440
}
441441

442+
public function deprecatesNonStandardCasts(): bool
443+
{
444+
return $this->versionId >= 80500;
445+
}
446+
442447
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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\DependencyInjection\RegisteredRule;
9+
use PHPStan\Php\PhpVersion;
10+
use PHPStan\Rules\Rule;
11+
use PHPStan\Rules\RuleErrorBuilder;
12+
13+
/**
14+
* @implements Rule<Cast>
15+
*/
16+
#[RegisteredRule(level: 0)]
17+
final class DeprecatedCastRule implements Rule
18+
{
19+
20+
public function __construct(private PhpVersion $phpVersion)
21+
{
22+
}
23+
24+
public function getNodeType(): string
25+
{
26+
return Cast::class;
27+
}
28+
29+
public function processNode(Node $node, Scope $scope): array
30+
{
31+
if (!$this->phpVersion->deprecatesNonStandardCasts()) {
32+
return [];
33+
}
34+
35+
if ($node instanceof Cast\Int_) {
36+
$kind = $node->getAttribute('kind', Cast\Int_::KIND_INT);
37+
if ($kind === Cast\Int_::KIND_INTEGER) {
38+
return [
39+
RuleErrorBuilder::message('Non-standard (integer) cast is deprecated in PHP 8.5. Use (int) instead.')
40+
->identifier('cast.deprecated')
41+
->build(),
42+
];
43+
}
44+
45+
return [];
46+
}
47+
48+
if ($node instanceof Cast\Bool_) {
49+
$kind = $node->getAttribute('kind', Cast\Bool_::KIND_BOOL);
50+
if ($kind === Cast\Bool_::KIND_BOOLEAN) {
51+
return [
52+
RuleErrorBuilder::message('Non-standard (boolean) cast is deprecated in PHP 8.5. Use (bool) instead.')
53+
->identifier('cast.deprecated')
54+
->build(),
55+
];
56+
}
57+
58+
return [];
59+
}
60+
61+
if ($node instanceof Cast\Double) {
62+
$kind = $node->getAttribute('kind', Cast\Double::KIND_FLOAT);
63+
if ($kind === Cast\Double::KIND_DOUBLE) {
64+
return [
65+
RuleErrorBuilder::message('Non-standard (double) cast is deprecated in PHP 8.5. Use (float) instead.')
66+
->identifier('cast.deprecated')
67+
->build(),
68+
];
69+
}
70+
71+
return [];
72+
}
73+
74+
if ($node instanceof Cast\String_) {
75+
$kind = $node->getAttribute('kind', Cast\String_::KIND_STRING);
76+
if ($kind === Cast\String_::KIND_BINARY) {
77+
return [
78+
RuleErrorBuilder::message('Non-standard (binary) cast is deprecated in PHP 8.5. Use (string) instead.')
79+
->identifier('cast.deprecated')
80+
->build(),
81+
];
82+
}
83+
84+
return [];
85+
}
86+
87+
return [];
88+
}
89+
90+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Cast;
4+
5+
use PHPStan\Php\PhpVersion;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Testing\RuleTestCase;
8+
use const PHP_VERSION_ID;
9+
10+
/**
11+
* @extends RuleTestCase<DeprecatedCastRule>
12+
*/
13+
class DeprecatedCastRuleTest extends RuleTestCase
14+
{
15+
16+
protected function getRule(): Rule
17+
{
18+
return new DeprecatedCastRule(new PhpVersion(PHP_VERSION_ID));
19+
}
20+
21+
public function testRule(): void
22+
{
23+
$errors = [];
24+
if (PHP_VERSION_ID >= 80500) {
25+
$errors = [
26+
[
27+
'Non-standard (integer) cast is deprecated in PHP 8.5. Use (int) instead.',
28+
7,
29+
],
30+
[
31+
'Non-standard (boolean) cast is deprecated in PHP 8.5. Use (bool) instead.',
32+
10,
33+
],
34+
[
35+
'Non-standard (double) cast is deprecated in PHP 8.5. Use (float) instead.',
36+
13,
37+
],
38+
[
39+
'Non-standard (binary) cast is deprecated in PHP 8.5. Use (string) instead.',
40+
16,
41+
],
42+
];
43+
}
44+
45+
$this->analyse([__DIR__ . '/data/deprecated-cast.php'], $errors);
46+
}
47+
48+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace DeprecatedCast;
4+
5+
function ($m): void {
6+
(int) $m;
7+
(integer) $m;
8+
9+
(bool) $m;
10+
(boolean) $m;
11+
12+
(float) $m;
13+
(double) $m;
14+
15+
(string) $m;
16+
(binary) $m;
17+
};

0 commit comments

Comments
 (0)