diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index aa585f5568a..dc2d5e12d8a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -670,6 +670,7 @@ public static function analyze( if ($function_storage->assertions && $stmt->name instanceof PhpParser\Node\Name) { self::applyAssertionsToContext( $stmt->name, + null, $function_storage->assertions, $stmt->args, $generic_params ?: [], diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php index 373545176db..8f172682452 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php @@ -39,11 +39,13 @@ use function is_string; use function array_values; use function array_shift; +use function array_unshift; use function get_class; use function strtolower; use function array_map; use function array_merge; use function explode; +use function implode; use function array_search; use function array_keys; use function in_array; @@ -1306,6 +1308,7 @@ function (PhpParser\Node\Arg $arg) { if ($method_storage->assertions) { self::applyAssertionsToContext( $stmt->name, + ExpressionAnalyzer::getArrayVarId($stmt->var, null, $statements_analyzer), $method_storage->assertions, $args, $class_template_params ?: [], diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php index 0a40a7699e2..1ed21e89281 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php @@ -905,6 +905,7 @@ function (PhpParser\Node\Arg $arg) { if ($method_storage->assertions) { self::applyAssertionsToContext( $stmt->name, + null, $method_storage->assertions, $stmt->args, $found_generic_params ?: [], diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 7376eb43d2d..d8479ae1ac4 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -50,10 +50,12 @@ use function in_array; use function array_reverse; use function array_filter; +use function is_null; use function is_string; use function assert; use function preg_match; use function preg_replace; +use function str_replace; use function is_int; use function substr; use function array_merge; @@ -3187,6 +3189,7 @@ protected static function checkFunctionExists( /** * @param PhpParser\Node\Identifier|PhpParser\Node\Name $expr * @param \Psalm\Storage\Assertion[] $assertions + * @param string $thisName * @param array $args * @param Context $context * @param array> $template_type_map, @@ -3196,6 +3199,7 @@ protected static function checkFunctionExists( */ protected static function applyAssertionsToContext( $expr, + ?string $thisName, array $assertions, array $args, array $template_type_map, @@ -3225,6 +3229,8 @@ protected static function applyAssertionsToContext( } } elseif (isset($context->vars_in_scope[$assertion->var_id])) { $assertion_var_id = $assertion->var_id; + } elseif (strpos($assertion->var_id, '$this->') === 0 && !is_null($thisName)) { + $assertion_var_id = $thisName . str_replace('$this->', '->', $assertion->var_id); } if ($assertion_var_id) { diff --git a/tests/AssertTest.php b/tests/AssertTest.php index df3a80eecbd..5c6af25488a 100644 --- a/tests/AssertTest.php +++ b/tests/AssertTest.php @@ -685,6 +685,32 @@ public function assertProperty() : bool { } }' ], + 'assertPropertyVisibleOutside' => [ + 'x = 0; + } + } + + /** + * @psalm-assert !null $this->x + */ + public function assertProperty() : void { + if (is_null($this->x)) { + throw new RuntimeException(); + } + } + } + + $a = new A(); + $a->maybeAssignX(); + $a->assertProperty(); + echo (2 * $a->x);', + ], ]; }