1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

improve empty/falsy

This commit is contained in:
orklah 2021-10-21 18:10:20 +02:00
parent 7f5a0245bf
commit 4b0e3d0c06
2 changed files with 36 additions and 148 deletions

View File

@ -118,7 +118,7 @@ class ProtocolStreamReader implements ProtocolReader
$this->emit('message', [$msg]);
/**
* @psalm-suppress DocblockTypeContradiction
* @psalm-suppress ParadoxicalCondition
* @psalm-suppress RedundantConditionGivenDocblockType
*/
if (!$this->is_accepting_new_requests) {
// If we fork, don't read any bytes in the input buffer from the worker process.

View File

@ -48,6 +48,7 @@ use Psalm\Type\Atomic\TString;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Union;
use function assert;
use function count;
use function explode;
use function get_class;
@ -2244,26 +2245,18 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
}
if ($did_remove_type && $existing_var_type->getAtomicTypes() === []) {
//every type was removed, this is an impossible assertion
if ($code_location && $key) {
if ($existing_var_type->from_docblock) {
$issue = new DocblockTypeContradiction(
'Found a paradox when evaluating ' . $key
. ' of type ' . $old_var_type_string
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
null
);
} else {
$issue = new ParadoxicalCondition(
'Found a paradox when evaluating ' . $key
. ' of type ' . $old_var_type_string
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location
);
}
if (IssueBuffer::accepts($issue, $suppressed_issues)) {
// fall through
}
self::triggerIssueForImpossible(
$existing_var_type,
$old_var_type_string,
$key,
$assertion,
false,
$negated,
$code_location,
$suppressed_issues
);
}
$failed_reconciliation = 2;
@ -2271,6 +2264,26 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
return Type::getEmpty();
}
if (!$did_remove_type) {
//nothing was removed, this is a redundant assertion
if ($code_location && $key) {
self::triggerIssueForImpossible(
$existing_var_type,
$old_var_type_string,
$key,
$assertion,
true,
$negated,
$code_location,
$suppressed_issues
);
}
$failed_reconciliation = 1;
return $existing_var_type;
}
if ($existing_var_type->hasType('bool')) {
$existing_var_type->removeType('bool');
$existing_var_type->addType(new TFalse());
@ -2292,33 +2305,6 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
if (get_class($mixed_atomic_type) === TMixed::class) {
$existing_var_type->removeType('mixed');
$existing_var_type->addType(new TEmptyMixed());
} elseif ($existing_var_type->isSingle() && $mixed_atomic_type instanceof TEmptyMixed) {
if ($code_location && $key && !$did_remove_type) {
if ($existing_var_type->from_docblock) {
$issue = new RedundantConditionGivenDocblockType(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
} else {
$issue = new RedundantCondition(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
}
if (IssueBuffer::accepts($issue, $suppressed_issues)) {
// fall through
}
}
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
@ -2328,35 +2314,6 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
if (get_class($scalar_atomic_type) === TScalar::class) {
$existing_var_type->removeType('scalar');
$existing_var_type->addType(new TEmptyScalar());
} elseif ($existing_var_type->isSingle() &&
$scalar_atomic_type instanceof TEmptyScalar
) {
if ($code_location && $key && !$did_remove_type) {
if ($existing_var_type->from_docblock) {
$issue = new RedundantConditionGivenDocblockType(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
} else {
$issue = new RedundantCondition(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
}
if (IssueBuffer::accepts($issue, $suppressed_issues)) {
// fall through
}
}
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
@ -2376,33 +2333,6 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
} elseif (get_class($string_atomic_type) === TNonEmptyNonspecificLiteralString::class) {
$existing_var_type->removeType('string');
$existing_var_type->addType(new TLiteralString('0'));
} elseif ($existing_var_type->isSingle() && $string_atomic_type instanceof TNonFalsyString) {
if ($code_location && $key && !$did_remove_type) {
if ($existing_var_type->from_docblock) {
$issue = new RedundantConditionGivenDocblockType(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
} else {
$issue = new RedundantCondition(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location,
$existing_var_type->getId() . ' ' . $assertion
);
}
if (IssueBuffer::accepts($issue, $suppressed_issues)) {
// fall through
}
}
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
@ -2420,28 +2350,16 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
$existing_var_type->removeType('int');
$existing_var_type->addType(new TLiteralInt(0));
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
if ($existing_var_type->hasFloat()) {
$existing_var_type->removeType('float');
$existing_var_type->addType(new TLiteralFloat(0.0));
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
if ($existing_var_type->hasNumeric()) {
$existing_var_type->removeType('numeric');
$existing_var_type->addType(new TEmptyNumeric());
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
foreach ($existing_var_atomic_types as $existing_var_atomic_type) {
@ -2461,8 +2379,6 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
$template_did_fail
);
$did_remove_type = true;
if (!$template_did_fail) {
$existing_var_type->addType($existing_var_atomic_type);
}
@ -2470,36 +2386,8 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
}
}
if ((!$did_remove_type || empty($existing_var_type->getAtomicTypes()))
&& ($assertion !== 'empty' || !$existing_var_type->possibly_undefined)
) {
if ($key && $code_location) {
self::triggerIssueForImpossible(
$existing_var_type,
$old_var_type_string,
$key,
$assertion,
!$did_remove_type,
$negated,
$code_location,
$suppressed_issues
);
}
if (!$did_remove_type) {
$failed_reconciliation = 1;
}
}
/** @psalm-suppress RedundantCondition can be empty after removing above */
if ($existing_var_type->getAtomicTypes()) {
return $existing_var_type;
}
$failed_reconciliation = 2;
return $assertion === 'empty' && $existing_var_type->possibly_undefined
? Type::getEmpty()
: Type::getMixed();
/** @psalm-suppress RedundantCondition safety check in case we removed something that shouldn't be removed */
assert($existing_var_type->getAtomicTypes() !== []);
return $existing_var_type;
}
}