|
26 | 26 | use PHPStan\Node\Printer\ExprPrinter; |
27 | 27 | use PHPStan\Php\PhpVersion; |
28 | 28 | use PHPStan\Reflection\Assertions; |
| 29 | +use PHPStan\Reflection\Callables\CallableParametersAcceptor; |
29 | 30 | use PHPStan\Reflection\ExtendedParametersAcceptor; |
30 | 31 | use PHPStan\Reflection\ParametersAcceptor; |
31 | 32 | use PHPStan\Reflection\ParametersAcceptorSelector; |
@@ -570,6 +571,13 @@ public function specifyTypesInCondition( |
570 | 571 | } |
571 | 572 | } |
572 | 573 |
|
| 574 | + return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); |
| 575 | + } elseif ($expr instanceof FuncCall && !($expr->name instanceof Name)) { |
| 576 | + $specifiedTypes = $this->specifyTypesFromCallableCall($context, $expr, $scope); |
| 577 | + if ($specifiedTypes !== null) { |
| 578 | + return $specifiedTypes; |
| 579 | + } |
| 580 | + |
573 | 581 | return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); |
574 | 582 | } elseif ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) { |
575 | 583 | $methodCalledOnType = $scope->getType($expr->var); |
@@ -1764,6 +1772,38 @@ static function (Type $type, callable $traverse) use ($templateTypeMap, &$contai |
1764 | 1772 | return $types; |
1765 | 1773 | } |
1766 | 1774 |
|
| 1775 | + private function specifyTypesFromCallableCall(TypeSpecifierContext $context, FuncCall $call, Scope $scope): ?SpecifiedTypes |
| 1776 | + { |
| 1777 | + if (!$call->name instanceof Expr) { |
| 1778 | + return null; |
| 1779 | + } |
| 1780 | + |
| 1781 | + $calleeType = $scope->getType($call->name); |
| 1782 | + |
| 1783 | + $assertions = null; |
| 1784 | + $parametersAcceptor = null; |
| 1785 | + if ($calleeType->isCallable()->yes()) { |
| 1786 | + $variants = $calleeType->getCallableParametersAcceptors($scope); |
| 1787 | + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $call->getArgs(), $variants); |
| 1788 | + if ($parametersAcceptor instanceof CallableParametersAcceptor) { |
| 1789 | + $assertions = $parametersAcceptor->getAsserts(); |
| 1790 | + } |
| 1791 | + } |
| 1792 | + |
| 1793 | + if ($assertions === null || $assertions->getAll() === [] || $parametersAcceptor === null) { |
| 1794 | + return null; |
| 1795 | + } |
| 1796 | + |
| 1797 | + $asserts = $assertions->mapTypes(static fn (Type $type) => TemplateTypeHelper::resolveTemplateTypes( |
| 1798 | + $type, |
| 1799 | + $parametersAcceptor->getResolvedTemplateTypeMap(), |
| 1800 | + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), |
| 1801 | + TemplateTypeVariance::createInvariant(), |
| 1802 | + )); |
| 1803 | + |
| 1804 | + return $this->specifyTypesFromAsserts($context, $call, $asserts, $parametersAcceptor, $scope); |
| 1805 | + } |
| 1806 | + |
1767 | 1807 | /** |
1768 | 1808 | * @return array<string, ConditionalExpressionHolder[]> |
1769 | 1809 | */ |
|
0 commit comments