1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Use more accurate means of determining whether function did return

This commit is contained in:
Matthew Brown 2020-03-28 23:37:42 -04:00
parent 7195ea6842
commit 5395183837
7 changed files with 23 additions and 15 deletions

View File

@ -1761,7 +1761,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
$class_storage, $class_storage,
$class_context->self, $class_context->self,
$analyzed_method_id, $analyzed_method_id,
$actual_method_id $actual_method_id,
$method_context->has_returned
); );
} }
@ -1785,7 +1786,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
ClassLikeStorage $class_storage, ClassLikeStorage $class_storage,
string $fq_classlike_name, string $fq_classlike_name,
\Psalm\Internal\MethodIdentifier $analyzed_method_id, \Psalm\Internal\MethodIdentifier $analyzed_method_id,
\Psalm\Internal\MethodIdentifier $actual_method_id \Psalm\Internal\MethodIdentifier $actual_method_id,
bool $did_explicitly_return
) : void { ) : void {
$secondary_return_type_location = null; $secondary_return_type_location = null;
@ -1892,7 +1894,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
$interface_return_type, $interface_return_type,
$interface_class, $interface_class,
$interface_return_type_location, $interface_return_type_location,
[$analyzed_method_id] [$analyzed_method_id],
$did_explicitly_return
); );
} }
} }
@ -1910,7 +1913,8 @@ class ClassAnalyzer extends ClassLikeAnalyzer
$return_type, $return_type,
$fq_classlike_name, $fq_classlike_name,
$return_type_location, $return_type_location,
$overridden_method_ids $overridden_method_ids,
$did_explicitly_return
); );
} }

View File

@ -67,6 +67,7 @@ class ReturnTypeAnalyzer
$fq_class_name = null, $fq_class_name = null,
CodeLocation $return_type_location = null, CodeLocation $return_type_location = null,
array $compatible_method_ids = [], array $compatible_method_ids = [],
bool $did_explicitly_return = false,
bool $closure_inside_call = false bool $closure_inside_call = false
) { ) {
$suppressed_issues = $function_like_analyzer->getSuppressedIssues(); $suppressed_issues = $function_like_analyzer->getSuppressedIssues();
@ -137,6 +138,10 @@ class ReturnTypeAnalyzer
true true
); );
if (!$inferred_return_type_parts) {
$did_explicitly_return = true;
}
if ((!$return_type || $return_type->from_docblock) if ((!$return_type || $return_type->from_docblock)
&& ScopeAnalyzer::getFinalControlActions( && ScopeAnalyzer::getFinalControlActions(
$function_stmts, $function_stmts,
@ -145,6 +150,7 @@ class ReturnTypeAnalyzer
) !== [ScopeAnalyzer::ACTION_END] ) !== [ScopeAnalyzer::ACTION_END]
&& !$inferred_yield_types && !$inferred_yield_types
&& count($inferred_return_type_parts) && count($inferred_return_type_parts)
&& !$did_explicitly_return
) { ) {
// only add null if we have a return statement elsewhere and it wasn't void // 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) { foreach ($inferred_return_type_parts as $inferred_return_type_part) {
@ -324,6 +330,7 @@ class ReturnTypeAnalyzer
$source, $source,
$function_like_analyzer, $function_like_analyzer,
$compatible_method_ids $compatible_method_ids
|| !$did_explicitly_return
|| (($project_analyzer->only_replace_php_types_with_non_docblock_types || (($project_analyzer->only_replace_php_types_with_non_docblock_types
|| $unsafe_return_type) || $unsafe_return_type)
&& $inferred_return_type->from_docblock), && $inferred_return_type->from_docblock),

View File

@ -35,12 +35,8 @@ class ReturnTypeCollector
) { ) {
$return_types = []; $return_types = [];
$had_explicit_return = [];
foreach ($stmts as $stmt) { foreach ($stmts as $stmt) {
if ($stmt instanceof PhpParser\Node\Stmt\Return_) { if ($stmt instanceof PhpParser\Node\Stmt\Return_) {
$had_explicit_return = true;
if ($stmt->expr instanceof PhpParser\Node\Expr\Yield_ || if ($stmt->expr instanceof PhpParser\Node\Expr\Yield_ ||
$stmt->expr instanceof PhpParser\Node\Expr\YieldFrom) { $stmt->expr instanceof PhpParser\Node\Expr\YieldFrom) {
$yield_types = array_merge($yield_types, self::getYieldTypeFromExpression($stmt->expr, $nodes)); $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; return $return_types;

View File

@ -588,6 +588,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
$storage->return_type, $storage->return_type,
$this->source->getFQCLN(), $this->source->getFQCLN(),
$storage->return_type_location, $storage->return_type_location,
$context->has_returned,
$global_context && $global_context->inside_call $global_context && $global_context->inside_call
); );
@ -1309,6 +1310,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
Type\Union $return_type = null, Type\Union $return_type = null,
$fq_class_name = null, $fq_class_name = null,
CodeLocation $return_type_location = null, CodeLocation $return_type_location = null,
bool $did_explicitly_return = false,
bool $closure_inside_call = false bool $closure_inside_call = false
) { ) {
ReturnTypeAnalyzer::verifyReturnType( ReturnTypeAnalyzer::verifyReturnType(
@ -1321,6 +1323,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
$fq_class_name, $fq_class_name,
$return_type_location, $return_type_location,
[], [],
$did_explicitly_return,
$closure_inside_call $closure_inside_call
); );
} }

View File

@ -116,7 +116,8 @@ class InterfaceAnalyzer extends ClassLikeAnalyzer
$class_storage, $class_storage,
$fq_interface_name, $fq_interface_name,
$actual_method_id, $actual_method_id,
$actual_method_id $actual_method_id,
false
); );
} }
} elseif ($stmt instanceof PhpParser\Node\Stmt\Property) { } elseif ($stmt instanceof PhpParser\Node\Stmt\Property) {

View File

@ -704,7 +704,8 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
$this, $this,
$return_type, $return_type,
$this->getFQCLN(), $this->getFQCLN(),
$return_type_location $return_type_location,
$function_context->has_returned
); );
} }
} }

View File

@ -405,7 +405,7 @@ class ReturnTypeManipulationTest extends FileManipulationTest
/** /**
* @return void * @return void
*/ */
protected function foo(): void {} protected function foo() {}
}', }',
'7.3', '7.3',
['InvalidReturnType'], ['InvalidReturnType'],