eslint: Bug: [flat config] Global `ignores` matches differently from non-global `ignores`
Environment
Node version: v18.12.1 npm version: 8.19.2 Local ESLint version: v8.41.0 Global ESLint version: none Operating System: Linux or MacOS
What parser are you using?
Default (Espree)
What did you do?
Configuration
eslint-global-ignore.config.js
export default [
{
ignores: ['ignored/'],
},
{
rules: {
'no-undef': 'error',
},
},
];
eslint-files-ignore.config.js
export default [
{
files: ['**/*.js'],
ignores: ['ignored/'],
rules: {
'no-undef': 'error',
},
},
];
file.js and ignored/file.js
console.log();
What did you expect to happen?
Not sure what is the correct intended behavior here, so raising this issue for the maintainers’ consideration. Based on the documentation (Globally ignoring files with ignores), it looks like ignores can match and ignore an entire directory tree:
{
// Ignores directory tree
ignores: ["ignored/"],
}
However, if the same ignores pattern is used in a configuration block which also has files, then the pattern is interpreted completely differently, and does not have the same effect:
{
files: ["**/*.js"],
// Does *not* ignore directory tree
ignores: ["ignored/"],
}
Rather, to ignore the entire top-level ignored tree, the ignores pattern needs to be adjusted as follows:
{
files: ["**/*.js"],
- ignores: ["ignored/"],
+ ignores: ["ignored/**"],
}
Is this difference in behavior between the two ignores (global and non-global) intentional? And if so, can it be explicitly documented, if not already? It seems like a surprising “gotcha”.
What actually happened?
$ ESLINT_USE_FLAT_CONFIG=true eslint -c eslint-global-ignore.config.js .
/repo/file.js
1:1 error 'console' is not defined no-undef
✖ 1 problems (1 errors, 0 warnings)
$ ESLINT_USE_FLAT_CONFIG=true eslint -c eslint-files-ignore.config.js .
/repo/ignored/file.js
1:1 error 'console' is not defined no-undef
/repo/file.js
1:1 error 'console' is not defined no-undef
✖ 2 problems (2 errors, 0 warnings)
Link to Minimal Reproducible Example
https://stackblitz.com/edit/eslint-ignore-pattern-inconsistency
Participation
- I am willing to submit a pull request for this issue.
Additional comments
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 17 (16 by maintainers)
@Rec0iL99 @mdjermanovic please be sure to take a stab at priority and impact when triaging. 😃
@mxxk @fasttime while I appreciate the enthusiasm, I think this is a pretty hairy change that I’d like to take myself. Definitely not a good first contribution to ESLint due to the complexity.
Thanks for your interest @mxxk! I haven’t looked into most of this code before, but I’ll try to point out what I think are the relevant parts. I will also do my best to answer any questions that may pop up while you progress.
This is where a directory matched by a global ignore pattern is filtered out:
https://github.com/eslint/eslint/blob/4f5440db631707b17140c4e5cc7beb223afbd2b9/lib/eslint/eslint-helpers.js#L279
The implementation of
isDirectoryIgnoredis in a different repository: https://github.com/humanwhocodes/config-array/blob/v0.11.9/src/config-array.js#L865-L925The
configsobject on which the method is called is the resolvedFlatConfigArrayobject that contains information about all globalignoresused.This is also done in the
config-arrayrepo:https://github.com/humanwhocodes/config-array/blob/v0.11.9/src/config-array.js#L302
The function
shouldIgnorePathis very simple, in that it tries to match a given file path against a list of ignore patterns. But what we would actually like to do additionally is to match the parent directories of that file against the list of ignore patterns. A possible impementation could be similar to what is being done in the core ofisDirectoryIgnored, except that in this case the list of ignore patterns would have to come directly from a config element (config.ignores), not from the globalignoresof the resolvedFlatConfigArrayobject. Also, I don’t think that we can reuse the caching logic ofisDirectoryIgnored, because the results would need to be specific to the config element that contains the ignore patterns.When you feel confident enough to start working on a change, this is what I would do next:
eslintandconfig-arrayrepos. Make sure you can test and build both projects locally.config-arrayin a local branch, including tests.config-arrayineslint. You can copy your localconfig-arrayfolder toeslint/node_modules/@humanwhocodes/config-arraymanually or usingnpm link.config-arrayand submit a PR.config-arrayineslint, add unit tests and update the docs.eslintand submit a new PR.It is intentional. Patterns in global
ignorescan match directories for performance reasons so that ESLint doesn’t traverse ignored directories. Patterns in non-globalignoresare supposed to match in the same way as patterns infiles, that is to match only files.In my opinion, this is indeed confusing. I think we should update the non-global
ignoresmatching to work the same as globalignoresmatching. @nzakas what do you think?Hi @mxxk, thanks for the issue.
ignoresuses minimatch which is mentioned in the docs.You would need to specify
ignored/**for any files in the ignored folder to match in theignoreskey. This does not look like a bug.Edit: I now see your point about the
ignoresglobally working withoutignored/**. I’m confused.@mdjermanovic please verify. Thanks.