mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Improve returning
This commit is contained in:
parent
4c081f7835
commit
ce9eef9ed7
@ -40,8 +40,6 @@ class MethodCallReturnTypeFetcher
|
||||
$fq_class_name = $method_id->fq_class_name;
|
||||
$method_name = $method_id->method_name;
|
||||
|
||||
$return_type_candidate = null;
|
||||
|
||||
if ($codebase->methods->return_type_provider->has($fq_class_name)) {
|
||||
$return_type_candidate = $codebase->methods->return_type_provider->getReturnType(
|
||||
$statements_analyzer,
|
||||
@ -52,9 +50,13 @@ class MethodCallReturnTypeFetcher
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->name),
|
||||
$lhs_type_part instanceof TGenericObject ? $lhs_type_part->type_params : null
|
||||
);
|
||||
|
||||
if ($return_type_candidate) {
|
||||
return $return_type_candidate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$return_type_candidate && $declaring_method_id && $declaring_method_id !== $method_id) {
|
||||
if ($declaring_method_id && $declaring_method_id !== $method_id) {
|
||||
$declaring_fq_class_name = $declaring_method_id->fq_class_name;
|
||||
$declaring_method_name = $declaring_method_id->method_name;
|
||||
|
||||
@ -70,126 +72,130 @@ class MethodCallReturnTypeFetcher
|
||||
$fq_class_name,
|
||||
$method_name
|
||||
);
|
||||
|
||||
if ($return_type_candidate) {
|
||||
return $return_type_candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return_type_candidate = null;
|
||||
|
||||
$class_storage = $codebase->methods->getClassLikeStorageForMethod($method_id);
|
||||
|
||||
if (!$return_type_candidate) {
|
||||
if (CallMap::inCallMap((string) $call_map_id)) {
|
||||
if (($template_result->generic_params || $class_storage->stubbed)
|
||||
&& isset($class_storage->methods[$method_id->method_name])
|
||||
&& ($method_storage = $class_storage->methods[$method_id->method_name])
|
||||
&& $method_storage->return_type
|
||||
) {
|
||||
$return_type_candidate = clone $method_storage->return_type;
|
||||
if (CallMap::inCallMap((string) $call_map_id)) {
|
||||
if (($template_result->generic_params || $class_storage->stubbed)
|
||||
&& isset($class_storage->methods[$method_id->method_name])
|
||||
&& ($method_storage = $class_storage->methods[$method_id->method_name])
|
||||
&& $method_storage->return_type
|
||||
) {
|
||||
$return_type_candidate = clone $method_storage->return_type;
|
||||
|
||||
if ($template_result->generic_params) {
|
||||
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
||||
$template_result->generic_params,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$callmap_callables = CallMap::getCallablesFromCallMap((string) $call_map_id);
|
||||
if ($template_result->generic_params) {
|
||||
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
||||
$template_result->generic_params,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$callmap_callables = CallMap::getCallablesFromCallMap((string) $call_map_id);
|
||||
|
||||
if (!$callmap_callables || $callmap_callables[0]->return_type === null) {
|
||||
throw new \UnexpectedValueException('Shouldn’t get here');
|
||||
}
|
||||
|
||||
$return_type_candidate = $callmap_callables[0]->return_type;
|
||||
if (!$callmap_callables || $callmap_callables[0]->return_type === null) {
|
||||
throw new \UnexpectedValueException('Shouldn’t get here');
|
||||
}
|
||||
|
||||
if ($return_type_candidate->isFalsable()) {
|
||||
$return_type_candidate->ignore_falsable_issues = true;
|
||||
$return_type_candidate = $callmap_callables[0]->return_type;
|
||||
}
|
||||
|
||||
if ($return_type_candidate->isFalsable()) {
|
||||
$return_type_candidate->ignore_falsable_issues = true;
|
||||
}
|
||||
|
||||
$return_type_candidate = ExpressionAnalyzer::fleshOutType(
|
||||
$codebase,
|
||||
$return_type_candidate,
|
||||
$fq_class_name,
|
||||
$static_type,
|
||||
$class_storage->parent_class
|
||||
);
|
||||
} else {
|
||||
$self_fq_class_name = $fq_class_name;
|
||||
|
||||
$return_type_candidate = $codebase->methods->getMethodReturnType(
|
||||
$method_id,
|
||||
$self_fq_class_name,
|
||||
$statements_analyzer,
|
||||
$args
|
||||
);
|
||||
|
||||
if ($return_type_candidate) {
|
||||
$return_type_candidate = clone $return_type_candidate;
|
||||
|
||||
if ($template_result->template_types) {
|
||||
$bindable_template_types = $return_type_candidate->getTemplateTypes();
|
||||
|
||||
foreach ($bindable_template_types as $template_type) {
|
||||
if ($template_type->defining_class !== $fq_class_name
|
||||
&& !isset(
|
||||
$template_result->generic_params
|
||||
[$template_type->param_name]
|
||||
[$template_type->defining_class]
|
||||
)
|
||||
) {
|
||||
$template_result->generic_params[$template_type->param_name] = [
|
||||
($template_type->defining_class) => [Type::getEmpty(), 0]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($template_result->generic_params) {
|
||||
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
||||
$template_result->generic_params,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
|
||||
$return_type_candidate = ExpressionAnalyzer::fleshOutType(
|
||||
$codebase,
|
||||
$return_type_candidate,
|
||||
$fq_class_name,
|
||||
$self_fq_class_name,
|
||||
$static_type,
|
||||
$class_storage->parent_class
|
||||
);
|
||||
} else {
|
||||
$self_fq_class_name = $fq_class_name;
|
||||
|
||||
$return_type_candidate = $codebase->methods->getMethodReturnType(
|
||||
$return_type_candidate->sources = [
|
||||
new Source(
|
||||
strtolower((string) $method_id),
|
||||
$cased_method_id,
|
||||
new CodeLocation($statements_analyzer, $stmt->name)
|
||||
)
|
||||
];
|
||||
|
||||
$return_type_location = $codebase->methods->getMethodReturnTypeLocation(
|
||||
$method_id,
|
||||
$self_fq_class_name,
|
||||
$statements_analyzer,
|
||||
$args
|
||||
$secondary_return_type_location
|
||||
);
|
||||
|
||||
if ($return_type_candidate) {
|
||||
$return_type_candidate = clone $return_type_candidate;
|
||||
|
||||
if ($template_result->template_types) {
|
||||
$bindable_template_types = $return_type_candidate->getTemplateTypes();
|
||||
|
||||
foreach ($bindable_template_types as $template_type) {
|
||||
if ($template_type->defining_class !== $fq_class_name
|
||||
&& !isset(
|
||||
$template_result->generic_params
|
||||
[$template_type->param_name]
|
||||
[$template_type->defining_class]
|
||||
)
|
||||
) {
|
||||
$template_result->generic_params[$template_type->param_name] = [
|
||||
($template_type->defining_class) => [Type::getEmpty(), 0]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($template_result->generic_params) {
|
||||
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
||||
$template_result->generic_params,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
|
||||
$return_type_candidate = ExpressionAnalyzer::fleshOutType(
|
||||
$codebase,
|
||||
$return_type_candidate,
|
||||
$self_fq_class_name,
|
||||
$static_type,
|
||||
$class_storage->parent_class
|
||||
);
|
||||
|
||||
$return_type_candidate->sources = [
|
||||
new Source(
|
||||
strtolower((string) $method_id),
|
||||
$cased_method_id,
|
||||
new CodeLocation($statements_analyzer, $stmt->name)
|
||||
)
|
||||
];
|
||||
|
||||
$return_type_location = $codebase->methods->getMethodReturnTypeLocation(
|
||||
$method_id,
|
||||
$secondary_return_type_location
|
||||
);
|
||||
|
||||
if ($secondary_return_type_location) {
|
||||
$return_type_location = $secondary_return_type_location;
|
||||
}
|
||||
|
||||
$config = \Psalm\Config::getInstance();
|
||||
|
||||
// only check the type locally if it's defined externally
|
||||
if ($return_type_location && !$config->isInProjectDirs($return_type_location->file_path)) {
|
||||
$return_type_candidate->check(
|
||||
$statements_analyzer,
|
||||
new CodeLocation($statements_analyzer, $stmt),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
$context->phantom_classes
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$result->returns_by_ref =
|
||||
$result->returns_by_ref
|
||||
|| $codebase->methods->getMethodReturnsByRef($method_id);
|
||||
if ($secondary_return_type_location) {
|
||||
$return_type_location = $secondary_return_type_location;
|
||||
}
|
||||
|
||||
$config = \Psalm\Config::getInstance();
|
||||
|
||||
// only check the type locally if it's defined externally
|
||||
if ($return_type_location && !$config->isInProjectDirs($return_type_location->file_path)) {
|
||||
$return_type_candidate->check(
|
||||
$statements_analyzer,
|
||||
new CodeLocation($statements_analyzer, $stmt),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
$context->phantom_classes
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$result->returns_by_ref =
|
||||
$result->returns_by_ref
|
||||
|| $codebase->methods->getMethodReturnsByRef($method_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user