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;
|
$fq_class_name = $method_id->fq_class_name;
|
||||||
$method_name = $method_id->method_name;
|
$method_name = $method_id->method_name;
|
||||||
|
|
||||||
$return_type_candidate = null;
|
|
||||||
|
|
||||||
if ($codebase->methods->return_type_provider->has($fq_class_name)) {
|
if ($codebase->methods->return_type_provider->has($fq_class_name)) {
|
||||||
$return_type_candidate = $codebase->methods->return_type_provider->getReturnType(
|
$return_type_candidate = $codebase->methods->return_type_provider->getReturnType(
|
||||||
$statements_analyzer,
|
$statements_analyzer,
|
||||||
@ -52,9 +50,13 @@ class MethodCallReturnTypeFetcher
|
|||||||
new CodeLocation($statements_analyzer->getSource(), $stmt->name),
|
new CodeLocation($statements_analyzer->getSource(), $stmt->name),
|
||||||
$lhs_type_part instanceof TGenericObject ? $lhs_type_part->type_params : null
|
$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_fq_class_name = $declaring_method_id->fq_class_name;
|
||||||
$declaring_method_name = $declaring_method_id->method_name;
|
$declaring_method_name = $declaring_method_id->method_name;
|
||||||
|
|
||||||
@ -70,126 +72,130 @@ class MethodCallReturnTypeFetcher
|
|||||||
$fq_class_name,
|
$fq_class_name,
|
||||||
$method_name
|
$method_name
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($return_type_candidate) {
|
||||||
|
return $return_type_candidate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$return_type_candidate = null;
|
||||||
|
|
||||||
$class_storage = $codebase->methods->getClassLikeStorageForMethod($method_id);
|
$class_storage = $codebase->methods->getClassLikeStorageForMethod($method_id);
|
||||||
|
|
||||||
if (!$return_type_candidate) {
|
if (CallMap::inCallMap((string) $call_map_id)) {
|
||||||
if (CallMap::inCallMap((string) $call_map_id)) {
|
if (($template_result->generic_params || $class_storage->stubbed)
|
||||||
if (($template_result->generic_params || $class_storage->stubbed)
|
&& isset($class_storage->methods[$method_id->method_name])
|
||||||
&& isset($class_storage->methods[$method_id->method_name])
|
&& ($method_storage = $class_storage->methods[$method_id->method_name])
|
||||||
&& ($method_storage = $class_storage->methods[$method_id->method_name])
|
&& $method_storage->return_type
|
||||||
&& $method_storage->return_type
|
) {
|
||||||
) {
|
$return_type_candidate = clone $method_storage->return_type;
|
||||||
$return_type_candidate = clone $method_storage->return_type;
|
|
||||||
|
|
||||||
if ($template_result->generic_params) {
|
if ($template_result->generic_params) {
|
||||||
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
$return_type_candidate->replaceTemplateTypesWithArgTypes(
|
||||||
$template_result->generic_params,
|
$template_result->generic_params,
|
||||||
$codebase
|
$codebase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$callmap_callables = CallMap::getCallablesFromCallMap((string) $call_map_id);
|
$callmap_callables = CallMap::getCallablesFromCallMap((string) $call_map_id);
|
||||||
|
|
||||||
if (!$callmap_callables || $callmap_callables[0]->return_type === null) {
|
if (!$callmap_callables || $callmap_callables[0]->return_type === null) {
|
||||||
throw new \UnexpectedValueException('Shouldn’t get here');
|
throw new \UnexpectedValueException('Shouldn’t get here');
|
||||||
}
|
|
||||||
|
|
||||||
$return_type_candidate = $callmap_callables[0]->return_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($return_type_candidate->isFalsable()) {
|
$return_type_candidate = $callmap_callables[0]->return_type;
|
||||||
$return_type_candidate->ignore_falsable_issues = true;
|
}
|
||||||
|
|
||||||
|
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(
|
$return_type_candidate = ExpressionAnalyzer::fleshOutType(
|
||||||
$codebase,
|
$codebase,
|
||||||
$return_type_candidate,
|
$return_type_candidate,
|
||||||
$fq_class_name,
|
$self_fq_class_name,
|
||||||
$static_type,
|
$static_type,
|
||||||
$class_storage->parent_class
|
$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,
|
$method_id,
|
||||||
$self_fq_class_name,
|
$secondary_return_type_location
|
||||||
$statements_analyzer,
|
|
||||||
$args
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($return_type_candidate) {
|
if ($secondary_return_type_location) {
|
||||||
$return_type_candidate = clone $return_type_candidate;
|
$return_type_location = $secondary_return_type_location;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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