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

Directory exclusions do not work as expected when a single file name is passed to phpcs #1731

Closed
toolstack opened this issue Oct 19, 2017 · 10 comments
Milestone

Comments

@toolstack
Copy link

GlotPress has been using phpcs in conjunction with TravisCI, we've created a phpcs.xml that includes several directory exclusions like:

<exclude-pattern>/tests/*</exclude-pattern>

However these do not function as expected when TravisCI runs against a PR.

Looking through the phpcs code, the shouldIgnorePath() method in /Filters/Filter.php, includes this code:

        if (is_dir($path) === true) {
            $ignorePatterns = $this->ignoreDirPatterns;
        } else {
            $ignorePatterns = $this->ignoreFilePatterns;
        }

Which checks to see if the path passed in to the function is a directory or a file and picks which exclusions to check (directory or file).

However when a file name is passed in to phpcs, like: (which is what happens on a PR with TravisCI)

phpcs --standard=phpcs.xml tests/phpunit/testcases/test_links.php

the directory exclusions are never checked as only the full path and filename are passed in to shouldIgnorePath().

As this individual file is not a directory, only the file ignore patterns are checked against and the filename.

This is easily observable by instead of using a directory pattern of /tests/*, just using /tests in the exclusion-pattern, which will get added as a file pattern.

A fix appears to be to change the above code to:

        if (is_dir($path) === true) {
            $ignorePatterns = $this->ignoreDirPatterns;
        } else {
            $ignorePatterns = array_merge($this->ignoreFilePatterns, $this->ignoreDirPatterns);
        }

Which ensures that when a file is checked, both file and directory patterns are used.

I can create a PR for the above if that makes sense.

@jrfnl
Copy link
Contributor

jrfnl commented Oct 20, 2017

Interesting, though I have not been able to reproduce the issue.

@toolstack
Copy link
Author

Try the following:

PHP-CodeSniffer/bin$ ./phpcs ../tests

Which will output:

................ 16 / 16 (100%)


Time: 162ms; Memory: 6Mb

Now try:

PHP-CodeSniffer/bin$ ./phpcs --ignore=*/tests/* ../tests

Which will output:

... 3 / 3 (100%)


Time: 49ms; Memory: 6Mb

(which is actually incorrect as it should have excluded the three files in the root of the tests directory)

Finally, try:

PHP-CodeSniffer/bin$ ./phpcs --ignore=*/tests/* ../tests/Core/File/FindExtendedClassNameTest.php

Which will output:

. 1 / 1 (100%)


Time: 47ms; Memory: 6Mb

However the expected output should be no files checked as we've explicitly told phpcs not to check files in the tests directory.

This is a result of how the directory tree is "walked" in each case:

  • In the second case, the walk is started inside of the tests directory, so shouldIgnorePath() is never called on the tests directory name itself, just on the three files inside of it. Then shouldIgnorePath() is called on the Code and Standards subdirectories and they are excluded from the walk as they match the directory pattern.

  • In the third case, shouldIgnorePath() is never called on any directory name as the root of the walk is a single file, which means the directory exclusions are never checked.

If you run the following command:

PHP-CodeSniffer/bin$ ./phpcs --ignore=*/tests ../tests/Core/File/FindExtendedClassNameTest.php

You'll get the expected output of:



Time: 28ms; Memory: 4Mb

because the pattern is stored as a file pattern instead of a directory pattern and the file is excluded "properly" when it is passed to shouldIgnorePath().

@pattonwebz
Copy link

