-
Notifications
You must be signed in to change notification settings - Fork 465
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bleeding edge - MissingMethodSelfOutTypeRule
- Loading branch information
1 parent
9ebc315
commit 892b319
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace PHPStan\Rules\Methods; | ||
|
||
use PhpParser\Node; | ||
use PHPStan\Analyser\Scope; | ||
use PHPStan\Node\InClassMethodNode; | ||
use PHPStan\Rules\MissingTypehintCheck; | ||
use PHPStan\Rules\Rule; | ||
use PHPStan\Rules\RuleErrorBuilder; | ||
use PHPStan\Type\VerbosityLevel; | ||
use function implode; | ||
use function sprintf; | ||
|
||
/** | ||
* @implements Rule<InClassMethodNode> | ||
*/ | ||
final class MissingMethodSelfOutTypeRule implements Rule | ||
{ | ||
|
||
public function __construct( | ||
private MissingTypehintCheck $missingTypehintCheck, | ||
) | ||
{ | ||
} | ||
|
||
public function getNodeType(): string | ||
{ | ||
return InClassMethodNode::class; | ||
} | ||
|
||
public function processNode(Node $node, Scope $scope): array | ||
{ | ||
$methodReflection = $node->getMethodReflection(); | ||
$selfOutType = $methodReflection->getSelfOutType(); | ||
|
||
if ($selfOutType === null) { | ||
return []; | ||
} | ||
|
||
$classReflection = $methodReflection->getDeclaringClass(); | ||
$phpDocTagMessage = 'PHPDoc tag @phpstan-self-out'; | ||
|
||
$messages = []; | ||
foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($selfOutType) as $iterableType) { | ||
$iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); | ||
$messages[] = RuleErrorBuilder::message(sprintf( | ||
'Method %s::%s() has %s with no value type specified in iterable type %s.', | ||
$classReflection->getDisplayName(), | ||
$methodReflection->getName(), | ||
$phpDocTagMessage, | ||
$iterableTypeDescription, | ||
)) | ||
->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP) | ||
->identifier('missingType.iterableValue') | ||
->build(); | ||
} | ||
|
||
foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($selfOutType) as [$name, $genericTypeNames]) { | ||
$messages[] = RuleErrorBuilder::message(sprintf( | ||
'Method %s::%s() has %s with generic %s but does not specify its types: %s', | ||
$classReflection->getDisplayName(), | ||
$methodReflection->getName(), | ||
$phpDocTagMessage, | ||
$name, | ||
implode(', ', $genericTypeNames), | ||
)) | ||
->identifier('missingType.generics') | ||
->build(); | ||
} | ||
|
||
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($selfOutType) as $callableType) { | ||
$messages[] = RuleErrorBuilder::message(sprintf( | ||
'Method %s::%s() has %s with no signature specified for %s.', | ||
$classReflection->getDisplayName(), | ||
$methodReflection->getName(), | ||
$phpDocTagMessage, | ||
$callableType->describe(VerbosityLevel::typeOnly()), | ||
))->identifier('missingType.callable')->build(); | ||
} | ||
|
||
return $messages; | ||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace PHPStan\Rules\Methods; | ||
|
||
use PHPStan\Rules\MissingTypehintCheck; | ||
use PHPStan\Rules\Rule as TRule; | ||
use PHPStan\Testing\RuleTestCase; | ||
|
||
/** | ||
* @extends RuleTestCase<MissingMethodSelfOutTypeRule> | ||
*/ | ||
class MissingMethodSelfOutTypeRuleTest extends RuleTestCase | ||
{ | ||
|
||
protected function getRule(): TRule | ||
{ | ||
return new MissingMethodSelfOutTypeRule(new MissingTypehintCheck(true, true, true, true, [])); | ||
} | ||
|
||
public function testRule(): void | ||
{ | ||
$this->analyse([__DIR__ . '/data/missing-method-self-out-type.php'], [ | ||
[ | ||
'Method MissingMethodSelfOutType\Foo::doFoo() has PHPDoc tag @phpstan-self-out with no value type specified in iterable type array.', | ||
14, | ||
'See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type', | ||
], | ||
[ | ||
'Method MissingMethodSelfOutType\Foo::doFoo2() has PHPDoc tag @phpstan-self-out with generic class MissingMethodSelfOutType\Foo but does not specify its types: T', | ||
22, | ||
], | ||
[ | ||
'Method MissingMethodSelfOutType\Foo::doFoo3() has PHPDoc tag @phpstan-self-out with no signature specified for callable.', | ||
30, | ||
], | ||
]); | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
tests/PHPStan/Rules/Methods/data/missing-method-self-out-type.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
namespace MissingMethodSelfOutType; | ||
|
||
/** | ||
* @template T | ||
*/ | ||
class Foo | ||
{ | ||
|
||
/** | ||
* @phpstan-self-out self<array> | ||
*/ | ||
public function doFoo(): void | ||
{ | ||
|
||
} | ||
|
||
/** | ||
* @phpstan-self-out self | ||
*/ | ||
public function doFoo2(): void | ||
{ | ||
|
||
} | ||
|
||
/** | ||
* @phpstan-self-out Foo<int>&callable | ||
*/ | ||
public function doFoo3(): void | ||
{ | ||
|
||
} | ||
|
||
} |