Skip to content

Commit 6128361

Browse files
committed
Fixed failing tests
1 parent 50a3dab commit 6128361

6 files changed

+62
-30
lines changed

Diff for: src/Type/BeberleiAssert/AssertHelper.php

+39-23
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
use PHPStan\Analyser\TypeSpecifier;
99
use PHPStan\Analyser\TypeSpecifierContext;
1010
use PHPStan\Type\ArrayType;
11+
use PHPStan\Type\Constant\ConstantArrayType;
12+
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
1113
use PHPStan\Type\Constant\ConstantStringType;
1214
use PHPStan\Type\IterableType;
1315
use PHPStan\Type\MixedType;
1416
use PHPStan\Type\ObjectType;
1517
use PHPStan\Type\Type;
1618
use PHPStan\Type\TypeCombinator;
19+
use PHPStan\Type\TypeUtils;
1720

1821
class AssertHelper
1922
{
@@ -92,7 +95,9 @@ public static function handleAll(
9295
reset($sureTypes);
9396
$exprString = key($sureTypes);
9497
$sureType = $sureTypes[$exprString];
95-
return self::arrayOrIterable($typeSpecifier, $scope, $sureType[0], $sureType[1]);
98+
return self::arrayOrIterable($typeSpecifier, $scope, $sureType[0], function () use ($sureType): Type {
99+
return $sureType[1];
100+
});
96101
}
97102
if (count($specifiedTypes->getSureNotTypes()) > 0) {
98103
throw new \PHPStan\ShouldNotHappenException();
@@ -116,42 +121,38 @@ public static function handleAllNot(
116121
): SpecifiedTypes
117122
{
118123
if ($assertName === 'notNull') {
119-
$expr = $args[0]->value;
120-
$currentType = $scope->getType($expr);
121124
return self::arrayOrIterable(
122125
$typeSpecifier,
123126
$scope,
124-
$expr,
125-
TypeCombinator::removeNull($currentType->getIterableValueType())
127+
$args[0]->value,
128+
function (Type $type): Type {
129+
return TypeCombinator::removeNull($type);
130+
}
126131
);
127132
} elseif ($assertName === 'notIsInstanceOf') {
128133
$classType = $scope->getType($args[1]->value);
129134
if (!$classType instanceof ConstantStringType) {
130135
return new SpecifiedTypes([], []);
131136
}
132137

133-
$expr = $args[0]->value;
134-
$currentType = $scope->getType($expr);
138+
$objectType = new ObjectType($classType->getValue());
135139
return self::arrayOrIterable(
136140
$typeSpecifier,
137141
$scope,
138-
$expr,
139-
TypeCombinator::remove(
140-
$currentType->getIterableValueType(),
141-
new ObjectType($classType->getValue())
142-
)
142+
$args[0]->value,
143+
function (Type $type) use ($objectType): Type {
144+
return TypeCombinator::remove($type, $objectType);
145+
}
143146
);
144147
} elseif ($assertName === 'notSame') {
145-
$expr = $args[0]->value;
146-
$currentType = $scope->getType($expr);
148+
$valueType = $scope->getType($args[1]->value);
147149
return self::arrayOrIterable(
148150
$typeSpecifier,
149151
$scope,
150-
$expr,
151-
TypeCombinator::remove(
152-
$currentType->getIterableValueType(),
153-
$scope->getType($args[1]->value)
154-
)
152+
$args[0]->value,
153+
function (Type $type) use ($valueType): Type {
154+
return TypeCombinator::remove($type, $valueType);
155+
}
155156
);
156157
}
157158

@@ -162,14 +163,29 @@ private static function arrayOrIterable(
162163
TypeSpecifier $typeSpecifier,
163164
Scope $scope,
164165
\PhpParser\Node\Expr $expr,
165-
Type $type
166+
\Closure $typeCallback
166167
): SpecifiedTypes
167168
{
168169
$currentType = $scope->getType($expr);
169-
if ((new ArrayType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes()) {
170-
$specifiedType = new ArrayType($currentType->getIterableKeyType(), $type);
170+
$arrayTypes = TypeUtils::getArrays($currentType);
171+
if (count($arrayTypes) > 0) {
172+
$newArrayTypes = [];
173+
foreach ($arrayTypes as $arrayType) {
174+
if ($arrayType instanceof ConstantArrayType) {
175+
$builder = ConstantArrayTypeBuilder::createEmpty();
176+
foreach ($arrayType->getKeyTypes() as $i => $keyType) {
177+
$valueType = $arrayType->getValueTypes()[$i];
178+
$builder->setOffsetValueType($keyType, $typeCallback($valueType));
179+
}
180+
$newArrayTypes[] = $builder->getArray();
181+
} else {
182+
$newArrayTypes[] = new ArrayType($arrayType->getKeyType(), $typeCallback($arrayType->getItemType()));
183+
}
184+
}
185+
186+
$specifiedType = TypeCombinator::union(...$newArrayTypes);
171187
} elseif ((new IterableType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes()) {
172-
$specifiedType = new IterableType($currentType->getIterableKeyType(), $type);
188+
$specifiedType = new IterableType($currentType->getIterableKeyType(), $typeCallback($currentType->getIterableValueType()));
173189
} else {
174190
return new SpecifiedTypes([], []);
175191
}

Diff for: tests/Type/BeberleiAssert/AssertTypeSpecifyingExtensionTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public function testExtension(): void
170170
97,
171171
],
172172
[
173-
'Variable $z is: array<0|1|2, 1>',
173+
'Variable $z is: array(1, -2|2, -3|3)',
174174
104,
175175
],
176176
[

Diff for: tests/Type/BeberleiAssert/ImpossibleCheckTypeMethodCallRuleTest.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,16 @@ public function getDynamicStaticMethodReturnTypeExtensions(): array
4646

4747
public function testExtension(): void
4848
{
49-
self::markTestIncomplete('Does not work yet - needs to rework ImpossibleCheckType rules, dynamic return type extension now has priority when resolving return type.');
50-
$this->analyse([__DIR__ . '/data/impossible-check.php'], []);
49+
$this->analyse([__DIR__ . '/data/impossible-check.php'], [
50+
[
51+
'Call to method Assert\AssertionChain::string() will always evaluate to true.',
52+
12,
53+
],
54+
[
55+
'Call to method Assert\AssertionChain::string() will always evaluate to true.',
56+
16,
57+
],
58+
]);
5159
}
5260

5361
}

Diff for: tests/Type/BeberleiAssert/ImpossibleCheckTypeStaticMethodCallRuleTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ protected function getRule(): Rule
1414
return new ImpossibleCheckTypeStaticMethodCallRule(new ImpossibleCheckTypeHelper($this->getTypeSpecifier()), true);
1515
}
1616

17+
1718
/**
1819
* @return \PHPStan\Type\StaticMethodTypeSpecifyingExtension[]
1920
*/
@@ -33,7 +34,7 @@ public function testExtension(): void
3334
],
3435
[
3536
'Call to static method Assert\Assertion::allString() with array<string> will always evaluate to true.',
36-
14,
37+
21,
3738
],
3839
]);
3940
}

Diff for: tests/Type/BeberleiAssert/data/data.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k,
9696
Assertion::notSame($y, 1);
9797
$y;
9898

99-
$z = [1, 1, 1];
99+
$z = [1, 2, 3];
100100
if (doFoo()) {
101-
$z = [-1, -1, -1];
101+
$z = [-1, -2, -3];
102102
}
103103
Assertion::allNotSame($z, -1);
104104
$z;

Diff for: tests/Type/BeberleiAssert/data/impossible-static-check.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@ public function doFoo(string $a, array $b)
1111
{
1212
Assertion::string($a);
1313
Assertion::allString($b);
14-
Assertion::allString($b);
14+
}
15+
16+
/**
17+
* @param string[] $strings
18+
*/
19+
public function doBar(array $strings)
20+
{
21+
Assertion::allString($strings);
1522
}
1623

1724
}

0 commit comments

Comments
 (0)