|
25 | 25 | use PhpParser\Node\Expr\FuncCall;
|
26 | 26 | use PhpParser\Node\Expr\Instanceof_;
|
27 | 27 | use PhpParser\Node\Expr\StaticCall;
|
28 |
| -use PhpParser\Node\Expr\Variable; |
29 | 28 | use PhpParser\Node\Name;
|
30 |
| -use PhpParser\Node\Param; |
31 | 29 | use PhpParser\Node\Scalar\LNumber;
|
32 | 30 | use PhpParser\Node\Scalar\String_;
|
33 |
| -use PhpParser\Node\Stmt\Return_; |
34 | 31 | use PHPStan\Analyser\Scope;
|
35 | 32 | use PHPStan\Analyser\SpecifiedTypes;
|
36 | 33 | use PHPStan\Analyser\TypeSpecifier;
|
|
44 | 41 | use PHPStan\Type\Constant\ConstantStringType;
|
45 | 42 | use PHPStan\Type\IterableType;
|
46 | 43 | use PHPStan\Type\MixedType;
|
| 44 | +use PHPStan\Type\NeverType; |
47 | 45 | use PHPStan\Type\ObjectType;
|
48 | 46 | use PHPStan\Type\StaticMethodTypeSpecifyingExtension;
|
49 | 47 | use PHPStan\Type\StringType;
|
|
59 | 57 | use function array_reduce;
|
60 | 58 | use function array_shift;
|
61 | 59 | use function count;
|
62 |
| -use function key; |
63 | 60 | use function lcfirst;
|
64 | 61 | use function substr;
|
65 | 62 |
|
@@ -774,56 +771,35 @@ private function handleAll(
|
774 | 771 | Scope $scope
|
775 | 772 | ): SpecifiedTypes
|
776 | 773 | {
|
777 |
| - $closureItemVariable = new Variable('item'); |
778 |
| - $closureArgs = $node->getArgs(); |
779 |
| - $closureArgs[0] = new Arg($closureItemVariable); |
780 |
| - |
781 |
| - $expression = new BooleanAnd( |
782 |
| - new FuncCall(new Name('is_iterable'), [$node->getArgs()[0]]), |
783 |
| - new Identical( |
784 |
| - $node->getArgs()[0]->value, |
785 |
| - new FuncCall( |
786 |
| - new Name('array_filter'), |
787 |
| - [ |
788 |
| - new Arg($node->getArgs()[0]->value), |
789 |
| - new Arg( |
790 |
| - new Expr\Closure( |
791 |
| - [ |
792 |
| - 'static' => true, |
793 |
| - 'params' => [new Param($closureItemVariable)], |
794 |
| - 'stmts' => [ |
795 |
| - new Return_(self::createExpression($scope, $methodName, $closureArgs)), |
796 |
| - ], |
797 |
| - ] |
798 |
| - ) |
799 |
| - ), |
800 |
| - ] |
801 |
| - ) |
802 |
| - ) |
803 |
| - ); |
| 774 | + $args = $node->getArgs(); |
| 775 | + $args[0] = new Arg(new Expr\ArrayDimFetch($args[0]->value, new LNumber(0))); |
| 776 | + $expression = self::createExpression($scope, $methodName, $args); |
| 777 | + if ($expression === null) { |
| 778 | + return new SpecifiedTypes(); |
| 779 | + } |
804 | 780 |
|
805 | 781 | $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition(
|
806 | 782 | $scope,
|
807 | 783 | $expression,
|
808 | 784 | TypeSpecifierContext::createTruthy()
|
809 | 785 | );
|
810 | 786 |
|
811 |
| - if (count($specifiedTypes->getSureTypes()) > 0) { |
812 |
| - $sureTypes = $specifiedTypes->getSureTypes(); |
813 |
| - $exprString = key($sureTypes); |
814 |
| - [$exprNode, $type] = $sureTypes[$exprString]; |
| 787 | + $sureNotTypes = $specifiedTypes->getSureNotTypes(); |
| 788 | + foreach ($specifiedTypes->getSureTypes() as $exprStr => [$exprNode, $type]) { |
| 789 | + if ($exprNode !== $args[0]->value) { |
| 790 | + continue; |
| 791 | + } |
| 792 | + |
| 793 | + $type = TypeCombinator::remove($type, $sureNotTypes[$exprStr][1] ?? new NeverType()); |
815 | 794 |
|
816 | 795 | return $this->arrayOrIterable(
|
817 | 796 | $scope,
|
818 |
| - $exprNode, |
| 797 | + $node->getArgs()[0]->value, |
819 | 798 | static function () use ($type): Type {
|
820 |
| - return $type->getIterableValueType(); |
| 799 | + return $type; |
821 | 800 | }
|
822 | 801 | );
|
823 | 802 | }
|
824 |
| - if (count($specifiedTypes->getSureNotTypes()) > 0) { |
825 |
| - throw new ShouldNotHappenException(); |
826 |
| - } |
827 | 803 |
|
828 | 804 | return $specifiedTypes;
|
829 | 805 | }
|
@@ -861,7 +837,9 @@ private function arrayOrIterable(
|
861 | 837 | return $this->typeSpecifier->create(
|
862 | 838 | $expr,
|
863 | 839 | $specifiedType,
|
864 |
| - TypeSpecifierContext::createTruthy() |
| 840 | + TypeSpecifierContext::createTruthy(), |
| 841 | + false, |
| 842 | + $scope |
865 | 843 | );
|
866 | 844 | }
|
867 | 845 |
|
|
0 commit comments