mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Use more accurate means of determining whether function did return
This commit is contained in:
parent
7195ea6842
commit
5395183837
@ -1761,7 +1761,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$class_storage,
|
||||
$class_context->self,
|
||||
$analyzed_method_id,
|
||||
$actual_method_id
|
||||
$actual_method_id,
|
||||
$method_context->has_returned
|
||||
);
|
||||
}
|
||||
|
||||
@ -1785,7 +1786,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
ClassLikeStorage $class_storage,
|
||||
string $fq_classlike_name,
|
||||
\Psalm\Internal\MethodIdentifier $analyzed_method_id,
|
||||
\Psalm\Internal\MethodIdentifier $actual_method_id
|
||||
\Psalm\Internal\MethodIdentifier $actual_method_id,
|
||||
bool $did_explicitly_return
|
||||
) : void {
|
||||
$secondary_return_type_location = null;
|
||||
|
||||
@ -1892,7 +1894,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$interface_return_type,
|
||||
$interface_class,
|
||||
$interface_return_type_location,
|
||||
[$analyzed_method_id]
|
||||
[$analyzed_method_id],
|
||||
$did_explicitly_return
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1910,7 +1913,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$return_type,
|
||||
$fq_classlike_name,
|
||||
$return_type_location,
|
||||
$overridden_method_ids
|
||||
$overridden_method_ids,
|
||||
$did_explicitly_return
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ class ReturnTypeAnalyzer
|
||||
$fq_class_name = null,
|
||||
CodeLocation $return_type_location = null,
|
||||
array $compatible_method_ids = [],
|
||||
bool $did_explicitly_return = false,
|
||||
bool $closure_inside_call = false
|
||||
) {
|
||||
$suppressed_issues = $function_like_analyzer->getSuppressedIssues();
|
||||
@ -137,6 +138,10 @@ class ReturnTypeAnalyzer
|
||||
true
|
||||
);
|
||||
|
||||
if (!$inferred_return_type_parts) {
|
||||
$did_explicitly_return = true;
|
||||
}
|
||||
|
||||
if ((!$return_type || $return_type->from_docblock)
|
||||
&& ScopeAnalyzer::getFinalControlActions(
|
||||
$function_stmts,
|
||||
@ -145,6 +150,7 @@ class ReturnTypeAnalyzer
|
||||
) !== [ScopeAnalyzer::ACTION_END]
|
||||
&& !$inferred_yield_types
|
||||
&& count($inferred_return_type_parts)
|
||||
&& !$did_explicitly_return
|
||||
) {
|
||||
// only add null if we have a return statement elsewhere and it wasn't void
|
||||
foreach ($inferred_return_type_parts as $inferred_return_type_part) {
|
||||
@ -324,6 +330,7 @@ class ReturnTypeAnalyzer
|
||||
$source,
|
||||
$function_like_analyzer,
|
||||
$compatible_method_ids
|
||||
|| !$did_explicitly_return
|
||||
|| (($project_analyzer->only_replace_php_types_with_non_docblock_types
|
||||
|| $unsafe_return_type)
|
||||
&& $inferred_return_type->from_docblock),
|
||||
|
@ -35,12 +35,8 @@ class ReturnTypeCollector
|
||||
) {
|
||||
$return_types = [];
|
||||
|
||||
$had_explicit_return = [];
|
||||
|
||||
foreach ($stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Return_) {
|
||||
$had_explicit_return = true;
|
||||
|
||||
if ($stmt->expr instanceof PhpParser\Node\Expr\Yield_ ||
|
||||
$stmt->expr instanceof PhpParser\Node\Expr\YieldFrom) {
|
||||
$yield_types = array_merge($yield_types, self::getYieldTypeFromExpression($stmt->expr, $nodes));
|
||||
@ -305,10 +301,6 @@ class ReturnTypeCollector
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
if (!$had_explicit_return) {
|
||||
$return_types[] = new Atomic\TVoid();
|
||||
}
|
||||
}
|
||||
|
||||
return $return_types;
|
||||
|
@ -588,6 +588,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
$storage->return_type,
|
||||
$this->source->getFQCLN(),
|
||||
$storage->return_type_location,
|
||||
$context->has_returned,
|
||||
$global_context && $global_context->inside_call
|
||||
);
|
||||
|
||||
@ -1309,6 +1310,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
Type\Union $return_type = null,
|
||||
$fq_class_name = null,
|
||||
CodeLocation $return_type_location = null,
|
||||
bool $did_explicitly_return = false,
|
||||
bool $closure_inside_call = false
|
||||
) {
|
||||
ReturnTypeAnalyzer::verifyReturnType(
|
||||
@ -1321,6 +1323,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
$fq_class_name,
|
||||
$return_type_location,
|
||||
[],
|
||||
$did_explicitly_return,
|
||||
$closure_inside_call
|
||||
);
|
||||
}
|
||||
|
@ -116,7 +116,8 @@ class InterfaceAnalyzer extends ClassLikeAnalyzer
|
||||
$class_storage,
|
||||
$fq_interface_name,
|
||||
$actual_method_id,
|
||||
$actual_method_id
|
||||
$actual_method_id,
|
||||
false
|
||||
);
|
||||
}
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Property) {
|
||||
|
@ -704,7 +704,8 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
|
||||
$this,
|
||||
$return_type,
|
||||
$this->getFQCLN(),
|
||||
$return_type_location
|
||||
$return_type_location,
|
||||
$function_context->has_returned
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ class ReturnTypeManipulationTest extends FileManipulationTest
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function foo(): void {}
|
||||
protected function foo() {}
|
||||
}',
|
||||
'7.3',
|
||||
['InvalidReturnType'],
|
||||
|
Loading…
Reference in New Issue
Block a user