Skip to content

Commit 4db44bd

Browse files
authored
support @phpstandba-inference-placeholder on static method calls (#432)
1 parent d73bbb7 commit 4db44bd

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

src/QueryReflection/QueryReflection.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\Node\Expr;
88
use PhpParser\Node\Expr\BinaryOp\Concat;
99
use PhpParser\Node\Identifier;
10+
use PhpParser\Node\Name;
1011
use PHPStan\Analyser\Scope;
1112
use PHPStan\ShouldNotHappenException;
1213
use PHPStan\Type\Constant\ConstantArrayType;
@@ -187,13 +188,21 @@ private function resolveQueryExpr(Expr $queryExpr, Scope $scope): ?string
187188
*/
188189
private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope): ?string
189190
{
190-
if ($queryExpr instanceof Expr\MethodCall && $queryExpr->name instanceof Identifier) {
191-
$classReflection = $scope->getClassReflection();
192-
193-
// XXX atm we only support inference-placeholder for method calls within the same class
194-
if (null !== $classReflection && $classReflection->hasMethod($queryExpr->name->name)) {
195-
$methodReflection = $classReflection->getMethod($queryExpr->name->name, $scope);
191+
if ($queryExpr instanceof Expr\CallLike) {
192+
$methodReflection = null;
193+
if ($queryExpr instanceof Expr\StaticCall) {
194+
if ($queryExpr->class instanceof Name && $queryExpr->name instanceof Identifier) {
195+
$classType = $scope->resolveTypeByName($queryExpr->class);
196+
$methodReflection = $scope->getMethodReflection($classType, $queryExpr->name->name);
197+
}
198+
} elseif ($queryExpr instanceof Expr\MethodCall && $queryExpr->name instanceof Identifier) {
199+
$classReflection = $scope->getClassReflection();
200+
if (null !== $classReflection && $classReflection->hasMethod($queryExpr->name->name)) {
201+
$methodReflection = $classReflection->getMethod($queryExpr->name->name, $scope);
202+
}
203+
}
196204

205+
if (null !== $methodReflection) {
197206
// atm no resolved phpdoc for methods
198207
// see https://github.com/phpstan/phpstan/discussions/7657
199208
$phpDocString = $methodReflection->getDocComment();

tests/default/data/inference-placeholder.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ public function fetchOneWithDynamicQueryPart(Connection $conn, string $email)
1212
$query = 'SELECT email, adaid FROM ada WHERE email = :email AND '.$this->dynamicWhere(rand(0, 100));
1313
$fetchResult = $conn->fetchOne($query, ['email' => $email]);
1414
assertType('string|false', $fetchResult);
15+
16+
$query = 'SELECT email, adaid FROM ada WHERE email = :email AND '.self::dynamicWhere(rand(0, 100));
17+
$fetchResult = $conn->fetchOne($query, ['email' => $email]);
18+
assertType('string|false', $fetchResult);
1519
}
1620

1721
/**
@@ -31,4 +35,22 @@ private function dynamicWhere(int $i)
3135

3236
return implode(' AND ', $where);
3337
}
38+
39+
/**
40+
* simulating a dynamic where part, not relevant for the query overall result.
41+
*
42+
* @phpstandba-inference-placeholder '1=1'
43+
*
44+
* @return string
45+
*/
46+
private static function staticDynamicWhere(int $i)
47+
{
48+
$where = ['1=1'];
49+
50+
if ($i > 100) {
51+
$where[] = 'adaid = '.$i.'';
52+
}
53+
54+
return implode(' AND ', $where);
55+
}
3456
}

0 commit comments

Comments
 (0)