1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Add example given in ticket and ensure that works too

This commit is contained in:
Matt Brown 2021-05-24 00:09:51 -04:00
parent c258303f78
commit 38c452ae58
4 changed files with 84 additions and 30 deletions

View File

@ -832,17 +832,22 @@ class ArgumentAnalyzer
$param_type->possibly_undefined = true;
}
if ($param_type->hasCallableType()
&& $param_type->isSingle()
&& $input_type->isSingleStringLiteral()
&& !\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($input_type->getSingleStringLiteral()->value)
) {
if ($param_type->hasCallableType() && $param_type->isSingle()) {
// we do this replacement early because later we don't have access to the
// $statements_analyzer, which is necessary to understand string function names
foreach ($input_type->getAtomicTypes() as $key => $atomic_type) {
if (!$atomic_type instanceof Type\Atomic\TLiteralString
|| \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($atomic_type->value)
) {
continue;
}
$candidate_callable = CallableTypeComparator::getCallableFromAtomic(
$codebase,
$atomic_type,
null,
$statements_analyzer
$statements_analyzer,
true
);
if ($candidate_callable) {

View File

@ -252,9 +252,14 @@ class CallableTypeComparator
null,
null,
true,
true,
false,
false,
true
);
}
$params[] = $param;
}
$return_type = null;
@ -267,6 +272,9 @@ class CallableTypeComparator
null,
null,
true,
true,
false,
false,
true
);
}

View File

@ -32,7 +32,8 @@ class TypeExpander
bool $evaluate_class_constants = true,
bool $evaluate_conditional_types = false,
bool $final = false,
bool $expand_generic = false
bool $expand_generic = false,
bool $expand_templates = false
): Type\Union {
$return_type = clone $return_type;
@ -50,7 +51,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if (is_array($parts)) {
@ -99,7 +101,8 @@ class TypeExpander
bool $evaluate_class_constants = true,
bool $evaluate_conditional_types = false,
bool $final = false,
bool $expand_generic = false
bool $expand_generic = false,
bool $expand_templates = false
) {
if ($return_type instanceof TNamedObject
|| $return_type instanceof TTemplateParam
@ -116,7 +119,8 @@ class TypeExpander
$parent_class,
$evaluate_class_constants,
$evaluate_conditional_types,
$expand_generic
$expand_generic,
$expand_templates
);
if ($extra_type instanceof TNamedObject && $extra_type->extra_types) {
@ -160,7 +164,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if ($new_as_type instanceof TNamedObject) {
@ -177,9 +182,14 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if ($expand_templates) {
return array_values($new_as_type->getAtomicTypes());
}
$return_type->as = $new_as_type;
}
@ -286,7 +296,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if (is_array($recursively_fleshed_out_type)) {
@ -364,7 +375,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if (\is_array($new_value_type)) {
@ -397,7 +409,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if (!is_array($new_value_types)) {
@ -432,7 +445,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
} elseif ($return_type instanceof Type\Atomic\TKeyedArray) {
@ -446,7 +460,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
} elseif ($return_type instanceof Type\Atomic\TList) {
@ -459,7 +474,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
@ -474,7 +490,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
}
@ -494,7 +511,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
}
@ -509,7 +527,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
}
@ -524,7 +543,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
}
@ -643,7 +663,8 @@ class TypeExpander
bool $evaluate_class_constants = true,
bool $evaluate_conditional_types = false,
bool $final = false,
bool &$expand_generic = false
bool &$expand_generic = false,
bool $expand_templates = false
) {
$new_as_type = self::expandUnion(
$codebase,
@ -654,7 +675,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
$return_type->as_type = $new_as_type;
@ -673,7 +695,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
if (!is_array($candidate)) {
@ -694,7 +717,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
$candidate_types = is_array($candidate) ? $candidate : [$candidate];
@ -717,7 +741,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
$candidate_types = is_array($candidate) ? $candidate : [$candidate];
@ -793,7 +818,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
$return_type->if_type = self::expandUnion(
@ -805,7 +831,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
$return_type->else_type = self::expandUnion(
@ -817,7 +844,8 @@ class TypeExpander
$evaluate_class_constants,
$evaluate_conditional_types,
$final,
$expand_generic
$expand_generic,
$expand_templates
);
return $return_type;

View File

@ -2293,8 +2293,21 @@ class ClassTemplateTest extends TestCase
/** @param ArrayCollection<int> $ints */
function takesInts(ArrayCollection $ints) :void {}
/** @param ArrayCollection<int|string> $ints */
function takesIntsOrStrings(ArrayCollection $ints) :void {}
takesInts((new ArrayCollection([ "a", "bc" ]))->map("strlen"));
/** @return ($s is "string" ? string : int) */
function foo(string $s) {
if ($s === "string") {
return "hello";
}
return 5;
}
takesIntsOrStrings((new ArrayCollection([ "a", "bc" ]))->map("foo"));
/**
* @template T
* @extends ArrayCollection<T>