Skip to content

Commit d3b9fec

Browse files
adaamzondrejmirtes
authored andcommitted
Check whether function has return typehint
1 parent c46b4ac commit d3b9fec

File tree

5 files changed

+129
-1
lines changed

5 files changed

+129
-1
lines changed

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"autoload-dev": {
3232
"classmap": ["tests/"],
3333
"files": [
34-
"tests/Rules/Functions/data/missing-function-parameter-typehint.php"
34+
"tests/Rules/Functions/data/missing-function-parameter-typehint.php",
35+
"tests/Rules/Functions/data/missing-function-return-typehint.php"
3536
]
3637
}
3738
}

rules.neon

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ rules:
1515
- PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
1616
- PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule
1717
- PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule
18+
- PHPStan\Rules\Functions\MissingFunctionReturnTypehintRule
1819
- PHPStan\Rules\Methods\MissingMethodParameterTypehintRule
1920
- PHPStan\Rules\Methods\MissingMethodReturnTypehintRule
2021
- PHPStan\Rules\Methods\WrongCaseOfInheritedMethodRule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\ParametersAcceptorSelector;
9+
use PHPStan\Type\MixedType;
10+
11+
final class MissingFunctionReturnTypehintRule implements \PHPStan\Rules\Rule
12+
{
13+
14+
/** @var Broker */
15+
private $broker;
16+
17+
public function __construct(Broker $broker)
18+
{
19+
$this->broker = $broker;
20+
}
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+
$functionReflection = $this->broker->getCustomFunction(new Node\Name($node->name->name), $scope);
36+
$returnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
37+
38+
if ($returnType instanceof MixedType && !$returnType->isExplicitMixed()) {
39+
return [
40+
sprintf(
41+
'Function %s() has no return typehint specified.',
42+
$functionReflection->getName()
43+
),
44+
];
45+
}
46+
47+
return [];
48+
}
49+
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
class MissingFunctionReturnTypehintRuleTest extends \PHPStan\Testing\RuleTestCase
6+
{
7+
8+
protected function getRule(): \PHPStan\Rules\Rule
9+
{
10+
$rule = new MissingFunctionReturnTypehintRule($this->createBroker([], []));
11+
12+
return $rule;
13+
}
14+
15+
public function testRule(): void
16+
{
17+
$this->analyse([__DIR__ . '/data/missing-function-return-typehint.php'], [
18+
[
19+
'Function globalFunction1() has no return typehint specified.',
20+
5,
21+
],
22+
[
23+
'Function MissingFunctionReturnTypehint\namespacedFunction1() has no return typehint specified.',
24+
30,
25+
],
26+
]);
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace
4+
{
5+
function globalFunction1($a, $b, $c)
6+
{
7+
return false;
8+
}
9+
10+
function globalFunction2($a, $b, $c): bool
11+
{
12+
$closure = function($a, $b, $c) {
13+
14+
};
15+
16+
return false;
17+
}
18+
19+
/**
20+
* @return bool
21+
*/
22+
function globalFunction3($a, $b, $c)
23+
{
24+
return false;
25+
}
26+
}
27+
28+
namespace MissingFunctionReturnTypehint
29+
{
30+
function namespacedFunction1($d, $e)
31+
{
32+
return 9;
33+
};
34+
35+
function namespacedFunction2($d, $e): int
36+
{
37+
return 9;
38+
};
39+
40+
/**
41+
* @return int
42+
*/
43+
function namespacedFunction3($d, $e)
44+
{
45+
return 9;
46+
};
47+
}

0 commit comments

Comments
 (0)