1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Improve handling of negated boolean operations

This commit is contained in:
Brown 2019-04-12 11:26:33 -04:00
parent b6d0ee0777
commit 8751bf232b
2 changed files with 68 additions and 23 deletions

View File

@ -127,18 +127,50 @@ class Algebra
return self::combineOredClauses($left_clauses, $right_clauses);
}
if ($conditional instanceof PhpParser\Node\Expr\BooleanNot
&& $conditional->expr instanceof PhpParser\Node\Expr\BinaryOp
) {
$negated_clauses = self::getFormula(
$conditional->expr,
$this_class_name,
$source,
$codebase,
!$inside_negation
);
if ($conditional instanceof PhpParser\Node\Expr\BooleanNot) {
if ($conditional->expr instanceof PhpParser\Node\Expr\BinaryOp\BooleanOr) {
$and_expr = new PhpParser\Node\Expr\BinaryOp\BooleanAnd(
new PhpParser\Node\Expr\BooleanNot(
$conditional->expr->left,
$conditional->getAttributes()
),
new PhpParser\Node\Expr\BooleanNot(
$conditional->expr->right,
$conditional->getAttributes()
),
$conditional->expr->getAttributes()
);
return self::negateFormula($negated_clauses);
return self::getFormula(
$and_expr,
$this_class_name,
$source,
$codebase,
$inside_negation
);
}
if ($conditional->expr instanceof PhpParser\Node\Expr\BinaryOp\BooleanAnd) {
$and_expr = new PhpParser\Node\Expr\BinaryOp\BooleanOr(
new PhpParser\Node\Expr\BooleanNot(
$conditional->expr->left,
$conditional->getAttributes()
),
new PhpParser\Node\Expr\BooleanNot(
$conditional->expr->right,
$conditional->getAttributes()
),
$conditional->expr->getAttributes()
);
return self::getFormula(
$and_expr,
$this_class_name,
$source,
$codebase,
$inside_negation
);
}
}
AssertionFinder::scrapeAssertions(

View File

@ -904,19 +904,32 @@ class TypeAlgebraTest extends TestCase
],
'invertEquation' => [
'<?php
/**
* @param mixed $width
* @param mixed $height
*
* @throws RuntimeException
*/
function Foo($width, $height) : void {
if (!(is_int($width) || is_float($width)) || !(is_int($height) || is_float($height))) {
throw new RuntimeException("bad");
}
/**
* @param mixed $width
* @param mixed $height
*
* @throws RuntimeException
*/
function Foo($width, $height) : void {
if (!(is_int($width) || is_float($width)) || !(is_int($height) || is_float($height))) {
throw new RuntimeException("bad");
}
echo sprintf("padding-top:%s%%;", 100 * ($height/$width));
}'
echo sprintf("padding-top:%s%%;", 100 * ($height/$width));
}'
],
'invertLogic' => [
'<?php
class A {}
class B extends A {}
function foo(?A $a) : A {
if (!$a || !($a instanceof B && rand(0, 1))) {
throw new Exception();
}
return $a;
}'
],
];
}