Skip to content

Commit 7d28bf3

Browse files
committed
Improve callmap docs
1 parent 5395878 commit 7d28bf3

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@
7575
},
7676
"extra": {
7777
"branch-alias": {
78-
"dev-master": "6.x-dev",
78+
"dev-master": "7.x-dev",
79+
"dev-6.x": "6.x-dev",
7980
"dev-5.x": "5.x-dev",
8081
"dev-4.x": "4.x-dev",
8182
"dev-3.x": "3.x-dev",

docs/contributing/editing_callmaps.md

+48
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,54 @@ optional parameter is postfixed with `=`, references with `&`/`&r_`/`&w_`/`&rw_`
3333
(depending on the read/write meaning of the reference param) and
3434
variadic args are prefixed with `...`.
3535

36+
Callmaps also support function aliases: aliases are very useful to specify that
37+
a certain function behaves differently according to the parameter types.
38+
39+
For example, the following aliases are currently in use in the callmap to specify
40+
that the `version_compare` function can be called with an `operator` parameter,
41+
in which case it will return a boolean; otherwise it will return an integer.
42+
43+
```php
44+
[
45+
'version_compare' => [
46+
0 => 'bool',
47+
'version1' => 'string',
48+
'version2' => 'string',
49+
'operator' => '\'!=\'|\'<\'|\'<=\'|\'<>\'|\'=\'|\'==\'|\'>\'|\'>=\'|\'eq\'|\'ge\'|\'gt\'|\'le\'|\'lt\'|\'ne\'|null',
50+
],
51+
'version_compare\'1' => [
52+
0 => 'int',
53+
'version1' => 'string',
54+
'version2' => 'string',
55+
],
56+
]
57+
```
58+
59+
**Note**: the above example doesn't provide almost any useful information for type inference;
60+
in fact, the real logic for return type inference is contained in the `VersionCompareReturnTypeProvider`.
61+
62+
The callmap is mainly useful when treating functions and methods as *callable values*, for example:
63+
64+
```php
65+
<?php
66+
function naive_version_compare(string $a, string $b, ?string $operator = null): int|bool {
67+
return 0;
68+
}
69+
70+
$a = ["1.0", "2.0"];
71+
72+
// OK
73+
usort($a, "version_compare");
74+
75+
// InvalidArgument: Argument 2 of usort expects callable(string, string):int, but impure-callable(string, string, null|string=):(bool|int) provided
76+
usort($a, "naive_version_compare");
77+
```
78+
79+
The first usort succeeds, because psalm chooses the correct alias to use between the two provided in the callmap.
80+
The second usort fails (equivalent to the non-split return type of `version_compare` inferred by reflection), because the return type is a union of the two possible signatures of version_compare.
81+
82+
When you have multifaceted functions like these, it's a very good idea to at least define a templated stub in `stubs/` for them, or a custom return type provider for even more complex logic, not representable with templates/conditional types/etc in a stub.
83+
3684
## Delta file format
3785

3886
Delta files (named `CallMap_<PHP major version><PHP minor version>_delta.php`)

tests/fixtures/DummyProjectWithErrors/diff_composer.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)