Skip to content

Commit 2335152

Browse files
authored
Support for phpstan and psaml prefixes on @method
1 parent bf76ad9 commit 2335152

File tree

4 files changed

+82
-25
lines changed

4 files changed

+82
-25
lines changed

src/PhpDoc/PhpDocNodeResolver.php

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -125,35 +125,41 @@ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope):
125125
{
126126
$resolved = [];
127127

128-
foreach ($phpDocNode->getMethodTagValues() as $tagValue) {
129-
$parameters = [];
130-
foreach ($tagValue->parameters as $parameterNode) {
131-
$parameterName = substr($parameterNode->parameterName, 1);
132-
$type = $parameterNode->type !== null ? $this->typeNodeResolver->resolve($parameterNode->type, $nameScope) : new MixedType();
133-
if ($parameterNode->defaultValue instanceof ConstExprNullNode) {
134-
$type = TypeCombinator::addNull($type);
135-
}
136-
$defaultValue = null;
137-
if ($parameterNode->defaultValue !== null) {
138-
$defaultValue = $this->constExprNodeResolver->resolve($parameterNode->defaultValue);
128+
foreach (['@method', '@psalm-method', '@phpstan-method'] as $tagName) {
129+
foreach ($phpDocNode->getMethodTagValues($tagName) as $tagValue) {
130+
$parameters = [];
131+
foreach ($tagValue->parameters as $parameterNode) {
132+
$parameterName = substr($parameterNode->parameterName, 1);
133+
$type = $parameterNode->type !== null
134+
? $this->typeNodeResolver->resolve($parameterNode->type, $nameScope)
135+
: new MixedType();
136+
if ($parameterNode->defaultValue instanceof ConstExprNullNode) {
137+
$type = TypeCombinator::addNull($type);
138+
}
139+
$defaultValue = null;
140+
if ($parameterNode->defaultValue !== null) {
141+
$defaultValue = $this->constExprNodeResolver->resolve($parameterNode->defaultValue);
142+
}
143+
144+
$parameters[$parameterName] = new MethodTagParameter(
145+
$type,
146+
$parameterNode->isReference
147+
? PassedByReference::createCreatesNewVariable()
148+
: PassedByReference::createNo(),
149+
$parameterNode->isVariadic || $parameterNode->defaultValue !== null,
150+
$parameterNode->isVariadic,
151+
$defaultValue
152+
);
139153
}
140154

141-
$parameters[$parameterName] = new MethodTagParameter(
142-
$type,
143-
$parameterNode->isReference
144-
? PassedByReference::createCreatesNewVariable()
145-
: PassedByReference::createNo(),
146-
$parameterNode->isVariadic || $parameterNode->defaultValue !== null,
147-
$parameterNode->isVariadic,
148-
$defaultValue
155+
$resolved[$tagValue->methodName] = new MethodTag(
156+
$tagValue->returnType !== null
157+
? $this->typeNodeResolver->resolve($tagValue->returnType, $nameScope)
158+
: new MixedType(),
159+
$tagValue->isStatic,
160+
$parameters
149161
);
150162
}
151-
152-
$resolved[$tagValue->methodName] = new MethodTag(
153-
$tagValue->returnType !== null ? $this->typeNodeResolver->resolve($tagValue->returnType, $nameScope) : new MixedType(),
154-
$tagValue->isStatic,
155-
$parameters
156-
);
157163
}
158164

159165
return $resolved;

src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class InvalidPHPStanDocTagRule implements \PHPStan\Rules\Rule
2828
'@phpstan-throws',
2929
'@phpstan-ignore-next-line',
3030
'@phpstan-ignore-line',
31+
'@phpstan-method',
3132
];
3233

3334
private Lexer $phpDocLexer;

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10023,6 +10023,11 @@ public function dataMinMaxReturnTypeWithArrays(): array
1002310023
return $this->gatherAssertTypes(__DIR__ . '/data/minmax-arrays.php');
1002410024
}
1002510025

10026+
public function dataClassPhpDocs(): array
10027+
{
10028+
return $this->gatherAssertTypes(__DIR__ . '/data/classPhpDocs.php');
10029+
}
10030+
1002610031
/**
1002710032
* @dataProvider dataBug2574
1002810033
* @dataProvider dataBug2577
@@ -10086,6 +10091,7 @@ public function dataMinMaxReturnTypeWithArrays(): array
1008610091
* @dataProvider dataNativeUnionTypes
1008710092
* @dataProvider dataMinMaxReturnTypeWithArrays
1008810093
* @dataProvider dataNativeStaticReturnType
10094+
* @dataProvider dataClassPhpDocs
1008910095
* @param string $assertType
1009010096
* @param string $file
1009110097
* @param mixed ...$args
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace ClassPhpDocsNamespace;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
/**
8+
* @method string string()
9+
* @method array arrayOfStrings()
10+
* @psalm-method array<string> arrayOfStrings()
11+
* @phpstan-method array<string, int> arrayOfInts()
12+
* @method array arrayOfInts()
13+
* @method mixed overrodeMethod()
14+
* @method static mixed overrodeStaticMethod()
15+
*/
16+
class Foo
17+
{
18+
public function __call($name, $arguments){}
19+
20+
public static function __callStatic($name, $arguments){}
21+
22+
public function doFoo()
23+
{
24+
assertType('string', $this->string());
25+
assertType('array<string>', $this->arrayOfStrings());
26+
assertType('array<string, int>', $this->arrayOfInts());
27+
assertType('mixed', $this->overrodeMethod());
28+
assertType('mixed', static::overrodeStaticMethod());
29+
}
30+
}
31+
32+
/**
33+
* @phpstan-method string overrodeMethod()
34+
* @phpstan-method static int overrodeStaticMethod()
35+
*/
36+
class Child extends Foo
37+
{
38+
public function doFoo()
39+
{
40+
assertType('string', $this->overrodeMethod());
41+
assertType('int', static::overrodeStaticMethod());
42+
}
43+
}
44+

0 commit comments

Comments
 (0)