Skip to content

Conversation

@peterfox
Copy link
Contributor

@peterfox peterfox commented Dec 5, 2025

Changes

  • Adds a new CallLikeExpectsThisBindedClosureArgsAnalyzer which allows the detection of the @param-closure-this.
  • Adds a mechanism in the Static Closure rule to apply an attribute to closures that might conflict with @param-closure-this and then skip these closures
  • Sets up the tests to cover these scenarios

Why

Often there's a few scenarios where the static closure rule causes problems and starts to add the keyword where it will break code because it's being used as a argument for a parameter which will be later bound to an object. This can't be done if the closure is static and causes a runtime error.

This happens quite a lot in Laravel projects. Example issues driftingly/rector-laravel#102

Notes

I had to use method.notFound to silence PHPStan. I don't know why this is the case as the code works but something is up with PHPStan.

I also created a new analyser to make this work but I'm happy to take this method and put it into a pre-existing one if adding a new one seems pointless.

@peterfox peterfox marked this pull request as ready for review December 5, 2025 23:39
@peterfox peterfox requested a review from samsonasik December 6, 2025 02:25
Copy link
Member

@samsonasik samsonasik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

@peterfox peterfox force-pushed the feature/static-closure-improved branch from 1310b07 to 91e3be0 Compare December 7, 2025 15:32
@peterfox peterfox requested a review from TomasVotruba December 7, 2025 16:20
…e-improved

# Conflicts:
#	src/DependencyInjection/LazyContainerFactory.php
#	src/NodeTypeResolver/Node/AttributeKey.php
#	src/PhpParser/NodeVisitor/CallLikeThisBoundClosureArgsNodeVisitor.php
…e-improved

# Conflicts:
#	rules/CodingStyle/Guard/ArrowFunctionAndClosureFirstClassCallableGuard.php
public function getArgsUsingThisBoundClosure(CallLike $callLike): array
{
$args = [];
$reflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($callLike);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this reflection get before it usage

Comment on lines +44 to +45
$parametersAcceptor = ParametersAcceptorSelectorVariantsWrapper::select($reflection, $callLike, $scope);
$parameters = $parametersAcceptor->getParameters();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think verify if there is Closure as Arg first is better to avoid possible reflection check:

$args = $callLike->getArgs();
$hasClosureArg = (bool) array_filter($args, fn (Arg $arg): bool => $arg->value instanceof Closure);

if (! $hasClosureArg) {
    return null;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants