Skip to content

Commit eecbcc8

Browse files
adaamzondrejmirtes
authored andcommitted
Check whether method parameter has typehint
1 parent 2dfbf80 commit eecbcc8

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Methods;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\MethodReflection;
8+
use PHPStan\Reflection\ParameterReflection;
9+
use PHPStan\Type\MixedType;
10+
11+
final class MissingMethodParameterTypehintRule implements \PHPStan\Rules\Rule
12+
{
13+
14+
/**
15+
* @return string Class implementing \PhpParser\Node
16+
*/
17+
public function getNodeType(): string
18+
{
19+
return \PhpParser\Node\Stmt\ClassMethod::class;
20+
}
21+
22+
/**
23+
* @param \PhpParser\Node\Stmt\ClassMethod $node
24+
* @param \PHPStan\Analyser\Scope $scope
25+
*
26+
* @return string[] errors
27+
*/
28+
public function processNode(Node $node, Scope $scope): array
29+
{
30+
if (!$scope->isInClass()) {
31+
throw new \PHPStan\ShouldNotHappenException();
32+
}
33+
34+
$methodReflection = $scope->getClassReflection()->getNativeMethod($node->name);
35+
36+
$messages = [];
37+
38+
foreach ($methodReflection->getParameters() as $parameterReflection) {
39+
$message = $this->checkMethodParameter($methodReflection, $parameterReflection);
40+
if ($message === null) {
41+
continue;
42+
}
43+
44+
$messages[] = $message;
45+
}
46+
47+
return $messages;
48+
}
49+
50+
private function checkMethodParameter(MethodReflection $methodReflection, ParameterReflection $parameterReflection): ?string
51+
{
52+
$parameterType = $parameterReflection->getType();
53+
54+
if ($parameterType instanceof MixedType && !$parameterType->isExplicitMixed()) {
55+
return sprintf(
56+
'Method %s::%s() has parameter $%s with no typehint specified',
57+
$methodReflection->getDeclaringClass()->getName(),
58+
$methodReflection->getName(),
59+
$parameterReflection->getName()
60+
);
61+
}
62+
63+
return null;
64+
}
65+
66+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Methods;
4+
5+
class MissingMethodParameterTypehintRuleTest extends \PHPStan\Testing\RuleTestCase
6+
{
7+
8+
protected function getRule(): \PHPStan\Rules\Rule
9+
{
10+
return new MissingMethodParameterTypehintRule();
11+
}
12+
13+
public function testRule(): void
14+
{
15+
$this->analyse([__DIR__ . '/data/missing-method-parameter-typehint.php'], [
16+
[
17+
'Method MissingMethodParameterTypehint\FooInterface::getFoo() has parameter $p1 with no typehint specified',
18+
8,
19+
],
20+
[
21+
'Method MissingMethodParameterTypehint\FooParent::getBar() has parameter $p2 with no typehint specified',
22+
15,
23+
],
24+
[
25+
'Method MissingMethodParameterTypehint\Foo::getFoo() has parameter $p1 with no typehint specified',
26+
25,
27+
],
28+
[
29+
'Method MissingMethodParameterTypehint\Foo::getBar() has parameter $p2 with no typehint specified',
30+
33,
31+
],
32+
[
33+
'Method MissingMethodParameterTypehint\Foo::getBaz() has parameter $p3 with no typehint specified',
34+
42,
35+
],
36+
]);
37+
}
38+
39+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace MissingMethodParameterTypehint;
4+
5+
interface FooInterface
6+
{
7+
8+
public function getFoo($p1): void;
9+
10+
}
11+
12+
class FooParent
13+
{
14+
15+
public function getBar($p2)
16+
{
17+
18+
}
19+
20+
}
21+
22+
class Foo extends FooParent implements FooInterface
23+
{
24+
25+
public function getFoo($p1): void
26+
{
27+
28+
}
29+
30+
/**
31+
* @param $p2
32+
*/
33+
public function getBar($p2)
34+
{
35+
36+
}
37+
38+
/**
39+
* @param $p3
40+
* @param int $p4
41+
*/
42+
public function getBaz($p3, $p4): bool
43+
{
44+
return false;
45+
}
46+
47+
/**
48+
* @param mixed $p5
49+
*/
50+
public function getFooBar($p5): bool
51+
{
52+
return false;
53+
}
54+
55+
}

0 commit comments

Comments
 (0)