vscode-intelephense
vscode-intelephense copied to clipboard
Support Psalm callable types
It would be really nice to support Psalm's callable type syntax.
https://psalm.dev/docs/docblock_type_syntax/#callable-types
Would be great to specify expected callback's arguments/return types in @param
, e.g. @param callable(int):string
.
Current link: https://psalm.dev/docs/annotating_code/type_syntax/callable_types/
As alternative there is also php 7.4 arrow syntax to consider, but existing psalm one is still winner for me.
As I understand it Psalm and Phan use:
callable(Type1, OptionalType2=, ...SpreadType3):ReturnType
with Closure
also allowed in place of callable
.
PHPStan seems to have something similar but allows parameter names? So it's more akin to an actual function declaration.
callable(Type1 $type1, OptionalType2 $optionalType2 = null, SpreadType3 ...$spreadType3):ReturnType
Given that there was already array<K, V>
and Generator<T>
for documenting types I don't understand why additional syntax was needed for Closure
. I'd rather see:
Closure<P1, P2, P3, R>
Though it would mean yet another way of documenting callables.
Another way to implement this could be via existing @method
syntax to give the parameter a local type name.
/**
* @method Foo MyCallableType(int $a, string $b) description...
* @param MyCallableType $callable
*/
function acceptsCallable(callable $callable) { }
Another way to implement this could be via existing
@method
syntax to give the parameter a local type name.
@method
means something completely different already, If you want own implementation just add @typedef
like in JS/TS.
I would appreciate it if there is a way to document callable directly and it is also recognised in intelephense. currently I use the simple syntax (string):void
to document it, of course I would have no problems with callable(string):void
. Only intelephense shows a \<string>
which is of course completely incorrect.
In my view, it would be sufficient if it were only treated as callable at the end.
Only the type hint (i.e. the preview of which value is in this variable) has a great use. But even if this syntax is valid and it is converted to a callable and displayed in the type hint and not string, it is more useful than displaying something completely wrong.
@lublak In some cases I'm using interfaces and anonymous classes, It has some overhead, but helps with more complicated code.
class SomeData{
public string $whatever;
}
interface CallMeBackInterface {
function done(SomeData $data);
}
function callMeBack(CallMeBackInterface $callback){
// ...
}
callMeBack(new class implements CallMeBackInterface {
function done(SomeData $data)
{
$data->whatever; // string
}
});
@KapitanOczywisty good idea, but hey it would be better if intelephense support it wihtout an interface.
what I found out by chance:
/**
* @var callable(string) $testParam
*/
function test($testParam):void {
$testParam;
}
/**
* @var callable(string) $testParam
*/
$testParam;
So its half supported.
It's supported as far as ignoring some common formats.
However if you copy type from anonymous function as @param
it is suggesting correct types :D
// BAD CODE // DO NOT USE
$a = fn():string => 'foo';
/**
* @param \Closure&\#Function#82d34e74 $cb
*/
function a ($cb){
$b = $cb();
// $b is string
}
Hi, I also would really appreciate this feature to work a little better. One method which works quite well "inside" the called function, but which doesn't help a lot for calling the function is this:
interface MyMethod {
public function __invoke(int|float $arg1, int|float $arg2): int|float;
}
/**
* @param MyMethod $handler
*/
function add_callback(Closure $handler): void {
// Completion works well here
$result = $handler(10, 20.5);
}
/**
* Completion doesn't work well here
*/
add_callback(function( /* HERE IT WOULD BE NICE TO HAVE COMPLETION */ ) {});
I'm sure it is possible to avoid actually declaring that interface using @typedef
or whatnot(?), but just put these interfaces in a PHP file which your application will never actually load. Intelephense will still use the interface.
Following will be supported in 1.9
callable(string, ?Foo): Bar
and \Closure(string, ?Foo): Bar
.
Longer form also supported callable(string $string, ?Foo $foo = null): Bar
.
Variadic params and default args are not supported in the short format callable(Type1, OptionalType2=, SpreadType3...):ReturnType