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

Add support for non-empty scalar

Ref #2449
This commit is contained in:
Brown 2019-12-09 17:06:00 -05:00
parent 447e3539af
commit aaffdbc79f
5 changed files with 181 additions and 0 deletions

View File

@ -1959,6 +1959,57 @@ class AssertionReconciler extends \Psalm\Type\Reconciler
}
}
if ($existing_var_type->hasScalar()) {
if ($existing_var_type->isSingle()
&& $existing_var_atomic_types['scalar'] instanceof Type\Atomic\TNonEmptyScalar
) {
if ($code_location
&& $key
&& IssueBuffer::accepts(
new ParadoxicalCondition(
'Found a paradox when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a ' . $assertion . ' assertion',
$code_location
),
$suppressed_issues
)
) {
// fall through
}
return Type::getScalar();
}
if (!$existing_var_atomic_types['scalar'] instanceof Type\Atomic\TEmptyScalar) {
$did_remove_type = true;
$existing_var_type->removeType('scalar');
if (!$existing_var_atomic_types['scalar'] instanceof Type\Atomic\TNonEmptyScalar) {
$existing_var_type->addType(new Type\Atomic\TEmptyScalar);
}
} elseif ($existing_var_type->isSingle()) {
if ($code_location
&& $key
&& IssueBuffer::accepts(
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
),
$suppressed_issues
)
) {
// fall through
}
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
if ($existing_var_type->hasType('bool')) {
$did_remove_type = true;
$existing_var_type->removeType('bool');

View File

@ -580,6 +580,14 @@ class NegatedAssertionReconciler extends Reconciler
}
}
if ($existing_var_type->hasScalar()) {
$existing_var_type->removeType('scalar');
if (!$existing_var_atomic_types['scalar'] instanceof Type\Atomic\TEmptyScalar) {
$existing_var_type->addType(new Type\Atomic\TNonEmptyScalar);
}
}
self::removeFalsyNegatedLiteralTypes(
$existing_var_type,
$did_remove_type
@ -648,6 +656,36 @@ class NegatedAssertionReconciler extends Reconciler
}
}
if ($existing_var_type->hasScalar()) {
if (!$existing_var_atomic_types['scalar'] instanceof Type\Atomic\TNonEmptyScalar) {
$did_remove_type = true;
$existing_var_type->removeType('scalar');
if (!$existing_var_atomic_types['scalar'] instanceof Type\Atomic\TEmptyScalar) {
$existing_var_type->addType(new Type\Atomic\TNonEmptyScalar);
}
} elseif ($existing_var_type->isSingle() && !$is_equality) {
if ($code_location
&& $key
&& IssueBuffer::accepts(
new RedundantCondition(
'Found a redundant condition when evaluating ' . $key
. ' of type ' . $existing_var_type->getId()
. ' and trying to reconcile it with a non-' . $assertion . ' assertion',
$code_location
),
$suppressed_issues
)
) {
// fall through
}
}
if ($existing_var_type->isSingle()) {
return $existing_var_type;
}
}
if ($existing_var_type->hasType('null')) {
$did_remove_type = true;
$existing_var_type->removeType('null');

View File

@ -1275,6 +1275,16 @@ abstract class Type
return new Union([$type]);
}
/**
* @return Type\Union
*/
public static function getScalar()
{
$type = new TMixed();
return new Union([$type]);
}
/**
* @return Type\Union
*/

View File

@ -0,0 +1,13 @@
<?php
namespace Psalm\Type\Atomic;
class TNonEmptyScalar extends TScalar
{
/**
* @return string
*/
public function getId()
{
return 'non-empty-scalar';
}
}

View File

@ -2200,6 +2200,19 @@ class ConditionalTest extends \Psalm\Tests\TestCase
}
}'
],
'allowEmptyScalarAndNonEmptyScalarAssertions' => [
'<?php
/** @param mixed $value */
function foo($value) : void {
if (\is_scalar($value)) {
if ($value) {
echo $value;
} else {
echo $value;
}
}
}'
],
];
}
@ -2491,6 +2504,62 @@ class ConditionalTest extends \Psalm\Tests\TestCase
}',
'error_message' => 'TypeDoesNotContainType'
],
'allowEmptyScalarAndNonEmptyScalarAssertions1' => [
'<?php
/** @param mixed $value */
function foo($value) : void {
if (\is_scalar($value)) {
if ($value) {
if (\is_scalar($value)) {}
} else {
echo $value;
}
}
}',
'error_message' => 'RedundantCondition',
],
'allowEmptyScalarAndNonEmptyScalarAssertions2' => [
'<?php
/** @param mixed $value */
function foo($value) : void {
if (\is_scalar($value)) {
if ($value) {
echo $value;
} else {
if (\is_scalar($value)) {}
}
}
}',
'error_message' => 'RedundantCondition',
],
'allowEmptyScalarAndNonEmptyScalarAssertions3' => [
'<?php
/** @param mixed $value */
function foo($value) : void {
if (\is_scalar($value)) {
if ($value) {
if ($value) {}
} else {
echo $value;
}
}
}',
'error_message' => 'RedundantCondition',
],
'allowEmptyScalarAndNonEmptyScalarAssertions4' => [
'<?php
/** @param mixed $value */
function foo($value) : void {
if (\is_scalar($value)) {
if ($value) {
echo $value;
} else {
if (!$value) {}
}
}
}',
'error_message' => 'RedundantCondition',
],
];
}
}