From 5954bb88827ae8e4b45ee5db4f430c1ced69818a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 23 Jun 2018 19:24:59 +0200 Subject: [PATCH] Fixed failing tests --- .../AssertTypeSpecifyingExtension.php | 66 ++++++++++++------- .../AssertTypeSpecifyingExtensionTest.php | 2 +- tests/Type/WebMozartAssert/data/data.php | 4 +- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php index 0bd287d..90638cf 100644 --- a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php +++ b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php @@ -11,6 +11,8 @@ use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\ArrayType; +use PHPStan\Type\Constant\ConstantArrayType; +use PHPStan\Type\Constant\ConstantArrayTypeBuilder; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\IterableType; use PHPStan\Type\MixedType; @@ -18,6 +20,7 @@ use PHPStan\Type\StaticMethodTypeSpecifyingExtension; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; +use PHPStan\Type\TypeUtils; class AssertTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension { @@ -109,7 +112,13 @@ public function specifyTypes( reset($sureTypes); $exprString = key($sureTypes); $sureType = $sureTypes[$exprString]; - return $this->arrayOrIterable($scope, $sureType[0], $sureType[1]); + return $this->arrayOrIterable( + $scope, + $sureType[0], + function () use ($sureType): Type { + return $sureType[1]; + } + ); } if (count($specifiedTypes->getSureNotTypes()) > 0) { throw new \PHPStan\ShouldNotHappenException(); @@ -325,12 +334,12 @@ private function handleAllNot( ): SpecifiedTypes { if ($methodName === 'allNotNull') { - $expr = $node->args[0]->value; - $currentType = $scope->getType($expr); return $this->arrayOrIterable( $scope, - $expr, - TypeCombinator::removeNull($currentType->getIterableValueType()) + $node->args[0]->value, + function (Type $type): Type { + return TypeCombinator::removeNull($type); + } ); } elseif ($methodName === 'allNotInstanceOf') { $classType = $scope->getType($node->args[1]->value); @@ -338,26 +347,22 @@ private function handleAllNot( return new SpecifiedTypes([], []); } - $expr = $node->args[0]->value; - $currentType = $scope->getType($expr); + $objectType = new ObjectType($classType->getValue()); return $this->arrayOrIterable( $scope, - $expr, - TypeCombinator::remove( - $currentType->getIterableValueType(), - new ObjectType($classType->getValue()) - ) + $node->args[0]->value, + function (Type $type) use ($objectType): Type { + return TypeCombinator::remove($type, $objectType); + } ); } elseif ($methodName === 'allNotSame') { - $expr = $node->args[0]->value; - $currentType = $scope->getType($expr); + $valueType = $scope->getType($node->args[1]->value); return $this->arrayOrIterable( $scope, - $expr, - TypeCombinator::remove( - $currentType->getIterableValueType(), - $scope->getType($node->args[1]->value) - ) + $node->args[0]->value, + function (Type $type) use ($valueType): Type { + return TypeCombinator::remove($type, $valueType); + } ); } @@ -367,14 +372,29 @@ private function handleAllNot( private function arrayOrIterable( Scope $scope, \PhpParser\Node\Expr $expr, - Type $type + \Closure $typeCallback ): SpecifiedTypes { $currentType = $scope->getType($expr); - if ((new ArrayType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes()) { - $specifiedType = new ArrayType($currentType->getIterableKeyType(), $type); + $arrayTypes = TypeUtils::getArrays($currentType); + if (count($arrayTypes) > 0) { + $newArrayTypes = []; + foreach ($arrayTypes as $arrayType) { + if ($arrayType instanceof ConstantArrayType) { + $builder = ConstantArrayTypeBuilder::createEmpty(); + foreach ($arrayType->getKeyTypes() as $i => $keyType) { + $valueType = $arrayType->getValueTypes()[$i]; + $builder->setOffsetValueType($keyType, $typeCallback($valueType)); + } + $newArrayTypes[] = $builder->getArray(); + } else { + $newArrayTypes[] = new ArrayType($arrayType->getKeyType(), $typeCallback($arrayType->getItemType())); + } + } + + $specifiedType = TypeCombinator::union(...$newArrayTypes); } elseif ((new IterableType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes()) { - $specifiedType = new IterableType($currentType->getIterableKeyType(), $type); + $specifiedType = new IterableType($currentType->getIterableKeyType(), $typeCallback($currentType->getIterableValueType())); } else { return new SpecifiedTypes([], []); } diff --git a/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php b/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php index c68761a..94434f6 100644 --- a/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php +++ b/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php @@ -134,7 +134,7 @@ public function testExtension(): void 100, ], [ - 'Variable $z is: array<0|1|2, 1>', + 'Variable $z is: array(1, -2|2, -3|3)', 107, ], [ diff --git a/tests/Type/WebMozartAssert/data/data.php b/tests/Type/WebMozartAssert/data/data.php index d24d469..080e119 100644 --- a/tests/Type/WebMozartAssert/data/data.php +++ b/tests/Type/WebMozartAssert/data/data.php @@ -99,9 +99,9 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k, Assert::notSame($y, 1); $y; - $z = [1, 1, 1]; + $z = [1, 2, 3]; if (doFoo()) { - $z = [-1, -1, -1]; + $z = [-1, -2, -3]; } Assert::allNotSame($z, -1); $z;