Skip to content

Commit 24f6264

Browse files
committed
OverridingPropertyRule - relax checking PHPDoc types
1 parent 9762d37 commit 24f6264

File tree

5 files changed

+145
-7
lines changed

5 files changed

+145
-7
lines changed

conf/config.level0.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ services:
220220
class: PHPStan\Rules\Properties\OverridingPropertyRule
221221
arguments:
222222
checkPhpDocMethodSignatures: %checkPhpDocMethodSignatures%
223+
reportMaybes: %reportMaybesInPropertyPhpDocTypes%
223224

224225
-
225226
class: PHPStan\Rules\Properties\UninitializedPropertyRule

conf/config.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ parameters:
8282
implicitThrows: true
8383
reportMaybes: false
8484
reportMaybesInMethodSignatures: false
85+
reportMaybesInPropertyPhpDocTypes: false
8586
reportStaticMethodSignatures: false
8687
mixinExcludeClasses: []
8788
scanFiles: []
@@ -267,6 +268,7 @@ parametersSchema:
267268
tipsOfTheDay: bool()
268269
reportMaybes: bool()
269270
reportMaybesInMethodSignatures: bool()
271+
reportMaybesInPropertyPhpDocTypes: bool()
270272
reportStaticMethodSignatures: bool()
271273
parallel: structure([
272274
jobSize: int(),

src/Rules/Properties/OverridingPropertyRule.php

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ class OverridingPropertyRule implements Rule
2020

2121
private bool $checkPhpDocMethodSignatures;
2222

23-
public function __construct(bool $checkPhpDocMethodSignatures)
23+
private bool $reportMaybes;
24+
25+
public function __construct(
26+
bool $checkPhpDocMethodSignatures,
27+
bool $reportMaybes
28+
)
2429
{
2530
$this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures;
31+
$this->reportMaybes = $reportMaybes;
2632
}
2733

2834
public function getNodeType(): string
@@ -152,21 +158,49 @@ public function processNode(Node $node, Scope $scope): array
152158
}
153159

154160
$propertyReflection = $classReflection->getNativeProperty($node->getName());
155-
if ($propertyReflection->getReadableType()->equals($prototype->getReadableType())) {
161+
if ($prototype->getReadableType()->equals($propertyReflection->getReadableType())) {
156162
return $errors;
157163
}
158164

159165
$verbosity = VerbosityLevel::getRecommendedLevelByType($prototype->getReadableType(), $propertyReflection->getReadableType());
160-
161-
$errors[] = RuleErrorBuilder::message(sprintf(
162-
'Type %s of property %s::$%s is not the same as type %s of overridden property %s::$%s.',
166+
$isSuperType = $prototype->getReadableType()->isSuperTypeOf($propertyReflection->getReadableType());
167+
$canBeTurnedOffError = RuleErrorBuilder::message(sprintf(
168+
'PHPDoc type %s of property %s::$%s is not the same as PHPDoc type %s of overridden property %s::$%s.',
163169
$propertyReflection->getReadableType()->describe($verbosity),
164170
$classReflection->getDisplayName(),
165171
$node->getName(),
166172
$prototype->getReadableType()->describe($verbosity),
167173
$prototype->getDeclaringClass()->getDisplayName(),
168174
$node->getName()
175+
))->tip(sprintf(
176+
"You can fix 3rd party PHPDoc types with stub files:\n %s\n This error can be turned off by setting\n %s",
177+
'<fg=cyan>https://phpstan.org/user-guide/stub-files</>',
178+
'<fg=cyan>reportMaybesInPropertyPhpDocTypes: false</> in your <fg=cyan>%configurationFile%</>.'
169179
))->build();
180+
$cannotBeTurnedOffError = RuleErrorBuilder::message(sprintf(
181+
'PHPDoc type %s of property %s::$%s is %s PHPDoc type %s of overridden property %s::$%s.',
182+
$propertyReflection->getReadableType()->describe($verbosity),
183+
$classReflection->getDisplayName(),
184+
$node->getName(),
185+
$this->reportMaybes ? 'not the same as' : 'not covariant with',
186+
$prototype->getReadableType()->describe($verbosity),
187+
$prototype->getDeclaringClass()->getDisplayName(),
188+
$node->getName()
189+
))->tip(sprintf(
190+
"You can fix 3rd party PHPDoc types with stub files:\n %s",
191+
'<fg=cyan>https://phpstan.org/user-guide/stub-files</>'
192+
))->build();
193+
if ($this->reportMaybes) {
194+
if (!$isSuperType->yes()) {
195+
$errors[] = $cannotBeTurnedOffError;
196+
} else {
197+
$errors[] = $canBeTurnedOffError;
198+
}
199+
} else {
200+
if (!$isSuperType->yes()) {
201+
$errors[] = $cannotBeTurnedOffError;
202+
}
203+
}
170204

171205
return $errors;
172206
}

tests/PHPStan/Rules/Properties/OverridingPropertyRuleTest.php

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
class OverridingPropertyRuleTest extends RuleTestCase
1212
{
1313

14+
/** @var bool */
15+
private $reportMaybes;
16+
1417
protected function getRule(): Rule
1518
{
16-
return new OverridingPropertyRule(true);
19+
return new OverridingPropertyRule(true, $this->reportMaybes);
1720
}
1821

1922
public function testRule(): void
@@ -22,6 +25,7 @@ public function testRule(): void
2225
$this->markTestSkipped('Test requires static reflection.');
2326
}
2427

28+
$this->reportMaybes = true;
2529
$this->analyse([__DIR__ . '/data/overriding-property.php'], [
2630
[
2731
'Static property OverridingProperty\Bar::$protectedFoo overrides non-static property OverridingProperty\Foo::$protectedFoo.',
@@ -88,10 +92,76 @@ public function testRule(): void
8892
142,
8993
],
9094
[
91-
'Type 4 of property OverridingProperty\Typed2WithPhpDoc::$foo is not the same as type 1|2|3 of overridden property OverridingProperty\TypedWithPhpDoc::$foo.',
95+
'PHPDoc type 4 of property OverridingProperty\Typed2WithPhpDoc::$foo is not the same as PHPDoc type 1|2|3 of overridden property OverridingProperty\TypedWithPhpDoc::$foo.',
9296
158,
97+
sprintf(
98+
"You can fix 3rd party PHPDoc types with stub files:\n %s",
99+
'<fg=cyan>https://phpstan.org/user-guide/stub-files</>'
100+
),
93101
],
94102
]);
95103
}
96104

105+
public function dataRulePHPDocTypes(): array
106+
{
107+
$tip = sprintf(
108+
"You can fix 3rd party PHPDoc types with stub files:\n %s",
109+
'<fg=cyan>https://phpstan.org/user-guide/stub-files</>',
110+
);
111+
$tipWithOption = sprintf(
112+
"You can fix 3rd party PHPDoc types with stub files:\n %s\n This error can be turned off by setting\n %s",
113+
'<fg=cyan>https://phpstan.org/user-guide/stub-files</>',
114+
'<fg=cyan>reportMaybesInPropertyPhpDocTypes: false</> in your <fg=cyan>%configurationFile%</>.'
115+
);
116+
117+
return [
118+
[
119+
false,
120+
[
121+
[
122+
'PHPDoc type array of property OverridingPropertyPhpDoc\Bar::$arrayClassStrings is not covariant with PHPDoc type array<class-string> of overridden property OverridingPropertyPhpDoc\Foo::$arrayClassStrings.',
123+
26,
124+
$tip,
125+
],
126+
[
127+
'PHPDoc type int of property OverridingPropertyPhpDoc\Bar::$string is not covariant with PHPDoc type string of overridden property OverridingPropertyPhpDoc\Foo::$string.',
128+
29,
129+
$tip,
130+
],
131+
],
132+
],
133+
[
134+
true,
135+
[
136+
[
137+
'PHPDoc type array<class-string> of property OverridingPropertyPhpDoc\Bar::$array is not the same as PHPDoc type array of overridden property OverridingPropertyPhpDoc\Foo::$array.',
138+
23,
139+
$tipWithOption,
140+
],
141+
[
142+
'PHPDoc type array of property OverridingPropertyPhpDoc\Bar::$arrayClassStrings is not the same as PHPDoc type array<class-string> of overridden property OverridingPropertyPhpDoc\Foo::$arrayClassStrings.',
143+
26,
144+
$tip,
145+
],
146+
[
147+
'PHPDoc type int of property OverridingPropertyPhpDoc\Bar::$string is not the same as PHPDoc type string of overridden property OverridingPropertyPhpDoc\Foo::$string.',
148+
29,
149+
$tip,
150+
],
151+
],
152+
],
153+
];
154+
}
155+
156+
/**
157+
* @dataProvider dataRulePHPDocTypes
158+
* @param bool $reportMaybes
159+
* @param mixed[] $errors
160+
*/
161+
public function testRulePHPDocTypes(bool $reportMaybes, array $errors): void
162+
{
163+
$this->reportMaybes = $reportMaybes;
164+
$this->analyse([__DIR__ . '/data/overriding-property-phpdoc.php'], $errors);
165+
}
166+
97167
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace OverridingPropertyPhpDoc;
4+
5+
class Foo
6+
{
7+
8+
/** @var array */
9+
protected $array;
10+
11+
/** @var array<class-string> */
12+
protected $arrayClassStrings;
13+
14+
/** @var string */
15+
protected $string;
16+
17+
}
18+
19+
class Bar extends Foo
20+
{
21+
22+
/** @var array<class-string> */
23+
protected $array;
24+
25+
/** @var array */
26+
protected $arrayClassStrings;
27+
28+
/** @var int */
29+
protected $string;
30+
31+
}

0 commit comments

Comments
 (0)