-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't add first class callable filter: No closure found #435
Comments
This looks like limitation of roave/betterreflection which is used to analyse closure created by first class callable. It tries to analyse given closure (param and return types) by parsing known location (file+line) of closure definition (it is part of closure "object") but looks only for normal closures not for first class callables. Honestly I have no idea how to fix this. |
I will check is there is any workaround for this used in PHPStan itself somewhere. |
Reported issue to roave/betterreflection Roave/BetterReflection#1363 |
Hey, please let me know the place in code where this problem occurs for you. Personally I think if you did |
It happens here:
We have Closure (real) created as first class callable which is extracted from Latte engine. And we need to know its signature to be able to preprocess code for analysis. Replace magic call by direct call to given method for which first class callable was created. |
In which form do you need the signature? What about FunctionReflection/MethodReflection or ParametersAcceptor? |
Well, class name + method name of first class callablectarget would be enough. Or we need types of all parameters and return type to create matching placeholder - MethodReflection should be enough. Problem is we do not have scope from plave where closure is defined - we just get closure itself from latte engine. |
Why is this code in a node visitor and not done later where you Scope and other helpers available? |
We compile template by latte, use these preprocessors to make it analysable and save it. Then we run analysis of this compiled template. |
Please show me these steps:
|
Original call to filter looks like this ( ($this->filters->upper)($title) for static methods we transform it to: \Nette\Utils\Strings::upper($title); for non-static methods we use: /** callable(string):string $__filter_upper */
// ...
$__filter_upper($title) |
Why don't you transform the filter call to: ((new Filters())->objectFilter(...))($whatIFilter) That way you don't really need to care and transform the details of the call. |
Or maybe just do: $__filter_upper = The\Callable::doFoo(...); |
Otherwise you could also do the job of collecting "this filter has this ParametersAcceptor signature" with a custom Collector (where you have all the PHPStan internals available) and then use that information later. |
Problem is we have only Closure object we get from latte engine. It is created outside analysed files. |
For your alternatives - in both cases we need to thow class name and method name Closure targets. But we cannot get it from Closure itslef. |
We also need to know if first param of target is FilterInfo because it is added to call magically by filter executor outside template |
I get it - so you don't see the AST from The bug isn't in BetterReflection. You're calling Since you already have the |
Thanks for the tip, I will try it. |
Fixed by #450 @ondrejmirtes Thanks for good tip |
When adding a filter like:
PHPStan returns "No closure found". I don't even know where to start so I'll just add a failing test (#436).
The text was updated successfully, but these errors were encountered: