Skip to content

Sniff-specific ignore rules inside rulesets are filtering out too many files #2391

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

Closed
wvega opened this issue Jan 28, 2019 · 6 comments
Closed
Assignees
Milestone

Comments

@wvega
Copy link
Contributor

wvega commented Jan 28, 2019

Consider the following custom standard (phpcs.xml):

<?xml version="1.0"?>
<ruleset name="Custom Standard">
    <rule ref="WordPress">
        <exclude-pattern>/the/content/of/the/pattern/is/irrelevant/</exclude-pattern>
    </rule>
</ruleset>

If the path to the project using that standard file includes wordpress (the name of the referenced rule) at any level, PHPCS will ignore all files on that project. The list of files to check is empty, even if other rules are being referenced in the standard without using an exclude pattern.

The way I understand it, on v3.4.0 and up to 8c94cf9 (at least), when exclude-patterns are defined for specific standards, categories or sniffs, the Ruleset::getIgnorePatterns() method returns an array with a structure similar to:

$ignorePatterns = [
    'WordPress' => [
        '/the/content/of/the/pattern/is/irrelevant/' => 'absolute'
    ],
    ...
    'WordPress.PHP.YodaConditions.NotYoda' => [
        '/the/content/of/the/pattern/is/irrelevant/' => 'absolute'
    ],
    ...
]

That array is later used on the shouldIgnorePath() method, as follows:

foreach ($ignorePatterns as $pattern => $type) {
    // ...
    if (preg_match($pattern, $testPath) === 1) {
        return true;
    }
}

So that the name of the standard, category or sniff ends up being used as the pattern to ignore.

When the exclude-pattern is specific to a category of sniffs or a single sniff, then is very unlikely that the name of that category or sniff matches the path of any file on the project, but when the exclude-pattern is specific to a standard with a single word name (like WordPress above) the problem is more likely to appear.


I'll submit a PR with a test for this issue in a moment.


Related to #686.

@jrfnl
Copy link
Contributor

jrfnl commented Jan 28, 2019

@wvega Thanks for setting up that unit test, I'm looking into this now.

@jrfnl
Copy link
Contributor

jrfnl commented Jan 29, 2019

@wvega I've send you a PR - wvega#1 - which will update PR #2392 when merged, and which should fix this issue.

It would be great if you could have a look and test the PR (and merge it if you think the proposed solution is acceptable).

@wvega
Copy link
Contributor Author

wvega commented Jan 29, 2019

@jrfnl thank you for checking this issue so quickly. I just merged your PR. The solution looks great and fixes the problem I was having on my project.

@jrfnl
Copy link
Contributor

jrfnl commented Jan 29, 2019

@wvega It's something I'd come across a few times myself, but I hadn't investigated to determine the cause yet. Your clear explanation of the issue made it an easy one to (finally) solve now ;-)

@aik099
Copy link
Contributor

aik099 commented Feb 5, 2019

While detecting (via debugging PHP_CodeSniffer) what exclude-pattern to use I've also noticed, that \PHP_CodeSniffer\Filters\Filter::shouldIgnorePath is processing combined array of ruleset + per-sniff exclude patterns and actually tries to compare sniff name against path. This doesn't do any bad for now, but if you have lots of per-sniff exclusion rules, then it would slow down file checking process.

Thanks for finding that out.

@gsherwood gsherwood added this to the 3.5.0 milestone Mar 22, 2019
@peternolland peternolland self-assigned this May 23, 2019
@peternolland peternolland changed the title Filter::shouldIgnorePath() incorrectly compares standard/categories/sniff names against file paths to decide whether a file is ignored or not Sniff-specific ignore rules inside rulesets are filtering out too many files May 23, 2019
peternolland added a commit that referenced this issue May 23, 2019
…tering out too many files

Moved is_array check earlier in shouldIgnorePath() as:
    $this->config->ignored was an array of pattern => string,
where as
    $this->ruleset->getIgnorePatterns() was an array of ref => [pattern => string]

Which meant the original array_merge was not merging the arrays correctly, which caused all files to be excluded as when the rule ref name appeared in the projects path.
@peternolland
Copy link
Contributor

fixed in PR #2392

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

5 participants