[import/no-unused-modules] - "No files matching the pattern" error
I'm using both eslint-plugin-import and eslint-plugin-json. When there are only *.json files in my project, I get "No files matching the pattern" error from the import/no-unused-modules rule, and ESLint crashes.
Steps to reproduce:
- Clone this minimal reproducible case: https://github.com/EvgenyOrekhov/eslint-config-hardcore/tree/no-files-matching-the-pattern-bug
npm installnpm test
Actual result:
> [email protected] test C:\eslint-config-hardcore
> eslint --ext .js,.json .
Oops! Something went wrong! :(
ESLint: 6.8.0.
No files matching the pattern "C:\eslint-config-hardcore" were found.
Please check for typing mistakes in the pattern.
npm ERR! Test failed. See above for more details.
Expected result: there should be no "No files matching the pattern" error, there should be only one warning from eslint-plugin-json
> [email protected] test C:\eslint-config-hardcore
> eslint --ext .js,.json .
C:\eslint-config-hardcore\invalid.json
1:2 error Expected a JSON object, array or literal json/*
✖ 1 problem (1 error, 0 warnings)
npm ERR! Test failed. See above for more details.
When I remove the import/no-unused-modules rule from .eslintrc.json, the problem goes away.
Note that it's not about *.json files. It's about the absence of *.js files. If I try to use the import/no-unused-modules rule in a TypeScript project, and if there are no *.js files, I get the same error.
This is an error coming from eslint itself. By default, if you're linting "no javascript files", it's probably a bug.
If you have no .foo files, don't pass .foo to --ext.
@ljharb I have a config that has ~500 rules from 15 different plugins, and only import/no-unused-modules is causing this error.
Indeed; it's the only rule where we're using eslint's FileEnumerator logic (which is what the command-line eslint uses as well).
You can fix it by configuring here src to be an empty array (it defaults to process.cwd()).
@ljharb Will it actually perform the analysis this way? Reading the docs makes me think it won't.
If you have no .js files, then there's nothing to analyze - json files don't import anything. If you have .ts files, then configure src to be ['**/*.ts'].
@ljharb I would like to be able to use my config in any project, irregardless of which types of files they have, without having to readjust the import/no-unused-modules rule for each one. Is it possible somehow?
I'm not sure how; many rules - including that one - require per-project config, and env settings are always app-specific.
@ljharb
If you have no
.foofiles, don't pass.footo--ext.
I just tried running eslint --ext .json . on my example, still got the "No files matching the pattern" error.
I see what you're saying; but the assumption is that an eslint config is always running on the full set of files that config applies to.
One thing you could do is configure using overrides a no-unused-modules rule for each file extension. Does that work?
@ljharb Tried this:
test.ts
export default 123;
.eslintrc.json
{
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": ["import"],
"overrides": [
{
"files": ["*.ts"],
"rules": {
"import/no-unused-modules": [
"error",
{
"missingExports": false,
"unusedExports": true
}
]
}
}
]
}
> eslint --ext .ts .
Oops! Something went wrong! :(
ESLint: 6.8.0.
No files matching the pattern "C:\eslint-config-hardcore" were found.
Please check for typing mistakes in the pattern.
npm ERR! Test failed. See above for more details.
src isn't configured in that example for the import/no-unused-modules rule; could you configure it?
@ljharb Yeah, adding "src": ["**/*.ts"], fixed the error.
So, in order to have a generic config that would work with several file extensions without throwing any errors, I would have to do this:
{
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": ["import"],
"overrides": [
{
"files": ["*.js"],
"rules": {
"import/no-unused-modules": [
"error",
{
"src": ["**/*.js"],
"missingExports": false,
"unusedExports": true
}
]
}
},
{
"files": ["*.ts"],
"rules": {
"import/no-unused-modules": [
"error",
{
"src": ["**/*.ts"],
"missingExports": false,
"unusedExports": true
}
]
}
},
{
"files": ["*.jsx"],
"rules": {
"import/no-unused-modules": [
"error",
{
"src": ["**/*.jsx"],
"missingExports": false,
"unusedExports": true
}
]
}
},
{
"files": ["*.tsx"],
"rules": {
"import/no-unused-modules": [
"error",
{
"src": ["**/*.tsx"],
"missingExports": false,
"unusedExports": true
}
]
}
}
]
}
I guess I could live with that, but I would rather prefer to not have to do it.
Yes, that seems right to me.
One last try for a single config - what if you do "src": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]?
@ljharb Tried doing that, plus the same extensions in the 'files' array - got the error.
In that case I think the multiple configs is the only current option.
It seems useful to preserve the error if any of the globs you provide result in matching zero files.
If I had to do it for every rule, that would be horrible.
Very true, but most rules apply to a file; this one has to check a whole codebase.
@ljharb Trying to fix it here: https://github.com/EvgenyOrekhov/eslint-config-hardcore/pull/59/files. Something weird is going on, now I'm getting a false positive: https://travis-ci.org/EvgenyOrekhov/eslint-config-hardcore/builds/659511799#L213. Am I missing something?
Hmm, i wonder if with this approach, TS files not used by TS files (etc) would be considered unused.
In other words, I’m no longer sure if it’s possible for this rule to support the use case of running on “not every extension the codebase uses at once”. In other words, this might after all require each project to configure it themselves (ie, it might not be possible to configure it in a generic sense, for a shared config)
I know that in ESLint 7 they will have some changes to the way ESLint handles file extensions. For example, they will not require using the --ext option, having overrides with specific extensions will be enough. Maybe it will fix this issue with no-unused-modules.
@ljharb I upgraded ESLint to 7.0.0 and removed the --ext option in my examples (the minimal reproducible case and the workaround), and I'm still getting the same errors.
@EvgenyOrekhov when i clone your minimal repro, and run npm install, npm test passes (as does npx eslint . and npx eslint --ext=.json *.json). What should I see?
@ljharb Make sure you checkout the no-files-matching-the-pattern-bug branch after you clone the repo. I get No files matching the pattern "C:\eslint-config-hardcore" were found. error.
I updated the code to use eslint . command. The goal is to make eslint . command (without any extra options like --ext) work even when there are no *.js files in the folder.
@ljharb I added a Travis CI config, you can see the log here: https://travis-ci.com/github/EvgenyOrekhov/eslint-config-hardcore/builds/169082082.
aha, the branch :-) thanks, will look.
@EvgenyOrekhov sooooo yay? I reproduced your error, and then i npm linked in the master branch of eslint-plugin-import, and now I get:
/path/to/eslint-config-hardcore/invalid.json
1:2 error Expected a JSON object, array or literal json/*
✖ 1 problem (1 error, 0 warnings)
Looks like the next release will fix this?
@ljharb Great, looks like it will! Feel free to close this issue. I will check it once the next version is released.
Thanks for the repro case :-) if there's a trivial way to add it as a test case to this repo, so we don't regress, that would be awesome too.
Hmm; I just tried again and the error occurs again, even with it linked - but when I try to make a test case in this repo, it provides the expected error.
I wonder if merely updating your lockfile with npm update would fix it - could you confirm?