Skip to content
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

Hotfix: fn arrow closure - Squiz.Scope.StaticThisUsage #2725

Conversation

michalbundyra
Copy link
Contributor

Related #2523

I am not sure about this change as this is actually invalid code.
We cannot use $this even inside closure, as then closure is not gonna
be usable. The same in case of normal closure.

Maybe here we should have another fix then?

@gsherwood
Copy link
Member

I am not sure about this change as this is actually invalid code.

That's the point of this sniff. Because it's a runtime error, the sniff tries to determine that the code is invalid during linting.

So I think this change is a good one.

if ($next === false) {
continue;
} else if ($tokens[$next]['code'] === T_CLOSURE
|| $tokens[$next]['code'] === T_FN
|| $tokens[$next]['code'] === T_ANON_CLASS
) {
$next = $tokens[$next]['scope_closer'];
Copy link
Member

Choose a reason for hiding this comment

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

T_FN tokens don't always have a scope closer, unlike closures and anon classes. This is because the T_FN token is a real token that exists, and then scope information is added later if the syntax looks valid. But T_CLOSURE and T_ANON_CLASS are custom tokens that only get applied by PHPCS if the syntax looks good. Otherwise they are normal T_FUNCTION and T_CLASS tokens that don't have scope information.

@michalbundyra
Copy link
Contributor Author

@gsherwood

So I think this change is a good one.

I think the error should be reported if method is static and $this is used inside closure

class A {
    public $name = 'NAME';
    
    public static function m1() { // cannot be static as we are using $this in closure
        return function () {
            return $this->name;
        };
    }
    
    public static function m2() { // cannot be static as we are using $this in closure
        return fn () => $this->name;
    }
}

https://3v4l.org/XgXbX

We are not getting any errors on that code, but if we try to call method and execute the result of the method - callback, then we get the error.

Currently we are skipping that case for normal closure (T_CLOSURE), that's why I've added also the same for T_FN, but I believe we should report error in that case.

I'll submit another commit soon and you'll decide what to do.

$next = $tokens[$next]['scope_closer'];
continue;
} else if (strtolower($tokens[$next]['content']) !== '$this') {
} else if ($tokens[$next]['content'] !== '$this') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was wrong, see:
https://3v4l.org/cvN2L

}
public static function myFunc() {
$this->doSomething();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

changes tabs to spaces

}

public static function anonClassUseThis() {
return new class($this) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently, when we find anonymous class we are skipping till scope_closer, but we can use $this in params, so we really shouldn't skip it 'yet'.

The check should be more complicated here - please see also example in lines 98-110.
Errors should be reported only in line 84 and 99, not in 93 or 106.

I've implemented "similar" sniff here:
https://github.com/webimpress/coding-standard/blob/develop/src/WebimpressCodingStandard/Sniffs/PHP/StaticCallbackSniff.php
which checks if closure can be defined as static or not.

@@ -31,9 +31,13 @@ public function getErrorList()
9 => 1,
14 => 1,
20 => 1,
41 => 1,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

in my opinion it was invalid implementation before, so the error was not reported on that line - as noted in one of the previous comments - we shouldn't skip closures.

@gsherwood gsherwood added this to the 3.5.4 milestone Dec 5, 2019
@gsherwood
Copy link
Member

I'm going to remove this from the 3.5.4 milestone as it contains failing test cases that should be resolved before merging.

@gsherwood gsherwood removed this from the 3.5.4 milestone Jan 6, 2020
Related squizlabs#2523

I am not sure about this change as this is actually invalid code.
We cannot use `$this` even inside closure, as then closure is not gonna
be usable. The same in case of normal closure.

Maybe here we should have another fix then?
Recursion for anonymous classes as $this can be used in the constructor
parameter. Fixes failing tests.
@michalbundyra michalbundyra force-pushed the hotfix/static-this-usage-array-closure branch from 692aeab to 10b6b2a Compare January 6, 2020 12:21
@michalbundyra
Copy link
Contributor Author

@gsherwood I've rebased and updated the code of detecting usage of $this variable. We need to use recursion, as I pointed before, because $this can be used in instantiation of new anonymous class.

Can it be added back to 3.5.4 release, please? Thanks!

@gsherwood gsherwood added this to the 3.5.6 milestone Mar 9, 2020
gsherwood added a commit that referenced this pull request Jun 22, 2020
@gsherwood gsherwood merged commit 4372f50 into squizlabs:master Jun 22, 2020
@gsherwood
Copy link
Member

Thanks a lot for this. Sorry it's taken so long.

@michalbundyra michalbundyra deleted the hotfix/static-this-usage-array-closure branch June 22, 2020 04:46
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.

2 participants