Skip to content

Conversation

jrfnl
Copy link
Contributor

@jrfnl jrfnl commented May 7, 2017

While working on making a custom standard compatible with PHPCS 3.x using class_alias()-es, a number of sniff files were getting misidentified by the autoloader causing PHPCS to choke.

This change fixes the issue I was encountering by using the the $newClasses diff in reverse.

While debugging this I noticed copy/paste artifacts in the subsequent checks for new interfaces and traits. Both of which were - incorrectly - being compared against the $classes variable.
I've taken the liberty to rename the local variables related to this as well to make the distinction clearer.

While working on making a custom standard compatible with PHPCS 3.x using `class_alias()`-es, a number of sniff files were getting misidentified by the autoloader causing PHPCS to choke. This change fixes the issue I was encountering by using the the `$newClasses` diff in reverse. While debugging this I notices copy/paste artefacts in the subsequent checks for new interfaces and traits. Both of which were - incorrectly - being compared against the `$classes` variable. I've taken the liberty to rename the local variables related to this as well to make the distinction clearer.
@jrfnl jrfnl changed the title 🔥 Fix PHPCS native autoloader & class recognition. 🔥 Fix PHPCS native autoloader & class recognition in PHPCS 3.x. May 7, 2017
@gsherwood
Copy link
Member

The $newClasses var name is intentional as I used the term class to refer to all 3 types throughout the code. But it's no big deal to change them - the behaviour will be the same and if it makes it clearer then all good too.

I need to give the main change more thought and more testing. I previously just grabbed the last class in the list and assumed that was the loaded one, but that was causing issues with HHVM so I changed to looking from the front of the list and finding the first unknown class. The commit is here: 12bcb35

I don't have more detail on the commit, but I'm pretty sure HHVM was just dumping classes in whatever order it felt like so I couldn't rely on the order in any way.

@jrfnl
Copy link
Contributor Author

jrfnl commented May 8, 2017

I suspect the other issue I reported #1453 might be loosely related to this as well. I'll see if I can do some more debugging and think of a more stable solution.

@gsherwood
Copy link
Member

Note: HHVM version at the time of failure was

$ php --version HipHop VM 3.6.6 (rel) Compiler: tags/HHVM-3.6.6-0-gead6875c956d4bd5e906ebea899c71c3b8a7182d Repo schema: 5034239b4e72c991556d7e651946e7fe89d8c2f4 
@gsherwood
Copy link
Member

gsherwood commented May 9, 2017

So I bit of debugging on a newer HHVM (3.19.2-dev (rel)) shows that HHVM's declared classes list is pretty different.

This is vanilla PHP loading a couple of the PHPCompat classes:

Classes loaded when including PHPCompatibility/PHPCompatibility/Sniff.php: Array ( [143] => PHPCompatibility\PHPCSHelper [144] => PHP_CodeSniffer\Files\File [145] => php_codesniffer_file [146] => php_codesniffer_tokens [147] => PHP_CodeSniffer\Exceptions\RuntimeException [148] => php_codesniffer_exception [149] => PHPCompatibility\Sniff ) Classes loaded when including PHPCompatibility/PHPCompatibility/Sniffs/PHP/CaseSensitiveKeywordsSniff.php: Array ( [143] => PHPCompatibility\PHPCSHelper [144] => PHP_CodeSniffer\Files\File [145] => php_codesniffer_file [146] => php_codesniffer_tokens [147] => PHP_CodeSniffer\Exceptions\RuntimeException [148] => php_codesniffer_exception [149] => PHPCompatibility\Sniff [150] => PHPCompatibility\Sniffs\PHP\CaseSensitiveKeywordsSniff ) 

And this is HHVM:

Classes loaded when including PHPCompatibility/PHPCompatibility/Sniff.php: Array ( [303] => PHP_CodeSniffer\Exceptions\RuntimeException [305] => PHP_CodeSniffer\Files\File [306] => PHPCompatibility\Sniff [310] => PHPCompatibility\PHPCSHelper ) Classes loaded when including PHPCompatibility/PHPCompatibility/Sniffs/PHP/CaseSensitiveKeywordsSniff.php: Array ( [303] => PHP_CodeSniffer\Exceptions\RuntimeException [304] => PHPCompatibility\Sniffs\PHP\CaseSensitiveKeywordsSniff [306] => PHP_CodeSniffer\Files\File [307] => PHPCompatibility\Sniff [311] => PHPCompatibility\PHPCSHelper ) 

So it looks as if class_alias() isn't doing anything, and that the order of classes is almost backwards, but not quite. I'm not sure what to do about this yet.

@gsherwood
Copy link
Member

gsherwood commented May 9, 2017

I had to swap around the trait and interface checks to make HHVM work properly again, but I think adding the array_reverse() to the class list is looking ok for HHVM support.

The key problem I was previously solving is that the actual included class could pop up in the middle of the list, so I cant rely on the first or last class name to be correct. But going through and looking for the first class we don't yet know about seems to work in HHVM both forwards and backwards, especially given the aliases don't appear in the list.

So I'll commit the changes I've made to get HHVM and PHPCompat support going again and we'll see what travis says.

gsherwood added a commit that referenced this pull request May 9, 2017
@gsherwood
Copy link
Member

Looks like it worked. I'm assuming that's going to work for you given it's pretty much what you had, but can you check it for me please?

@jrfnl
Copy link
Contributor Author

jrfnl commented May 9, 2017

Thanks for looking into this. I'll test this later today.

Looks like your commit is missing the additional bugfix I added though:

While debugging this I noticed copy/paste artifacts in the subsequent checks for new interfaces and traits. Both of which were - incorrectly - being compared against the $classes variable.

The variable rename was just to make it more obvious those blocks work with different data and can be left out, but I kind of think you intended to do the array_diff against the relevant arrays ?

if ($className === null) {
$newClasses = array_reverse(array_diff(get_declared_traits(), $classes));
foreach ($newClasses as $name) {
$newTraits = array_reverse(array_diff(get_declared_traits(), $traits));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

⬆️ The $traits here

if ($className === null) {
$newClasses = array_reverse(array_diff(get_declared_interfaces(), $classes));
foreach ($newClasses as $name) {
$newInterfaces = array_reverse(array_diff(get_declared_interfaces(), $interfaces));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

⬆️ The $interfaces here

@jrfnl
Copy link
Contributor Author

jrfnl commented May 9, 2017

Tested & found working. Thanks!

P.S.: not closing the issue yet as my remark about the trait/interface array_diffs most likely still needs addressing.

gsherwood added a commit that referenced this pull request May 9, 2017
@gsherwood
Copy link
Member

not closing the issue yet as my remark about the trait/interface array_diffs most likely still needs addressing.

Unbelievable. I looked at the code so many times and never saw that. It's amazing nothing ever broke. Thanks a lot for pointing that out again.

@jrfnl
Copy link
Contributor Author

jrfnl commented May 9, 2017

Happens to the best of us ;-)

Anyway, as the additional commit has now been made, I believe this PR can be closed. Agreed ?

@gsherwood
Copy link
Member

Agreed :)

@gsherwood gsherwood closed this May 9, 2017
@jrfnl jrfnl deleted the feature/3.x-fix-broken-autoload-class-identifying branch May 9, 2017 23:42
@gsherwood gsherwood added this to the 3.0.1 milestone Jun 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants