mirror of
https://github.com/danog/psalm.git
synced 2024-12-02 09:37:59 +01:00
Merge pull request #10357 from robchett/inherit_conditional_function_templates
Inherit conditional returns
This commit is contained in:
commit
0e43c441d0
@ -577,7 +577,7 @@ final class MethodCallReturnTypeFetcher
|
|||||||
) {
|
) {
|
||||||
if ($template_type->param_name === 'TFunctionArgCount') {
|
if ($template_type->param_name === 'TFunctionArgCount') {
|
||||||
$template_result->lower_bounds[$template_type->param_name] = [
|
$template_result->lower_bounds[$template_type->param_name] = [
|
||||||
'fn-' . strtolower((string) $method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(false, $arg_count),
|
Type::getInt(false, $arg_count),
|
||||||
),
|
),
|
||||||
@ -585,7 +585,7 @@ final class MethodCallReturnTypeFetcher
|
|||||||
];
|
];
|
||||||
} elseif ($template_type->param_name === 'TPhpMajorVersion') {
|
} elseif ($template_type->param_name === 'TPhpMajorVersion') {
|
||||||
$template_result->lower_bounds[$template_type->param_name] = [
|
$template_result->lower_bounds[$template_type->param_name] = [
|
||||||
'fn-' . strtolower((string) $method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
||||||
),
|
),
|
||||||
@ -593,7 +593,7 @@ final class MethodCallReturnTypeFetcher
|
|||||||
];
|
];
|
||||||
} elseif ($template_type->param_name === 'TPhpVersionId') {
|
} elseif ($template_type->param_name === 'TPhpVersionId') {
|
||||||
$template_result->lower_bounds[$template_type->param_name] = [
|
$template_result->lower_bounds[$template_type->param_name] = [
|
||||||
'fn-' . strtolower((string) $method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(
|
Type::getInt(
|
||||||
false,
|
false,
|
||||||
|
@ -629,7 +629,7 @@ final class ExistingAtomicStaticCallAnalyzer
|
|||||||
): array {
|
): array {
|
||||||
if ($template_type->param_name === 'TFunctionArgCount') {
|
if ($template_type->param_name === 'TFunctionArgCount') {
|
||||||
return [
|
return [
|
||||||
'fn-' . strtolower((string)$method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(false, count($stmt->getArgs())),
|
Type::getInt(false, count($stmt->getArgs())),
|
||||||
),
|
),
|
||||||
@ -639,7 +639,7 @@ final class ExistingAtomicStaticCallAnalyzer
|
|||||||
|
|
||||||
if ($template_type->param_name === 'TPhpMajorVersion') {
|
if ($template_type->param_name === 'TPhpMajorVersion') {
|
||||||
return [
|
return [
|
||||||
'fn-' . strtolower((string)$method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
||||||
),
|
),
|
||||||
@ -649,7 +649,7 @@ final class ExistingAtomicStaticCallAnalyzer
|
|||||||
|
|
||||||
if ($template_type->param_name === 'TPhpVersionId') {
|
if ($template_type->param_name === 'TPhpVersionId') {
|
||||||
return [
|
return [
|
||||||
'fn-' . strtolower((string) $method_id) => [
|
'fn-' . $method_id->method_name => [
|
||||||
new TemplateBound(
|
new TemplateBound(
|
||||||
Type::getInt(
|
Type::getInt(
|
||||||
false,
|
false,
|
||||||
|
@ -512,9 +512,8 @@ final class FunctionLikeDocblockScanner
|
|||||||
|
|
||||||
if ($token_body === 'func_num_args()') {
|
if ($token_body === 'func_num_args()') {
|
||||||
$template_name = 'TFunctionArgCount';
|
$template_name = 'TFunctionArgCount';
|
||||||
|
|
||||||
$storage->template_types[$template_name] = [
|
$storage->template_types[$template_name] = [
|
||||||
$template_function_id => Type::getInt(),
|
'fn-' . strtolower($storage->cased_name ?? '') => Type::getInt(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$function_template_types[$template_name]
|
$function_template_types[$template_name]
|
||||||
@ -527,7 +526,7 @@ final class FunctionLikeDocblockScanner
|
|||||||
$template_name = 'TPhpMajorVersion';
|
$template_name = 'TPhpMajorVersion';
|
||||||
|
|
||||||
$storage->template_types[$template_name] = [
|
$storage->template_types[$template_name] = [
|
||||||
$template_function_id => Type::getInt(),
|
'fn-' . strtolower($storage->cased_name ?? '') => Type::getInt(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$function_template_types[$template_name]
|
$function_template_types[$template_name]
|
||||||
@ -540,7 +539,7 @@ final class FunctionLikeDocblockScanner
|
|||||||
$template_name = 'TPhpVersionId';
|
$template_name = 'TPhpVersionId';
|
||||||
|
|
||||||
$storage->template_types[$template_name] = [
|
$storage->template_types[$template_name] = [
|
||||||
$template_function_id => Type::getInt(),
|
'fn-' . strtolower($storage->cased_name ?? '') => Type::getInt(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$function_template_types[$template_name]
|
$function_template_types[$template_name]
|
||||||
|
@ -463,6 +463,31 @@ class ConditionalReturnTypeTest extends TestCase
|
|||||||
'$c' => 'string',
|
'$c' => 'string',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'InheritFuncNumArgs' => [
|
||||||
|
'code' => '<?php
|
||||||
|
abstract class A
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @psalm-return (func_num_args() is 1 ? string : int)
|
||||||
|
*/
|
||||||
|
public static function get(bool $a, ?bool $b = null)
|
||||||
|
{
|
||||||
|
if ($b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A
|
||||||
|
{
|
||||||
|
|
||||||
|
public static function getB(bool $a): int
|
||||||
|
{
|
||||||
|
return self::get($a, true);
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
'namespaceFuncNumArgs' => [
|
'namespaceFuncNumArgs' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
namespace Foo;
|
namespace Foo;
|
||||||
@ -887,6 +912,39 @@ class ConditionalReturnTypeTest extends TestCase
|
|||||||
'ignored_issues' => [],
|
'ignored_issues' => [],
|
||||||
'php_version' => '7.2',
|
'php_version' => '7.2',
|
||||||
],
|
],
|
||||||
|
'ineritedreturnTypeBasedOnPhpVersionId' => [
|
||||||
|
'code' => '<?php
|
||||||
|
class A {
|
||||||
|
/**
|
||||||
|
* @psalm-return (PHP_VERSION_ID is int<70300, max> ? string : int)
|
||||||
|
*/
|
||||||
|
function getSomething()
|
||||||
|
{
|
||||||
|
return mt_rand(1, 10) > 5 ? "a value" : 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @psalm-return (PHP_VERSION_ID is int<70100, max> ? string : int)
|
||||||
|
*/
|
||||||
|
function getSomethingElse()
|
||||||
|
{
|
||||||
|
return mt_rand(1, 10) > 5 ? "a value" : 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {}
|
||||||
|
|
||||||
|
$class = new B();
|
||||||
|
$something = $class->getSomething();
|
||||||
|
$somethingElse = $class->getSomethingElse();
|
||||||
|
',
|
||||||
|
'assertions' => [
|
||||||
|
'$something' => 'int',
|
||||||
|
'$somethingElse' => 'string',
|
||||||
|
],
|
||||||
|
'ignored_issues' => [],
|
||||||
|
'php_version' => '7.2',
|
||||||
|
],
|
||||||
'ineritedConditionalTemplatedReturnType' => [
|
'ineritedConditionalTemplatedReturnType' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
/** @template InstanceType */
|
/** @template InstanceType */
|
||||||
|
Loading…
Reference in New Issue
Block a user