1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Merge pull request #9647 from tuqqu/match-branch-flattening

Flatten `match` arm conditions to check conditions independently
This commit is contained in:
orklah 2023-04-13 10:52:11 +02:00 committed by GitHub
commit cb6508e63c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 6 deletions

View File

@ -128,18 +128,27 @@ class MatchAnalyzer
}
$arms = $stmt->arms;
$flattened_arms = [];
$last_arm = null;
foreach ($arms as $i => $arm) {
// move default to the end
foreach ($arms as $arm) {
if ($arm->conds === null) {
unset($arms[$i]);
$arms[] = $arm;
$last_arm = $arm;
continue;
}
foreach ($arm->conds as $cond) {
$flattened_arms[] = new PhpParser\Node\MatchArm(
[$cond],
$arm->body,
$arm->getAttributes(),
);
}
}
$arms = $flattened_arms;
$arms = array_reverse($arms);
$last_arm = array_shift($arms);
$last_arm ??= array_shift($arms);
if (!$last_arm) {
IssueBuffer::maybeAdd(

View File

@ -95,6 +95,44 @@ class MatchTest extends TestCase
'ignored_issues' => [],
'php_version' => '8.1',
],
'multipleInstanceOfConditionsInOneArm' => [
'code' => '<?php
interface Foo {}
class A implements Foo {}
class B implements Foo {}
class C {}
function baz(A|B $_): int {
return 1;
}
function bar(Foo $foo): int {
return match (true) {
$foo instanceof A, $foo instanceof B => baz($foo),
$foo instanceof C => 3,
default => 0,
};
}',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.0',
],
'multipleTypeCheckConditionsInOneArm' => [
'code' => '<?php
function baz(int|string $_): int {
return 1;
}
function bar(mixed $foo): int {
return match (true) {
is_string($foo), is_int($foo) => baz($foo),
default => 0,
};
}',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.0',
],
];
}
@ -243,6 +281,28 @@ class MatchTest extends TestCase
'ignored_issues' => [],
'php_version' => '8.0',
],
'multipleInstanceOfConditionsNotMetInOneArm' => [
'code' => '<?php
interface Foo {}
class A implements Foo {}
class B implements Foo {}
class C {}
function baz(C $_): int {
return 1;
}
function bar(Foo $foo): int {
return match (true) {
$foo instanceof A, $foo instanceof B => baz($foo),
$foo instanceof C => 3,
default => 0,
};
}',
'error_message' => 'InvalidArgument',
'ignored_issues' => [],
'php_version' => '8.0',
],
];
}
}