Skip to content

Commit e0ef6de

Browse files
committed
Check whether method has return typehint
1 parent 26eb57c commit e0ef6de

File tree

3 files changed

+138
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)