Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 111799b

Browse files
rvanvelzenondrejmirtes
authored andcommitted
Support conditional types in phpdoc asserts
1 parent 26bf11c commit 111799b

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

‎src/Analyser/TypeSpecifier.php‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,17 @@ private function specifyTypesFromAsserts(TypeSpecifierContext $context, Expr\Cal
13131313
continue;
13141314
}
13151315

1316+
$assertedType = TypeTraverser::map($assert->getType(), static function (Type $type, callable $traverse) use ($argsMap, $scope): Type {
1317+
if ($type instanceof ConditionalTypeForParameter) {
1318+
$parameterName = substr($type->getParameterName(), 1);
1319+
if (array_key_exists($parameterName, $argsMap)) {
1320+
$type = $type->toConditional($scope->getType($argsMap[$parameterName]));
1321+
}
1322+
}
1323+
1324+
return $traverse($type);
1325+
});
1326+
13161327
$assertExpr = $assert->getParameter()->getExpr($parameterExpr);
13171328

13181329
$templateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap();
@@ -1334,19 +1345,19 @@ static function (Type $type, callable $traverse) use ($templateTypeMap, &$contai
13341345

13351346
$newTypes = $this->create(
13361347
$assertExpr,
1337-
$assert->getType(),
1348+
$assertedType,
13381349
$assert->isNegated() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createTrue(),
13391350
false,
13401351
$scope,
13411352
$containsUnresolvedTemplate || $assert->isEquality() ? $call : null,
13421353
);
13431354
$types = $types !== null ? $types->unionWith($newTypes) : $newTypes;
13441355

1345-
if (!$context->null() || !$assert->getType() instanceof ConstantBooleanType) {
1356+
if (!$context->null() || !$assertedType instanceof ConstantBooleanType) {
13461357
continue;
13471358
}
13481359

1349-
$subContext = $assert->getType()->getValue() ? TypeSpecifierContext::createTrue() : TypeSpecifierContext::createFalse();
1360+
$subContext = $assertedType->getValue() ? TypeSpecifierContext::createTrue() : TypeSpecifierContext::createFalse();
13501361
if ($assert->isNegated()) {
13511362
$subContext = $subContext->negate();
13521363
}

‎tests/PHPStan/Analyser/NodeScopeResolverTest.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ public function dataFileAsserts(): iterable
10881088
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-methods.php');
10891089
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-intersected.php');
10901090
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-invariant.php');
1091+
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-conditional.php');
10911092
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/docblock-assert-equality.php');
10921093
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8008.php');
10931094
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-class-type.php');
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace AssertConditional;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @phpstan-assert ($if is true ? true : false) $condition
9+
*/
10+
function assertIf(mixed $condition, bool $if)
11+
{
12+
}
13+
14+
function (mixed $value1, mixed $value2) {
15+
assertIf($value1, true);
16+
assertType('true', $value1);
17+
18+
assertIf($value2, false);
19+
assertType('false', $value2);
20+
};
21+
22+
/**
23+
* @template T of bool
24+
* @param T $if
25+
* @phpstan-assert (T is true ? true : false) $condition
26+
*/
27+
function assertIfTemplated(mixed $condition, bool $if)
28+
{
29+
}
30+
31+
function (mixed $value1, mixed $value2) {
32+
assertIfTemplated($value1, true);
33+
assertType('true', $value1);
34+
35+
assertIfTemplated($value2, false);
36+
assertType('false', $value2);
37+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /