From 712eac22fe27cfccd569d322687a0e2674e70b9f Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Thu, 24 Nov 2022 23:10:42 -0400 Subject: [PATCH 1/2] Fix issues Psalm identified 1. Support (and ignore) first-class callables for `Mockery::mock(...)` and `Mockery::spy(...)` 2. Fix prefix and bracket logic 3. Drop unused `@var` 4. Force `resolvedName` to be treated as `class-string` (because it is a class-string) --- Hooks/MockReturnTypeUpdater.php | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Hooks/MockReturnTypeUpdater.php b/Hooks/MockReturnTypeUpdater.php index dec3323..4e5b9f3 100644 --- a/Hooks/MockReturnTypeUpdater.php +++ b/Hooks/MockReturnTypeUpdater.php @@ -3,6 +3,7 @@ namespace Psalm\MockeryPlugin\Hooks; use PhpParser; +use PhpParser\Node\Arg; use Psalm\Plugin\EventHandler\AfterMethodCallAnalysisInterface; use Psalm\Plugin\EventHandler\Event\AfterMethodCallAnalysisEvent; use Psalm\Type; @@ -17,7 +18,11 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve $return_type_candidate = $event->getReturnTypeCandidate(); $expr = $event->getExpr(); $method_id = $event->getMethodId(); - if ($return_type_candidate && self::isMockMethod($method_id) && isset($expr->args[0])) { + if ($return_type_candidate + && self::isMockMethod($method_id) + && isset($expr->args[0]) + && $expr->args[0] instanceof Arg + ) { $first_arg = $expr->args[0]->value; $fq_class_name = null; @@ -27,6 +32,7 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve && $first_arg->name instanceof PhpParser\Node\Identifier && $first_arg->name->name === 'class' ) { + /** @var class-string */ $fq_class_name = $first_arg->class->getAttribute('resolvedName'); } elseif ( $first_arg instanceof PhpParser\Node\Expr\BinaryOp\Concat @@ -36,22 +42,23 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve && $first_arg->right instanceof PhpParser\Node\Scalar\String_ && $first_arg->right->value[0] === '[' ) { - /** @var PhpParser\Node\Expr\ClassConstFetch $left */ $left = $first_arg->left; + /** @var class-string */ $fq_class_name = $left->class->getAttribute('resolvedName'); } elseif ($first_arg instanceof PhpParser\Node\Scalar\String_) { - if (substr($first_arg->value, 0, 6) === 'alias:') { - $trimmed_value = substr($first_arg->value, 6); + $value = $first_arg->value; + if (substr($value, 0, 6) === 'alias:') { + $value = substr($value, 6); } elseif (substr($first_arg->value, 0, 9) === 'overload:') { - $trimmed_value = substr($first_arg->value, 9); + $value = substr($value, 9); } - $bracket_position = strpos($first_arg->value, '['); - $fq_class_name = substr( - (!isset($trimmed_value) || $trimmed_value === false) ? $first_arg->value : $trimmed_value, - 0, - $bracket_position === false ? strlen($first_arg->value) : $bracket_position - ); + $bracket_position = strpos($value, '['); + if ($bracket_position !== false) { + $fq_class_name = substr($value, 0, $bracket_position); + } else { + $fq_class_name = $value; + } } if ($fq_class_name) { From a4ff1b32a6077bcd2d48fc073cb6fe6b32fe3d12 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Thu, 24 Nov 2022 23:18:12 -0400 Subject: [PATCH 2/2] CS fix --- Hooks/MockReturnTypeUpdater.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Hooks/MockReturnTypeUpdater.php b/Hooks/MockReturnTypeUpdater.php index 4e5b9f3..0b695c5 100644 --- a/Hooks/MockReturnTypeUpdater.php +++ b/Hooks/MockReturnTypeUpdater.php @@ -18,7 +18,8 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve $return_type_candidate = $event->getReturnTypeCandidate(); $expr = $event->getExpr(); $method_id = $event->getMethodId(); - if ($return_type_candidate + if ( + $return_type_candidate && self::isMockMethod($method_id) && isset($expr->args[0]) && $expr->args[0] instanceof Arg