Ran accross this issue as well today. I have */tests/* directory as excluded pattern in the ruleset, Travis still fails on items in the tests directory :'(

pattonwebz added a commit to pattonwebz/primary-category-plugin that referenced this issue Oct 28, 2017
  The directory should be excluded but it isn't. See here for reasoning:
squizlabs/PHP_CodeSniffer#1731
pattonwebz added a commit to pattonwebz/primary-category-plugin that referenced this issue Oct 28, 2017
* scaffolded tests from wpcli

* Add first test

* Don't check tests or bin directory with phpcs

* Remove commented out code

* Fix comments

* maybe exclude default index.php files in project??

* some param and comments updates

* Spacing fixes

* Fix missed spacing correction

* Add a comment above the sample tests to stop phpcs shouting at us.
  The directory should be excluded but it isn't. See here for reasoning:
squizlabs/PHP_CodeSniffer#1731

* Added some tests for class existance.

* Try again to exclude the test file

* Don't test on php 5.3. Add test on  7.0,7.1,7.2

* Test on 4.8... not time for 4.9 yet

* Try readd php 5.3, also try 5.6 and 7.0 in martix

* Try again with php 5.3 compat

* PHP 5.3 instaed of 5.2...

* PHP 5.3/5.2 compat - no shorthad arrays in early versions.

* Try better matrix for travis
pattonwebz added a commit to pattonwebz/primary-category-plugin that referenced this issue Oct 30, 2017
* scaffolded tests from wpcli

* Add first test

* Don't check tests or bin directory with phpcs

* Remove commented out code

* Fix comments

* maybe exclude default index.php files in project??

* some param and comments updates

* Spacing fixes

* Fix missed spacing correction

* Add a comment above the sample tests to stop phpcs shouting at us.
  The directory should be excluded but it isn't. See here for reasoning:
squizlabs/PHP_CodeSniffer#1731

* Added some tests for class existance.

* Try again to exclude the test file

* Don't test on php 5.3. Add test on  7.0,7.1,7.2

* Test on 4.8... not time for 4.9 yet

* Try readd php 5.3, also try 5.6 and 7.0 in martix

* Try again with php 5.3 compat

* PHP 5.3 instaed of 5.2...

* PHP 5.3/5.2 compat - no shorthad arrays in early versions.

* Try better matrix for travis

* These tests identified an issue with the shortcode if no id/anything is passed.

* Tests added for shortcode class

* Fix type for 'parent'

* Simple test that shortcode exists

* Testing that classes added exists and can be instansiated

* Assert both constants are defined in a single test

* Make the class instanceof test php 5.4 compatible and below
@toolstack
Copy link
Author

@jrfnl have you had a chance to try my above instructions?

@ikappas
Copy link

ikappas commented Nov 2, 2017

I've run into this issue as well. Can @gsherwood have a look?

@gsherwood
Copy link
Member

This is a bug. PHPCS should ignore the file if the standard's (or CLI specified) ignore patterns match it.

gsherwood added a commit that referenced this issue Nov 8, 2017
@gsherwood
Copy link
Member

The Filter class has an optimisation in it (compared to 2.x) so that it only run a regex check for filters that look like they are excluding entire directories (end with /*) when it gets to a directory path. This saves a lot of time if your standard has a lot of file-specific ignore patterns, as someone previously reported to me.

So that works fine, but the code wasn't using those directory-specific ignore patterns when it encountered an individual file path, which happens when you ask PHPCS to check a specific file.

This behaviour was different from 2.x where all patterns were checked for all paths. So the optimisation looks to have caused this issue, which has now been resolved by checking all ignore patterns for file paths, but only directory ignore patterns for directories.

Thanks for reporting this.

@gsherwood gsherwood added this to the 3.2.0 milestone Nov 8, 2017
@toolstack
Copy link
Author

toolstack commented Nov 8, 2017

Thanks @gsherwood for resolving this, any timeline for 3.2 yet?

@gsherwood
Copy link
Member

any timeline for 3.2 yet?

No idea yet. My day job is pretty crazy at the moment, but I'm getting through the todo list when I can.

@mtangoo
Copy link

mtangoo commented Dec 27, 2019

Encountered an issue similar to this (I need to confirm before I open bug report

$ phpcs --version
PHP_CodeSniffer version 3.5.1 (stable) by Squiz (http://www.squiz.net)

if I run phpcs --standard=PSR12,PSR2 --extensions=php --ignore=*/vendor/,*/tests/,*/runtime/,*/web/ my_file.php it does not work. If I remove */tests/* or rename it to */test/* then it works fine and I get warnings.

Is this the same issue or I should open different ticket?

pereirinha added a commit to cloudinary/cloudinary_wordpress that referenced this issue Nov 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants