1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Merge pull request #9685 from Nicelocal/avoid_wrong_assertions

Avoid wrong assertions when working with objects returned by methods
This commit is contained in:
orklah 2023-04-21 11:34:15 +02:00 committed by GitHub
commit a97b6b8a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 16 deletions

View File

@ -42,10 +42,13 @@ use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Union;
use UnexpectedValueException;
use function array_filter;
use function array_map;
use function count;
use function explode;
use function in_array;
use function is_string;
use function strpos;
use function strtolower;
/**
@ -422,30 +425,48 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
}
if ($method_storage->if_true_assertions) {
$possibilities = array_map(
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
$template_result,
$lhs_var_id,
$codebase,
),
$method_storage->if_true_assertions,
);
if ($lhs_var_id === null) {
$possibilities = array_filter(
$possibilities,
static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id)
&& strpos($assertion->var_id, '$this->') === 0
)
);
}
$statements_analyzer->node_data->setIfTrueAssertions(
$stmt,
array_map(
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
$template_result,
$lhs_var_id,
$codebase,
),
$method_storage->if_true_assertions,
),
$possibilities,
);
}
if ($method_storage->if_false_assertions) {
$possibilities = array_map(
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
$template_result,
$lhs_var_id,
$codebase,
),
$method_storage->if_false_assertions,
);
if ($lhs_var_id === null) {
$possibilities = array_filter(
$possibilities,
static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id)
&& strpos($assertion->var_id, '$this->') === 0
)
);
}
$statements_analyzer->node_data->setIfFalseAssertions(
$stmt,
array_map(
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
$template_result,
$lhs_var_id,
$codebase,
),
$method_storage->if_false_assertions,
),
$possibilities,
);
}
}

View File

@ -2007,6 +2007,30 @@ class AssertAnnotationTest extends TestCase
function requiresString(string $_str): void {}
',
],
'assertionOnPropertyReturnedByMethod' => [
'code' => '<?php
class a {
public ?int $id = null;
/**
* @psalm-mutation-free
*
* @psalm-assert-if-true !null $this->id
*/
public function isExists(): bool {
return $this->id !== null;
}
}
class b {
public ?int $id = null;
public function __construct(private a $a) {
if ($this->getA()->isExists()) {
/** @psalm-check-type-exact $this->id = ?int */
}
}
public function getA(): a { return $this->a; }
}',
],
'assertWithEmptyStringOnKeyedArray' => [
'code' => '<?php
class A