-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
feat: Implement alternate config lookup #18742
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for docs-eslint canceled.
|
There are merge conflicts now. |
I'll look at those, but if you can please review ASAP I'd appreciate it. This is a complicated change and there will continue to be more conflicts until we get this merged. It's already been three weeks since I posted it. |
lib/eslint/eslint-helpers.js
Outdated
const configs = rawPatterns[matchIndex] !== "." && !entry.path.includes("/") | ||
? void 0 | ||
: await configLoader.loadConfigArrayForDirectory(absolutePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Special-casing only immediate children would cause inconsistent behavior, in my opinion. For example, if the root config file ignores foo
and bar/baz
directories, and both of them have their own config files, eslint foo
would work, while eslint bar/baz
wouldn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I'm having trouble following what it is you're describing. Can you put together a test case that will fail?
And do you have other suggestions for how you might approach this? It turns out getting the exact behavior in the RFC is pretty difficult and this was the only approach I found that passed all of the tests we had described there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a test case: bb439b1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One approach could be to search per each pattern and start loading configs from globParent()
of the pattern. That's how eslintrc's FileEnumerator works. A downside is performance as the same directories might be traversed multiple times.
Another approach could be to keep searching with multiple patterns at once but check if the directory path is a part of the globParent()
of at least one of the patterns, and in that case enter the directory even if it's ignored by a config in a parent directory. Though, this seems complicated as only those patterns should match in the directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's another test that I think should pass but is failing with the current iteration of this PR: 7e21937
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another possible approach: perhaps we could always group patterns by their globParent()
and start loading configs from that path.
There is a new merge conflict now and the tests were not run. |
Added in @mdjermanovic's test and removed the check for immediate children. Somehow, this caused all tests to pass. 😄 Maybe I'm missing something, though. |
LGTM, thanks! Leaving open for @mdjermanovic to complete his review. |
lib/eslint/eslint-helpers.js
Outdated
const configs = rawPatterns[matchIndex] !== "." | ||
? void 0 | ||
: await configLoader.loadConfigArrayForDirectory(absolutePath); | ||
|
||
return !configs?.isDirectoryIgnored(absolutePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, on this branch, a pattern like **/*.js
would traverse all directories, which is not what we want, I believe.
To reproduce, add console.log(entry.path);
at the beginning of async directoryFilter(entry)
and run npx eslint "**/*.js"
.
.cache
.git
.git/hooks
.git/info
.git/logs
.git/logs/refs
.git/logs/refs/heads
.git/logs/refs/remotes
.git/logs/refs/remotes/origin
.git/logs/refs/remotes/origin/chore
.git/logs/refs/remotes/origin/docs
.git/logs/refs/remotes/origin/fix
.git/logs/refs/remotes/origin/renovate
.git/objects
.git/objects/00
.git/objects/01
.git/objects/02
.git/objects/03
.git/objects/04
.git/objects/05
.git/objects/06
.git/objects/07
.git/objects/08
.git/objects/09
.git/objects/0a
.git/objects/0b
.git/objects/0c
.git/objects/0d
.git/objects/0e
... (~10,000 directories)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm yeah, that's not right. I'll take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not able to reproduce this (Windows 10). Are you sure you're using the right command (npx eslint
would download ESLint if you don't have it locally?). Here's what I'm getting:
$ node ./bin/eslint.js "**/*.js"
(node:5064) ESLintIgnoreWarning: The ".eslintignore" file is no longer supported.
Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files
(Use `node --trace-warnings ...` to show
where the warning was created)
.cache
.git
.github
.nyc_output
.trunk
.vscode
bin
build
conf
coverage
docs
lib
messages
node_modules
packages
templates
tests
tmp
tools
Oops! Something went wrong! :(
ESLint: 9.9.1
No files matching the pattern "**C:/Program Files/Git/*.js" were found.
Please check for typing mistakes in the pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Something went wrong! :(
ESLint: 9.9.1
No files matching the pattern "**C:/Program Files/Git/*.js" were found.
Please check for typing mistakes in the pattern.
That "**C:/Program Files/Git/*.js"
looks weird, I'm not sure where it did come from when running $ node ./bin/eslint.js "**/*.js"
(maybe your shell is doing some expansion despite the quotes?).
I tried again, on this branch, with a clean npm install
, and in cmd.exe which doesn't expand globs. I also added console.log({ patterns });
at the beginning of async function globSearch
to make sure that the pattern is passed through.
C:\projects\eslint>node ./bin/eslint.js "**/*.js"
(node:7136) ESLintIgnoreWarning: The ".eslintignore" file is no longer supported. Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files
(Use `node --trace-warnings ...` to show where the warning was created)
{ patterns: [ 'C:\\projects\\eslint\\**\\*.js' ] }
.cache
.git
.git/hooks
.git/info
.git/logs
.git/logs/refs
.git/logs/refs/heads
.git/logs/refs/remotes
.git/logs/refs/remotes/origin
.git/logs/refs/remotes/origin/chore
.git/logs/refs/remotes/origin/docs
.git/logs/refs/remotes/origin/fix
.git/logs/refs/remotes/origin/renovate
.git/objects
.git/objects/00
.git/objects/01
.git/objects/02
.git/objects/03
.git/objects/04
.git/objects/05
.git/objects/06
.git/objects/07
.git/objects/08
.git/objects/09
.git/objects/0a
.git/objects/0b
.git/objects/0c
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I can see this in cmd
but not in Git Bash. It looks like Git Bash is representing the path in Windows differently:
patterns: [
'C:\\Users\\nzaka\\projects\\eslint\\eslint\\**C:\\Program Files\\Git\\*.js'
]
I'll take a look at that, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it looks like Git for Windows is expanding the pattern even if it's quoted.
git-for-windows/git#5131
} | ||
} | ||
}); | ||
const failFilePath = fs.realpathSync(ge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the expected behavior in this case when cwd has some files in it? When I add a file (any file, e.g.. file
with no extension) directly into subdir-only-config
, the test fails with "Error: Could not find config file.".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we explicitly defined this behavior. Technically, throwing an error is correct because our logic says "for a given file, if you can't find a config file that tells you what to do with it, throw an error."
I'm not sure how common it would be for someone to run eslint .
in a directory without a config file. This might be a case where we leave this behavior as-is and see what feedback we get. Otherwise, I'd be back to checking "if pattern is .
and file is an immediate child of .
, then ignore it".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that throwing an error when a pattern matches a file for which a config file cannot be found is the correct behavior.
@mdjermanovic I've been fighting with this for the last three days and have made zero progress. Do you want to take a stab at it? |
Hold that thought! I might have figured it out. |
Co-authored-by: 唯然 <[email protected]>
Co-authored-by: 唯然 <[email protected]>
Co-authored-by: Francesco Trotta <[email protected]>
Prerequisites checklist
What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[ ] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofix to a rule
[ ] Add a CLI option
[x] Add something to the core
[ ] Other, please explain:
What changes did you make? (Give an overview)
Implemented the design from eslint/rfcs#120:
unstable_config_lookup_from_file
flagConfigLoader
andLegacyConfigLoader
findFiles()
to use new config scheme.Fixes #18385
Is there anything you'd like reviewers to focus on?
Marking as a draft because I'd like us to merge #18134 first.
Note that I did not remove the config loading logic from the
ESLint
class, I just duplicated it in theconfig-loader.js
file in order to have an easier merge once #18134 is merged. (This accounts for the linting error ineslint.js
)