From c280be4a16f1c1ae643ede9fb4656246c4526047 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 3 Oct 2022 11:51:21 +0200 Subject: [PATCH] extract PhpDocUtil (#435) --- src/PhpDoc/PhpDocUtil.php | 77 +++++++++++++++++++++++++ src/QueryReflection/QueryReflection.php | 32 ++-------- 2 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 src/PhpDoc/PhpDocUtil.php diff --git a/src/PhpDoc/PhpDocUtil.php b/src/PhpDoc/PhpDocUtil.php new file mode 100644 index 000000000..91c3f11aa --- /dev/null +++ b/src/PhpDoc/PhpDocUtil.php @@ -0,0 +1,77 @@ +getDocComment(); + if (null !== $phpDocString && false !== strpos($phpDocString, $text)) { + return true; + } + } + + return false; + } + + /** + * Returns a unquoted plain string following a annotation. + * + * @param string $annotation e.g. '@phpstandba-inference-placeholder' + */ + public static function matchStringAnnotation(string $annotation, CallLike $callike, Scope $scope): ?string + { + $methodReflection = self::getMethodReflection($callike, $scope); + + if (null !== $methodReflection) { + // atm no resolved phpdoc for methods + // see https://github.com/phpstan/phpstan/discussions/7657 + $phpDocString = $methodReflection->getDocComment(); + if (null !== $phpDocString && preg_match('/'.$annotation.'\s+(.+)$/m', $phpDocString, $matches)) { + $placeholder = $matches[1]; + + if (\in_array($placeholder[0], ['"', "'"], true)) { + $placeholder = trim($placeholder, $placeholder[0]); + } + + return $placeholder; + } + } + + return null; + } + + private static function getMethodReflection(CallLike $callike, Scope $scope): ?MethodReflection + { + $methodReflection = null; + if ($callike instanceof Expr\StaticCall) { + if ($callike->class instanceof Name && $callike->name instanceof Identifier) { + $classType = $scope->resolveTypeByName($callike->class); + $methodReflection = $scope->getMethodReflection($classType, $callike->name->name); + } + } elseif ($callike instanceof Expr\MethodCall && $callike->name instanceof Identifier) { + $classReflection = $scope->getClassReflection(); + if (null !== $classReflection && $classReflection->hasMethod($callike->name->name)) { + $methodReflection = $classReflection->getMethod($callike->name->name, $scope); + } + } + + return $methodReflection; + } +} diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index 5347005bc..831436143 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -6,8 +6,6 @@ use PhpParser\Node\Expr; use PhpParser\Node\Expr\BinaryOp\Concat; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; use PhpParser\Node\Scalar\Encapsed; use PhpParser\Node\Scalar\EncapsedStringPart; use PHPStan\Analyser\Scope; @@ -24,6 +22,7 @@ use staabm\PHPStanDba\Ast\ExpressionFinder; use staabm\PHPStanDba\DbaException; use staabm\PHPStanDba\Error; +use staabm\PHPStanDba\PhpDoc\PhpDocUtil; use staabm\PHPStanDba\UnresolvableQueryException; final class QueryReflection @@ -202,34 +201,13 @@ private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope, bool $res } if ($queryExpr instanceof Expr\CallLike) { - $methodReflection = null; - if ($queryExpr instanceof Expr\StaticCall) { - if ($queryExpr->class instanceof Name && $queryExpr->name instanceof Identifier) { - $classType = $scope->resolveTypeByName($queryExpr->class); - $methodReflection = $scope->getMethodReflection($classType, $queryExpr->name->name); - } - } elseif ($queryExpr instanceof Expr\MethodCall && $queryExpr->name instanceof Identifier) { - $classReflection = $scope->getClassReflection(); - if (null !== $classReflection && $classReflection->hasMethod($queryExpr->name->name)) { - $methodReflection = $classReflection->getMethod($queryExpr->name->name, $scope); - } - } - - if (null !== $methodReflection) { - // atm no resolved phpdoc for methods - // see https://github.com/phpstan/phpstan/discussions/7657 - $phpDocString = $methodReflection->getDocComment(); - if (null !== $phpDocString && preg_match('/@phpstandba-inference-placeholder\s+(.+)$/m', $phpDocString, $matches)) { - $placeholder = $matches[1]; + $placeholder = PhpDocUtil::matchStringAnnotation('@phpstandba-inference-placeholder', $queryExpr, $scope); - if (\in_array($placeholder[0], ['"', "'"], true)) { - $placeholder = trim($placeholder, $placeholder[0]); - } - - return $placeholder; - } + if (null !== $placeholder) { + return $placeholder; } } + if ($queryExpr instanceof Concat) { $left = $queryExpr->left; $right = $queryExpr->right;