From 1bb4a05725ba3d3a1f89bb618e2923784679663c Mon Sep 17 00:00:00 2001 From: orklah Date: Sat, 15 May 2021 01:21:01 +0200 Subject: [PATCH] NullsafeMethodCall makes the variable not null for the rest of the scope (#5771) --- .../Statements/Expression/AssertionFinder.php | 19 +++++++++++ tests/TypeReconciliation/TypeAlgebraTest.php | 33 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 0c0277b84..cc890ba45 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -138,6 +138,25 @@ class AssertionFinder ); } + //A nullsafe method call basically adds an assertion !null for the checked variable + if ($conditional instanceof PhpParser\Node\Expr\NullsafeMethodCall) { + $if_types = []; + + $var_name = ExpressionIdentifier::getArrayVarId( + $conditional->var, + $this_class_name, + $source + ); + + if ($var_name) { + $if_types[$var_name] = [['!null']]; + } + + //we may throw a RedundantNullsafeMethodCall here in the future if $var_name is never null + + return $if_types ? [$if_types] : []; + } + if ($conditional instanceof PhpParser\Node\Expr\BinaryOp\Greater || $conditional instanceof PhpParser\Node\Expr\BinaryOp\GreaterOrEqual ) { diff --git a/tests/TypeReconciliation/TypeAlgebraTest.php b/tests/TypeReconciliation/TypeAlgebraTest.php index c36c0e984..cc61399a1 100644 --- a/tests/TypeReconciliation/TypeAlgebraTest.php +++ b/tests/TypeReconciliation/TypeAlgebraTest.php @@ -1077,6 +1077,22 @@ class TypeAlgebraTest extends \Psalm\Tests\TestCase return ""; }' ], + 'notNullAfterSuccessfulNullsafeMethodCall' => [ + 'a()) { + echo $x->b(); + } + }', + [], + [], + '8.1', + ], ]; } @@ -1321,6 +1337,23 @@ class TypeAlgebraTest extends \Psalm\Tests\TestCase }', 'error_message' => 'PossiblyNullReference', ], + 'stillNullAfterNullsafeMethodCall' => [ + 'a())) { + echo $x->b(); + } + }', + 'error_message' => 'NullReference', + [], + false, + '8.1', + ], ]; } }