Skip to content

Squiz/StaticThisUsage: improve handling of anonymous functions#1377

Open
jrfnl wants to merge 3 commits into4.xfrom
feature/1357/squiz-staticthisusage-fix-false-positive-nested-closure
Open

Squiz/StaticThisUsage: improve handling of anonymous functions#1377
jrfnl wants to merge 3 commits into4.xfrom
feature/1357/squiz-staticthisusage-fix-false-positive-nested-closure

Conversation

@jrfnl
Copy link
Member

@jrfnl jrfnl commented Mar 1, 2026

Description

Squiz/StaticThisUsage: always skip nested anonymous scope

As things were, the Squiz.Scope.StaticThisUsage sniff already skipped over the body of anonymous classes when found within the body of a static OO method, to prevent false positives related to $this when it refers to the anonymous class.
However, the sniff did not skip over the body of an anonymous function (closure).

This is wrong, as anonymous functions can be bound to an object, in which case the closure has access to that object via $this.
However, whether the object is actually bound or not, is irrelevant. The closure has its own (closed) scope and doesn't have access to variables from outside the closure, so any usages of $this within the closure would not be the "static this usage" this sniff is looking for anyway.

With that in mind, the sniff should skip over the body of closures, same as it skips over the body of anonymous classes.

Having said that, I also believe that the sniff should explicitly examine static closures for the use of $this, while it currently doesn't (false negative), but that's another matter.

Fixes #1357

Related to previous iterations:

Squiz/StaticThisUsage: examine the body of static closures

As noted in the previous commit, closures can be declared as static, in which case they do not have access to $this.

That case was so far not considered by this sniff.

This commit changes the sniff to:

  1. Also examine T_CLOSURE tokens.
  2. Examine these when nested inside OO methods, as well as when found completely outside of OO structures.

Note: in a future iteration it should be considered to get rid of the implementation via the AbstractScopeSniff as that implementation actually makes the sniff more complicated instead of less complicated.

Includes unit tests.

Squiz/StaticThisUsage: add extra test

... for code in the sniff previously not covered by tests.

Suggested changelog entry

  • Fixed: Squiz.Scope.StaticThisUsage: false positive for usage of $this in non-static closures nested in OO methods.
  • Changed: Squiz.Scope.StaticThisUsage: the sniff will now also search for the use of $this in static closures.

As things were, the `Squiz.Scope.StaticThisUsage` sniff already skipped over the body of anonymous classes when found within the body of a static OO method, to prevent false positives related to `$this` when it refers to the anonymous class.
However, the sniff did not skip over the body of an anonymous function (closure).

This is wrong, as anonymous functions can be bound to an object, in which case the closure has access to that object via `$this`.
However, whether the object is actually bound or not, is irrelevant. The closure has its own (closed) scope and doesn't have access to variables from outside the closure, so any usages of `$this` _within_ the closure would not be the "static this usage" this sniff is looking for anyway.

With that in mind, the sniff should skip over the body of closures, same as it skips over the body of anonymous classes.

Having said that, I also believe that the sniff should explicitly examine `static` closures for the use of `$this`, while it currently doesn't (false negative), but that's another matter.

Fixes 1357

Related to previous iterations:
* squizlabs/PHP_CodeSniffer 1747 - solved via 8ad3826
* squizlabs/PHP_CodeSniffer 2725
Copy link
Contributor

@rodrigoprimo rodrigoprimo 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. I just left a comment with a small fix in a docblock.

@rodrigoprimo rodrigoprimo self-requested a review March 3, 2026 12:49
jrfnl added 2 commits March 3, 2026 14:50
As noted in the previous commit, closures can be declared as `static`, in which case they do not have access to `$this`.

That case was so far not considered by this sniff.

This commit changes the sniff to:
1. Also examine `T_CLOSURE` tokens.
2. Examine these when nested inside OO methods, as well as when found completely outside of OO structures.

Note: in a future iteration it should be considered to get rid of the implementation via the `AbstractScopeSniff` as that implementation actually makes the sniff _more complicated_ instead of _less complicated_.

Includes unit tests.
... for code in the sniff previously not covered by tests.
@jrfnl jrfnl force-pushed the feature/1357/squiz-staticthisusage-fix-false-positive-nested-closure branch from bb14224 to 2da3413 Compare March 3, 2026 13:50
@jrfnl
Copy link
Member Author

jrfnl commented Mar 3, 2026

Squashed the "fix up" commit from the review into the canonical commit it belongs with.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Squiz.Scope.StaticThisUsage false positive for Closure::bind closure inside static method

2 participants