Skip to content
Permalink
Browse files

Fix mixed method issues after defining new type

  • Loading branch information
muglug committed Dec 8, 2019
1 parent 83b10bb commit c9f43782fd72757910ff98e6d6e46e4db7d6b748
@@ -1079,6 +1079,10 @@ private static function scrapeInequalityAssertions(
);

if ($var_name) {
if ($base_conditional instanceof PhpParser\Node\Expr\Assign) {
$var_name = '=' . $var_name;
}

if ($conditional instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical) {
$if_types[$var_name] = [['!null']];
} else {
@@ -231,7 +231,7 @@ function ($c) use ($reconciled_expression_clauses) {
}

$if_context->reconciled_expression_clauses = array_merge(
$context->if_context->reconciled_expression_clauses,
$if_context->reconciled_expression_clauses,
array_map(
function ($c) {
return $c->getHash();
@@ -60,18 +60,28 @@ class Clause
/** @var bool */
public $generated = false;

/** @var array<string, bool> */
public $redefined_vars = [];

/**
* @param array<string, non-empty-list<string>> $possibilities
* @param bool $wedge
* @param bool $reconcilable
* @param bool $generated
* @param array<string, bool> $redefined_vars
*/
public function __construct(array $possibilities, $wedge = false, $reconcilable = true, $generated = false)
{
public function __construct(
array $possibilities,
$wedge = false,
$reconcilable = true,
$generated = false,
array $redefined_vars = []
) {
$this->possibilities = $possibilities;
$this->wedge = $wedge;
$this->reconcilable = $reconcilable;
$this->generated = $generated;
$this->redefined_vars = $redefined_vars;
}

/**
@@ -199,6 +199,14 @@ public static function getFormula(
$clauses = [];

foreach ($assertions as $var => $anded_types) {
$redefined = false;

if ($var[0] === '=') {
/** @var string */
$var = substr($var, 1);
$redefined = true;
}

foreach ($anded_types as $orred_types) {
$clauses[] = new Clause(
[$var => $orred_types],
@@ -208,7 +216,8 @@ public static function getFormula(
|| $orred_types[0][0] === '~'
|| (strlen($orred_types[0]) > 1
&& ($orred_types[0][1] === '='
|| $orred_types[0][1] === '~'))
|| $orred_types[0][1] === '~')),
$redefined ? [$var => true] : []
);
}
}
@@ -300,6 +309,14 @@ public static function getFormula(
$clauses = [];

foreach ($assertions as $var => $anded_types) {
$redefined = false;

if ($var[0] === '=') {
/** @var string */
$var = substr($var, 1);
$redefined = true;
}

foreach ($anded_types as $orred_types) {
$clauses[] = new Clause(
[$var => $orred_types],
@@ -309,7 +326,8 @@ public static function getFormula(
|| $orred_types[0][0] === '~'
|| (strlen($orred_types[0]) > 1
&& ($orred_types[0][1] === '='
|| $orred_types[0][1] === '~'))
|| $orred_types[0][1] === '~')),
$redefined ? [$var => true] : []
);
}
}
@@ -462,7 +480,7 @@ public static function getTruthsFromFormula(
foreach ($clause->possibilities as $var => $possible_types) {
// if there's only one possible type, return it
if (count($clause->possibilities) === 1 && count($possible_types) === 1) {
if (isset($truths[$var])) {
if (isset($truths[$var]) && !isset($clause->redefined_vars[$var])) {
$truths[$var][] = [array_pop($possible_types)];
} else {
$truths[$var] = [[array_pop($possible_types)]];
@@ -1855,6 +1855,23 @@ function exampleWithAnd($value): O {
return new O();
}'
],
'assertVarRedefinedInIfWithAndAndMethodCall' => [
'<?php
class O {
public function foo() : bool { return true; }
}
/**
* @param mixed $value
*/
function anotherExampleWithAnd($value): O {
if (is_string($value) && (($value = rand(0, 1) ? new O : null) !== null) && $value->foo()) {
return $value;
}
return new O();
}'
],
'SKIPPED-assertVarRedefinedInIfWithOr' => [
'<?php
class O {}
@@ -1898,7 +1915,7 @@ public function foo() : bool { return true; }
/** @var mixed */
$value = $_GET["foo"];
$a = is_string($value) && (($valu = rand(0, 1) ? new O : null) !== null) && $valu->foo();',
$a = is_string($value) && (($value = rand(0, 1) ? new O : null) !== null) && $value->foo();',
[
'$a' => 'bool',
]

0 comments on commit c9f4378

Please sign in to comment.
You can’t perform that action at this time.