mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Mutation checks should not care about return type
This commit is contained in:
parent
ae69695f89
commit
9442805763
@ -62,7 +62,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
protected $source;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, Type\Union>>
|
||||
* @var ?array<string, Type\Union>
|
||||
*/
|
||||
protected $return_vars_in_scope = [];
|
||||
|
||||
@ -72,7 +72,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
protected $possible_param_types = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool>>
|
||||
* @var ?array<string, bool>
|
||||
*/
|
||||
protected $return_vars_possibly_in_scope = [];
|
||||
|
||||
@ -582,7 +582,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($context->collect_initializations) {
|
||||
if ($context->collect_initializations || $context->collect_mutations) {
|
||||
$statements_analyzer->addSuppressedIssues([
|
||||
'DocblockTypeContradiction',
|
||||
'InvalidReturnStatement',
|
||||
@ -854,17 +854,17 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
}
|
||||
|
||||
if ($add_mutations) {
|
||||
if (isset($this->return_vars_in_scope[''])) {
|
||||
if ($this->return_vars_in_scope !== null) {
|
||||
$context->vars_in_scope = TypeAnalyzer::combineKeyedTypes(
|
||||
$context->vars_in_scope,
|
||||
$this->return_vars_in_scope['']
|
||||
$this->return_vars_in_scope
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($this->return_vars_possibly_in_scope[''])) {
|
||||
if ($this->return_vars_possibly_in_scope !== null) {
|
||||
$context->vars_possibly_in_scope = array_merge(
|
||||
$context->vars_possibly_in_scope,
|
||||
$this->return_vars_possibly_in_scope['']
|
||||
$this->return_vars_possibly_in_scope
|
||||
);
|
||||
}
|
||||
|
||||
@ -967,24 +967,24 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addReturnTypes($return_type, Context $context)
|
||||
public function addReturnTypes(Context $context)
|
||||
{
|
||||
if (isset($this->return_vars_in_scope[$return_type])) {
|
||||
$this->return_vars_in_scope[$return_type] = TypeAnalyzer::combineKeyedTypes(
|
||||
if ($this->return_vars_in_scope !== null) {
|
||||
$this->return_vars_in_scope = TypeAnalyzer::combineKeyedTypes(
|
||||
$context->vars_in_scope,
|
||||
$this->return_vars_in_scope[$return_type]
|
||||
$this->return_vars_in_scope
|
||||
);
|
||||
} else {
|
||||
$this->return_vars_in_scope[$return_type] = $context->vars_in_scope;
|
||||
$this->return_vars_in_scope = $context->vars_in_scope;
|
||||
}
|
||||
|
||||
if (isset($this->return_vars_possibly_in_scope[$return_type])) {
|
||||
$this->return_vars_possibly_in_scope[$return_type] = array_merge(
|
||||
if ($this->return_vars_possibly_in_scope !== null) {
|
||||
$this->return_vars_possibly_in_scope = array_merge(
|
||||
$context->vars_possibly_in_scope,
|
||||
$this->return_vars_possibly_in_scope[$return_type]
|
||||
$this->return_vars_possibly_in_scope
|
||||
);
|
||||
} else {
|
||||
$this->return_vars_possibly_in_scope[$return_type] = $context->vars_possibly_in_scope;
|
||||
$this->return_vars_possibly_in_scope = $context->vars_possibly_in_scope;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,10 +119,7 @@ class ReturnAnalyzer
|
||||
if ($source instanceof FunctionLikeAnalyzer
|
||||
&& !($source->getSource() instanceof TraitAnalyzer)
|
||||
) {
|
||||
$source->addReturnTypes(
|
||||
$stmt->expr ? (string) $stmt->inferredType : '',
|
||||
$context
|
||||
);
|
||||
$source->addReturnTypes($context);
|
||||
|
||||
$source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt);
|
||||
|
||||
|
@ -106,6 +106,51 @@ class MethodMutationTest extends TestCase
|
||||
$this->assertTrue($method_context->vars_possibly_in_scope['$this->title']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testNotSettingUser()
|
||||
{
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
class User {}
|
||||
|
||||
class FooController {
|
||||
/** @var User|null */
|
||||
public $user;
|
||||
|
||||
public function doThingWithUser(): array
|
||||
{
|
||||
if (!$this->user) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ["hello"];
|
||||
}
|
||||
|
||||
public function barBar(): void {
|
||||
$this->user = rand(0, 1) ? new User() : null;
|
||||
|
||||
$this->doThingWithUser();
|
||||
}
|
||||
}'
|
||||
);
|
||||
|
||||
new FileAnalyzer($this->project_analyzer, 'somefile.php', 'somefile.php');
|
||||
$this->project_analyzer->getCodebase()->scanFiles();
|
||||
$method_context = new Context();
|
||||
$method_context->collect_mutations = true;
|
||||
$this->project_analyzer->getMethodMutations(
|
||||
'FooController::barBar',
|
||||
$method_context,
|
||||
'somefile.php',
|
||||
'somefile.php'
|
||||
);
|
||||
|
||||
$this->assertSame('null|User', (string)$method_context->vars_in_scope['$this->user']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user