Skip to content

Commit 2f456b9

Browse files
committed
Bleeding edge - deep inspect types for missing typehints
1 parent 09e771b commit 2f456b9

File tree

6 files changed

+78
-7
lines changed

6 files changed

+78
-7
lines changed

conf/bleedingEdge.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ parameters:
1919
rememberFunctionValues: true
2020
preciseExceptionTracking: true
2121
apiRules: true
22+
deepInspectTypes: true

conf/config.neon

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ parameters:
4141
rememberFunctionValues: false
4242
preciseExceptionTracking: false
4343
apiRules: false
44+
deepInspectTypes: false
4445
fileExtensions:
4546
- php
4647
checkAlwaysTrueCheckTypeFunctionCall: false
@@ -210,7 +211,8 @@ parametersSchema:
210211
skipCheckGenericClasses: listOf(string()),
211212
rememberFunctionValues: bool(),
212213
preciseExceptionTracking: bool(),
213-
apiRules: bool()
214+
apiRules: bool(),
215+
deepInspectTypes: bool()
214216
])
215217
fileExtensions: listOf(string())
216218
checkAlwaysTrueCheckTypeFunctionCall: bool()
@@ -836,6 +838,7 @@ services:
836838
checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType%
837839
checkMissingCallableSignature: %checkMissingCallableSignature%
838840
skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses%
841+
deepInspectTypes: %featureToggles.deepInspectTypes%
839842

840843
-
841844
class: PHPStan\Rules\NullsafeCheck

src/Command/ErrorFormatter/CheckstyleErrorFormatter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function formatErrors(
3737
$output->writeRaw(sprintf(
3838
' <error line="%d" column="1" severity="error" message="%s" />',
3939
$this->escape((string) $error->getLine()),
40-
$this->escape((string) $error->getMessage())
40+
$this->escape($error->getMessage())
4141
));
4242
$output->writeLineFormatted('');
4343
}
@@ -94,7 +94,7 @@ private function escape(string $string): string
9494
* Group errors by file
9595
*
9696
* @param AnalysisResult $analysisResult
97-
* @return array<string, array> Array that have as key the relative path of file
97+
* @return array<string, array<\PHPStan\Analyser\Error>> Array that have as key the relative path of file
9898
* and as value an array with occurred errors.
9999
*/
100100
private function groupByFile(AnalysisResult $analysisResult): array

src/Rules/MissingTypehintCheck.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class MissingTypehintCheck
3838
/** @var string[] */
3939
private array $skipCheckGenericClasses;
4040

41+
private bool $deepInspectTypes;
42+
4143
/**
4244
* @param string[] $skipCheckGenericClasses
4345
*/
@@ -46,14 +48,16 @@ public function __construct(
4648
bool $checkMissingIterableValueType,
4749
bool $checkGenericClassInNonGenericObjectType,
4850
bool $checkMissingCallableSignature,
49-
array $skipCheckGenericClasses = []
51+
array $skipCheckGenericClasses = [],
52+
bool $deepInspectTypes = false
5053
)
5154
{
5255
$this->reflectionProvider = $reflectionProvider;
5356
$this->checkMissingIterableValueType = $checkMissingIterableValueType;
5457
$this->checkGenericClassInNonGenericObjectType = $checkGenericClassInNonGenericObjectType;
5558
$this->checkMissingCallableSignature = $checkMissingCallableSignature;
5659
$this->skipCheckGenericClasses = $skipCheckGenericClasses;
60+
$this->deepInspectTypes = $deepInspectTypes;
5761
}
5862

5963
/**
@@ -86,6 +90,10 @@ public function getIterableTypesWithMissingValueTypehint(Type $type): array
8690
}
8791
$iterablesWithMissingValueTypehint[] = $type;
8892
}
93+
if ($this->deepInspectTypes) {
94+
return $traverse($type);
95+
}
96+
8997
return $type;
9098
}
9199
return $traverse($type);
@@ -142,8 +150,8 @@ public function getNonGenericObjectTypesWithGenericClass(Type $type): array
142150
];
143151
return $type;
144152
}
145-
$traverse($type);
146-
return $type;
153+
154+
return $traverse($type);
147155
});
148156

149157
return $objectTypes;

tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
class MissingMethodParameterTypehintRuleTest extends \PHPStan\Testing\RuleTestCase
1111
{
1212

13+
/** @var bool */
14+
private $deepInspectTypes = false;
15+
1316
protected function getRule(): \PHPStan\Rules\Rule
1417
{
1518
$broker = $this->createReflectionProvider();
16-
return new MissingMethodParameterTypehintRule(new MissingTypehintCheck($broker, true, true, true));
19+
return new MissingMethodParameterTypehintRule(new MissingTypehintCheck($broker, true, true, true, [], $this->deepInspectTypes));
1720
}
1821

1922
public function testRule(): void
@@ -92,4 +95,32 @@ public function testPromotedProperties(): void
9295
]);
9396
}
9497

98+
public function testDoNotDeepInspectTypes(): void
99+
{
100+
$this->analyse([__DIR__ . '/data/deep-inspect-types.php'], [
101+
[
102+
'Method DeepInspectTypes\Foo::doBar() has parameter $bars with generic class DeepInspectTypes\Bar but does not specify its types: T',
103+
17,
104+
MissingTypehintCheck::TURN_OFF_NON_GENERIC_CHECK_TIP,
105+
],
106+
]);
107+
}
108+
109+
public function testDeepInspectTypes(): void
110+
{
111+
$this->deepInspectTypes = true;
112+
$this->analyse([__DIR__ . '/data/deep-inspect-types.php'], [
113+
[
114+
'Method DeepInspectTypes\Foo::doFoo() has parameter $foo with no value type specified in iterable type iterable.',
115+
11,
116+
MissingTypehintCheck::TURN_OFF_MISSING_ITERABLE_VALUE_TYPE_TIP,
117+
],
118+
[
119+
'Method DeepInspectTypes\Foo::doBar() has parameter $bars with generic class DeepInspectTypes\Bar but does not specify its types: T',
120+
17,
121+
MissingTypehintCheck::TURN_OFF_NON_GENERIC_CHECK_TIP,
122+
],
123+
]);
124+
}
125+
95126
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace DeepInspectTypes;
4+
5+
class Foo
6+
{
7+
8+
/**
9+
* @param array<iterable> $foo
10+
*/
11+
public function doFoo(array $foo): void
12+
{
13+
14+
}
15+
16+
/** @param array<Bar> $bars */
17+
public function doBar(array $bars): void
18+
{
19+
20+
}
21+
22+
}
23+
24+
/** @template T */
25+
class Bar
26+
{
27+
28+
}

0 commit comments

Comments
 (0)