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:
commit
cb6508e63c
@ -128,18 +128,27 @@ class MatchAnalyzer
|
|||||||
}
|
}
|
||||||
|
|
||||||
$arms = $stmt->arms;
|
$arms = $stmt->arms;
|
||||||
|
$flattened_arms = [];
|
||||||
|
$last_arm = null;
|
||||||
|
|
||||||
foreach ($arms as $i => $arm) {
|
foreach ($arms as $arm) {
|
||||||
// move default to the end
|
|
||||||
if ($arm->conds === null) {
|
if ($arm->conds === null) {
|
||||||
unset($arms[$i]);
|
$last_arm = $arm;
|
||||||
$arms[] = $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);
|
$arms = array_reverse($arms);
|
||||||
|
$last_arm ??= array_shift($arms);
|
||||||
$last_arm = array_shift($arms);
|
|
||||||
|
|
||||||
if (!$last_arm) {
|
if (!$last_arm) {
|
||||||
IssueBuffer::maybeAdd(
|
IssueBuffer::maybeAdd(
|
||||||
|
@ -95,6 +95,44 @@ class MatchTest extends TestCase
|
|||||||
'ignored_issues' => [],
|
'ignored_issues' => [],
|
||||||
'php_version' => '8.1',
|
'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' => [],
|
'ignored_issues' => [],
|
||||||
'php_version' => '8.0',
|
'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',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user