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

Clone isset type before contradicting

This commit is contained in:
Brown 2020-01-14 18:28:32 -05:00
parent 3fd70a9c88
commit 0f6b61d62d
3 changed files with 49 additions and 10 deletions

View File

@ -777,7 +777,7 @@ class BinaryOpAnalyzer
if ($stmt_left_type = $statements_analyzer->node_data->getType($stmt->left)) {
$if_return_type_reconciled = AssertionReconciler::reconcile(
'!null',
$stmt_left_type,
clone $stmt_left_type,
'',
$statements_analyzer,
$context->inside_loop,
@ -786,7 +786,7 @@ class BinaryOpAnalyzer
$statements_analyzer->getSuppressedIssues()
);
$lhs_type = $if_return_type_reconciled;
$lhs_type = clone $if_return_type_reconciled;
}
$stmt_right_type = null;

View File

@ -9,6 +9,7 @@ use Psalm\CodeLocation;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TraitAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;
use Psalm\Issue\DocblockTypeContradiction;
use Psalm\Issue\ParadoxicalCondition;
use Psalm\Issue\RedundantCondition;
use Psalm\Issue\TypeDoesNotContainType;
@ -104,14 +105,28 @@ class NegatedAssertionReconciler extends Reconciler
$failed_reconciliation = 2;
if ($code_location) {
if (IssueBuffer::accepts(
new TypeDoesNotContainType(
'Cannot resolve types for ' . $key . ' and !isset assertion',
$code_location
),
$suppressed_issues
)) {
// fall through
if ($existing_var_type->from_docblock) {
if (IssueBuffer::accepts(
new DocblockTypeContradiction(
'Cannot resolve types for ' . $key . ' with docblock-defined type '
. $existing_var_type . ' and !isset assertion',
$code_location
),
$suppressed_issues
)) {
// fall through
}
} else {
if (IssueBuffer::accepts(
new TypeDoesNotContainType(
'Cannot resolve types for ' . $key . ' with type '
. $existing_var_type . ' and !isset assertion',
$code_location
),
$suppressed_issues
)) {
}
}
}

View File

@ -742,6 +742,30 @@ class IssetTest extends \Psalm\Tests\TestCase
return "bar";
}',
],
'issetOnMethodCallInsideFunctionCall' => [
'<?php
class C {
public function foo() : ?string {
return null;
}
}
function foo(C $c) : void {
strlen($c->foo() ?? "");
}'
],
'issetOnMethodCallInsideMethodCall' => [
'<?php
class C {
public function foo() : ?string {
return null;
}
}
function foo(C $c) : void {
new DateTime($c->foo() ?? "");
}'
],
];
}