Skip to content

Commit c94d4bf

Browse files
committed
Check whether function parameter has typehint
1 parent 9630213 commit c94d4bf

File tree

4 files changed

+136
-1
lines changed

4 files changed

+136
-1
lines changed

Diff for: composer.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
}
2929
},
3030
"autoload-dev": {
31-
"classmap": ["tests/"]
31+
"classmap": ["tests/"],
32+
"files": [
33+
"tests/Rules/Functions/data/missing-function-parameter-typehint.php"
34+
]
3235
}
3336
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Broker\Broker;
8+
use PHPStan\Reflection\BrokerAwareExtension;
9+
use PHPStan\Reflection\FunctionReflection;
10+
use PHPStan\Reflection\ParameterReflection;
11+
use PHPStan\Type\MixedType;
12+
13+
final class MissingFunctionParameterTypehintRule implements \PHPStan\Rules\Rule, BrokerAwareExtension
14+
{
15+
16+
/** @var Broker */
17+
private $broker;
18+
19+
/**
20+
* @return string Class implementing \PhpParser\Node
21+
*/
22+
public function getNodeType(): string
23+
{
24+
return \PhpParser\Node\Stmt\Function_::class;
25+
}
26+
27+
/**
28+
* @param \PhpParser\Node\Stmt\Function_ $node
29+
* @param \PHPStan\Analyser\Scope $scope
30+
*
31+
* @return string[] errors
32+
*/
33+
public function processNode(Node $node, Scope $scope): array
34+
{
35+
if ($scope->isInClass()) {
36+
throw new \PHPStan\ShouldNotHappenException();
37+
}
38+
39+
$functionReflection = $this->broker->getCustomFunction(new Node\Name($node->name, $node->getAttributes()), $scope);
40+
41+
$messages = [];
42+
43+
foreach ($functionReflection->getParameters() as $parameterReflection) {
44+
$message = $this->checkFunctionParameter($functionReflection, $parameterReflection);
45+
if ($message === null) {
46+
continue;
47+
}
48+
49+
$messages[] = $message;
50+
}
51+
52+
return $messages;
53+
}
54+
55+
private function checkFunctionParameter(FunctionReflection $functionReflection, ParameterReflection $parameterReflection): ?string
56+
{
57+
$parameterType = $parameterReflection->getType();
58+
59+
if ($parameterType instanceof MixedType && !$parameterType->isExplicitMixed()) {
60+
return sprintf(
61+
'Function %s() has parameter $%s with no typehint specified',
62+
$functionReflection->getName(),
63+
$parameterReflection->getName()
64+
);
65+
}
66+
67+
return null;
68+
}
69+
70+
public function setBroker(Broker $broker): void
71+
{
72+
$this->broker = $broker;
73+
}
74+
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
class MissingFunctionParameterTypehintRuleTest extends \PHPStan\Testing\RuleTestCase
6+
{
7+
8+
protected function getRule(): \PHPStan\Rules\Rule
9+
{
10+
$rule = new MissingFunctionParameterTypehintRule();
11+
$rule->setBroker($this->createBroker([], []));
12+
13+
return $rule;
14+
}
15+
16+
public function testRule(): void
17+
{
18+
$this->analyse([__DIR__ . '/data/missing-function-parameter-typehint.php'], [
19+
[
20+
'Function globalFunction() has parameter $b with no typehint specified',
21+
9,
22+
],
23+
[
24+
'Function globalFunction() has parameter $c with no typehint specified',
25+
9,
26+
],
27+
[
28+
'Function MissingFunctionParameterTypehint\namespacedFunction() has parameter $d with no typehint specified',
29+
20,
30+
],
31+
]);
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace
4+
{
5+
/**
6+
* @param int $a
7+
* @param $b
8+
*/
9+
function globalFunction($a, $b, $c): bool
10+
{
11+
return false;
12+
}
13+
}
14+
15+
namespace MissingFunctionParameterTypehint
16+
{
17+
/**
18+
* @param $d
19+
*/
20+
function namespacedFunction($d, bool $e): int {
21+
return 9;
22+
};
23+
}

0 commit comments

Comments
 (0)