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
New: Add overrides
and files
configuration options (refs #3611)
#8081
Conversation
LGTM |
@smably, thanks for your PR! By analyzing the history of the files in this pull request, we identified @gyandeeps, @nzakas and @sethmcl to be potential reviewers. |
Thanks! Sorry, looks like we lost track of this PR. To make this easier to review, how difficult would it be to split up @CrabDude's commit and your improvements? It's currently a bit difficult to identify which parts are different from #7177. Also, does this implement the changes that @nzakas requested in #7177 (review)? |
Hi @not-an-aardvark, no worries. Unfortunately it would be pretty difficult to split up, because I had to rewrite large parts of @CrabDude's work to ES6-ify it (the diff was pretty much useless because the indentation changed when I moved everything inside a class). I can see about trying to split it up, but I think it might be best to review this from scratch as the changes are pretty substantial (particularly when it comes to the caches). Let me know what you think. I'll add some comments on @nzakas' review on the original PR. Sorry I couldn't maintain the original PR -- not sure if there's a way to do that on a PR from a personal fork. If there is still potential for this to get merged, I'll definitely see if I can rebase and fix the conflict later today. |
LGTM |
Added comments to the original PR and fixed the merge conflict. |
Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:
Can you please update the pull request to address these? (More information can be found in our pull request guide.) |
@not-an-aardvark Turned out I had I still had the branch with the unsquashed version of this locally. I've updated this PR with the contents of the unsquashed branch. The first commit is the existing work, with some updates to make it mergeable but no functional changes. The subsequent commits represent the new stuff I've changed or added. |
Thanks! I'm planning to review this sometime in the next day or two. I'm not very familiar with the part of the codebase that this changes, so I'm hoping someone else can also review it. |
Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:
Can you please update the pull request to address these? (More information can be found in our pull request guide.) |
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 haven't gone through everything yet, but some of the small issues I've found so far.
lib/config.js
Outdated
return; | ||
} | ||
|
||
const relativePath = (filePath || directory).substr(config.baseDirectory.length + 1); |
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.
use path.relative(config, filePath)
instead.
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.
Fixed.
lib/config/config-ops.js
Outdated
} else if (config.files) { | ||
delete config.files; | ||
} | ||
configCache.setMergedVectorConfig(vector, config); |
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.
It looks like for a single config with 1 override we are going to update the same key in the Map 3 times. Once here, and twice inside getConfigFromVector
function. Do we need to set it in the getConfigFromVector
? I think pretty much all code paths goes through getConfig
.
lib/config/config-ops.js
Outdated
nearestCacheIndex = vector.length - 1; | ||
|
||
// Check the merged vector config cache to try to find a merged config for the current config or a parent | ||
for (; nearestCacheIndex >= 0; nearestCacheIndex--) { |
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.
Nit: I'd rather use decrementing while loop. Easier to read for me.
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.
Fixed.
lib/config/config-ops.js
Outdated
*/ | ||
pathMatchesGlobs(filePath, patterns) { | ||
patterns = [].concat(patterns); | ||
return patterns.every(pattern => minimatch(filePath, pattern, { matchBase: true })); |
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.
We are not protecting against "../" patterns anywhere. Those will basically never work (or at least will not work in most cases). They are also going to be really hard to wrap your head around, so I think we should filter out and ignore them.
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.
Also, I'm slightly concerned about absolute paths as well.
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.
Fixed both (will now ignore patterns with absolute paths or that contain ..
).
@@ -0,0 +1,150 @@ | |||
/** |
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.
We now have two config caches. One for config files themselves (used in file-finder.js) and one for config vectors. Do we need both of them?
lib/config/config-ops.js
Outdated
subvector.pop(); | ||
} | ||
|
||
if (config) { |
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.
This is not a very helpful comment, but all of the code that goes below seems like a black magic to me. Branching on array value types, hardcoded array indexes, etc. I sort of understand what the code is doing, but it's not very readable and is really hard to follow. Not sure what can be done to improve this (as I said, not a very helpful comment).
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.
Agreed. Using array methods like .find()
instead of loops would probably be a good idea.
Performance numbers look pretty good (although we are not testing for anything with overrides): Before:
After:
|
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.
Thanks again for the pull request. My main concern at the moment is that some of the code here is hard to follow (which was also a problem before these changes 😄). Right now it's fairly difficult to reason about the code, so I'm concerned that it might contain bugs that we won't be able to catch.
A few concrete suggestions:
- The config logic uses "vector" arrays, which seem to be holding a lot of different types of information in arrays. I'm wondering if this abstraction is necessary -- if so, then I think we should use a better datatype, and if not then we should split it up or remove it.
- Using mutable state less will also make this easier to reason about. For example, some functions in this PR end up reassigning and mutating variables many times, and it's difficult to track what's going on. Using
const
and splitting up logic into helper functions will help with this. - This logic has a lot of caches. This is fine, but right now the cache logic seems to be interspersed with everything else, so it's hard to figure out what's cached at what times, etc. If something cached, I think it's much better to have the caching behavior encapsulated by a helper function (e.g. "If this thing is in the cache, return it, otherwise get it from the filesystem"). Then the rest of the code shouldn't care whether the cache was used.
lib/config.js
Outdated
* Gets the vector of applicable configs from the hierarchy for a given file, including any overrides that apply to | ||
* the specified file path. A vector is an array of config file paths, each optionally followed by one or more | ||
* numbers that correspond to the indices of nested config blocks within the config file's overrides section whose | ||
* glob patterns match the specified file path; e.g., the vector ['/home/john/project/app/.eslintrc', 0, 2] would |
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.
Is there a reason to use an array with strings and numbers here, rather than some other data structure? An array containing multiple datatypes with different meanings seems like a code smell.
Maybe an object would be better than a "vector":
{
configFilePath: '/home/john/project/app/.eslintrc',
overrideConfigs: [
{
rules: { /* ... */ }
},
{
rules: { /* ... */ }
}
]
}
lib/config/config-file.js
Outdated
*/ | ||
function loadCached(filePath) { | ||
const cachedConfig = configCache.getConfig(filePath); | ||
let config = {}; |
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.
Initializing config
to an empty object seems unnecessary here, because it's reassigned immediately below.
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.
Fixed.
lib/config/config-ops.js
Outdated
subvector.pop(); | ||
} | ||
|
||
if (config) { |
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.
Using a more organized object instead of a "vector" with multiple datatypes would also make this easier to read.
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.
Fixed. I refactored all the code relating to vectors (still can't think of a better name) and it is now vastly more readable at the expense of a bit of performance.
package.json
Outdated
@@ -55,6 +55,7 @@ | |||
"json-stable-stringify": "^1.0.0", | |||
"levn": "^0.3.0", | |||
"lodash": "^4.0.0", | |||
"minimatch": "^3.0.0", |
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.
We already have a dependency on glob
, which we use for parsing CLI options. Can you use that instead of adding another glob-parsing dependency?
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 this seems redundant, but glob
is specifically for matching patterns against files and directories on disk. In this case, minimatch
is being used to check a file path (which is already confirmed to exist) against a specified pattern, which glob
is not able to do. And glob
actually uses minimatch
under the hood -- it just adds the filesystem traversal logic -- so the results should be the same.
lib/config.js
Outdated
if (value) { | ||
this.cliConfig[configKey] = value; | ||
} | ||
}, this); |
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.
Nitpick: If you use an arrow function here, you won't need to add a this
argument at the end.
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.
Fixed.
lib/config.js
Outdated
cache = configCache.getHierarchyLocalConfigs(localConfigDirectory); | ||
if (cache) { | ||
break; | ||
} |
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 sure I'm understanding this logic -- aren't all local config files in the same directory? Why does the cache need to be checked separately for each iteration of this loop?
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.
Local config files can be in the current directory, but they can also be in the parent directory, or any directory above the current one in the tree.
findLocalConfigFiles
actually finds all the config files in the filesystem above the specified directory. So localConfigFiles
will contain config files in various directories above the current one, some of which may have already been cached. This logic stops walking up the directory tree as soon as we hit a directory that's already in the local hierarchy cache, because it already contains all the configs for that directory and its parents.
lib/config.js
Outdated
Plugins.loadAll(this.options.plugins); | ||
config = ConfigOps.merge(config, { plugins: this.options.plugins }); | ||
} | ||
if (!configs.length && !cache && !this.useSpecificConfig) { |
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.
This logic is hard to follow. Would it be possible to split it into multiple functions?
Specifically, it's not clear to me how the presence of a cache changes the control flow. Intuitively, I would expect the cache to be an alternate way to populate configs
, but in that case its effects should be isolated, and it shouldn't be necessary to refer to the cache separately afterwards.
} | ||
|
||
/** | ||
* Gets a list of hierarchy-local config objects that apply to the specified 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.
What are "hierarchy-local config objects"?
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.
Configs parsed from config files in the filesystem hierarchy that apply to files in directories below them (as opposed to, say, the user's personal config from their homedir, or a config file passed as on option on the command line). Totally willing to change the terminology if you can think of a better way to describe these.
lib/config/config-ops.js
Outdated
getConfigFromVector(vector) { | ||
|
||
const subvector = Array.from(vector); | ||
let config, |
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.
The config
variable is reassigned in several different places, and it's mutated later on, which makes this code hard to follow. Could it be restructured into functions to make it easier to tell what's going on?
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.
Fixed.
Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:
Can you please update the pull request to address these? (More information can be found in our pull request guide.) |
Thanks for the comments, @ilyavolodin and @not-an-aardvark! It's been a busy week, and I haven't had a chance to address all of the issues you identified, but I've pushed my first round of fixes and responded to some of the comments. Just wanted to confirm that I haven't forgotten about this, and further fixes are coming. |
Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:
Can you please update the pull request to address these? (More information can be found in our pull request guide.) |
@smably I see you've pushed some changes since this was last reviewed. Do you think this is ready to be reviewed again? (There's no rush -- I just want to make sure we're not accidentally deadlocked if you were waiting for a review and I was waiting for you to finish.) |
Hey @not-an-aardvark, thanks for the nudge. I fixed most of the issues but tests seems to be failing on Windows (I'm guess something path-related) and I've been procrastinating figuring out the issue because I don't have a Windows machine available. I'll see if I can find some time in the next week to do some debugging and update the thread with the status of this work. |
It looks like the issue is that you're using |
Waiting another day to merge this in case anyone else on @eslint/eslint-team wants to review it. |
🎉 Thank you for the guidance and very helpful review comments! This is my first open source contribution (of code, at least) and at first I was a little worried that I'd bitten off more than I could chew. But I think it came together quite nicely. |
Awesome job @smably This is a very high profile feature that users have been asking for a while, so great job at taking on it! |
This is great. @smably Thanks for investing your time into that ❤️ |
I noticed I couldn't use Eg. {
overrides: [{
files: ['test/**'],
extends: ['my-config/mocha']
}],
} It that an intentional limitation? |
Ping @smably @not-an-aardvark, see this comment. If we're intentionally not supporting |
@platinumazure Yup, intentionally unsupported (and called out in the docs). It wasn't in the PR I inherited, and I didn't want to add any more scope to what was already a big change. I agree that adding support for this would make a worthy follow-up ticket, and I would be happy to work on the implementation if nobody else has already started. |
@smably Awesome, thanks for clarifying. I'll create a new issue. |
I am beyond impressed y'all saw this through to fruition, and honestly a little shocked. Awesome. |
Does anyone have final performance numbers on a codebase of significant size? |
I just used this feature on a large project at work - really great stuff ❤️ |
@CrabDude Thanks for getting this going and figuring out the logic! You definitely deserve a lot of the credit for this feature... no way I would have been able to get all that caching logic working on my own. ❤️ |
1817: Update eslint to the latest version 🚀 r=jniles ## Version **4.1.0** of [eslint](https://github.com/eslint/eslint) just got published. <table> <tr> <th align=left> Dependency </td> <td> eslint </td> </tr> <tr> <th align=left> Current Version </td> <td> 3.19.0 </td> </tr> <tr> <th align=left> Type </td> <td> devDependency </td> </tr> </table> The version **4.1.0** is **not covered** by your **current version range**. Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though. I recommend you look into these changes and try to get onto the latest version of eslint. Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update. --- <details> <summary>Release Notes</summary> <strong>v4.1.0</strong> <ul> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e8f1362ab640c883a5d296e951308fab22073e7f" class="commit-link"><tt>e8f1362</tt></a> Docs: Remove wrong descriptions in <code>padded-block</code> rule (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8783" class="issue-link js-issue-link" data-url="eslint/eslint#8783" data-id="237771100" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8783</a>) (Plusb Preco)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/291a78302c1d5d402c6582b3f4cc836e61fde787" class="commit-link"><tt>291a783</tt></a> Update: <code>enforceForArrowConditionals</code> to <code>no-extra-parens</code> (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/6196" class="issue-link js-issue-link" data-url="eslint/eslint#6196" data-id="155067290" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#6196</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8439" class="issue-link js-issue-link" data-url="eslint/eslint#8439" data-id="220697521" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8439</a>) (Evilebot Tnawi)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a21dd32c46f95bc232a67929c224824692f94b70" class="commit-link"><tt>a21dd32</tt></a> New: Add <code>overrides</code>/<code>files</code> options for glob-based config (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/3611" class="issue-link js-issue-link" data-url="eslint/eslint#3611" data-id="104053558" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#3611</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8081" class="issue-link js-issue-link" data-url="eslint/eslint#8081" data-id="207675247" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8081</a>) (Sylvan Mably)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/879688ce96f80aa0692f732759c6f67a0c36c4c3" class="commit-link"><tt>879688c</tt></a> Update: Add ignoreComments option to no-trailing-spaces (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8061" class="issue-link js-issue-link" data-url="eslint/eslint#8061" data-id="206865549" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8061</a>) (Jake Roussel)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b58ae2e6d6bd4662b549ca5c0472943055a74df8" class="commit-link"><tt>b58ae2e</tt></a> Chore: Only instantiate fileEntryCache when cache flage set (perf) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8763" class="issue-link js-issue-link" data-url="eslint/eslint#8763" data-id="236756225" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8763</a>) (Gyandeep Singh)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/98512881f1fc2417011247931fa089d987ee8cc6" class="commit-link"><tt>9851288</tt></a> Update: fix indent errors on multiline destructure (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8729" class="issue-link js-issue-link" data-url="eslint/eslint#8729" data-id="235733166" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8729</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8756" class="issue-link js-issue-link" data-url="eslint/eslint#8756" data-id="236673913" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8756</a>) (Victor Hom)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3608f06c2a412587c2d05dec0297803b25f3e630" class="commit-link"><tt>3608f06</tt></a> Docs: Increase visibility of code of conduct (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8758" class="issue-link js-issue-link" data-url="eslint/eslint#8758" data-id="236687424" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8758</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8764" class="issue-link js-issue-link" data-url="eslint/eslint#8764" data-id="236758243" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8764</a>) (Kai Cataldo)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/673a58bc8420075ba698cee6762e17322a5263c3" class="commit-link"><tt>673a58b</tt></a> Update: support multiple fixes in a report (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/7348" class="issue-link js-issue-link" data-url="eslint/eslint#7348" data-id="182620143" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#7348</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8101" class="issue-link js-issue-link" data-url="eslint/eslint#8101" data-id="208681921" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8101</a>) (Toru Nagashima)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7a1bc3893ab55d0ab16ccf4b7a62c85329ab4007" class="commit-link"><tt>7a1bc38</tt></a> Fix: don't pass default parserOptions to custom parsers (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8744" class="issue-link js-issue-link" data-url="eslint/eslint#8744" data-id="236336414" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8744</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8745" class="issue-link js-issue-link" data-url="eslint/eslint#8745" data-id="236373829" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8745</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/c5b405280409698d14b62cbf3c87b7cf6cf71391" class="commit-link"><tt>c5b4052</tt></a> Chore: enable computed-property-spacing on ESLint codebase (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8760" class="issue-link js-issue-link" data-url="eslint/eslint#8760" data-id="236699991" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8760</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3419f6446e205d79d9db77f6c176b9167d1fd8a7" class="commit-link"><tt>3419f64</tt></a> Docs: describe how to use formatters on the formatter demo page (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8754" class="issue-link js-issue-link" data-url="eslint/eslint#8754" data-id="236645523" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8754</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a3ff8f21106cf8eca55978d4b3e053973f5e1bf2" class="commit-link"><tt>a3ff8f2</tt></a> Chore: combine tests in tests/lib/eslint.js and tests/lib/linter.js (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8746" class="issue-link js-issue-link" data-url="eslint/eslint#8746" data-id="236375849" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8746</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b7cc1e6fe995d52e581fcb2b1a44e37a18680e90" class="commit-link"><tt>b7cc1e6</tt></a> Fix: Space-infix-ops should ignore type annotations in TypeScript (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8341" class="issue-link js-issue-link" data-url="eslint/eslint#8341" data-id="217102387" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8341</a>) (Reyad Attiyat)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/46e73eea69abc2ba80bb1397c6779b8789dbd385" class="commit-link"><tt>46e73ee</tt></a> Fix: eslint --init installs wrong dependencies of popular styles (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/7338" class="issue-link js-issue-link" data-url="eslint/eslint#7338" data-id="182134634" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#7338</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8713" class="issue-link js-issue-link" data-url="eslint/eslint#8713" data-id="235217725" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8713</a>) (Toru Nagashima)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a82361b65699653761436a2e9acc7f485c827ca0" class="commit-link"><tt>a82361b</tt></a> Chore: Prevent package-lock.json files from being created (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8742" class="issue-link js-issue-link" data-url="eslint/eslint#8742" data-id="236292937" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8742</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8747" class="issue-link js-issue-link" data-url="eslint/eslint#8747" data-id="236397701" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8747</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/5f81a68a3904a559764872e3f0c7453865a6c6dc" class="commit-link"><tt>5f81a68</tt></a> New: Add eslintIgnore support to package.json (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8458" class="issue-link js-issue-link" data-url="eslint/eslint#8458" data-id="221689525" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8458</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8690" class="issue-link js-issue-link" data-url="eslint/eslint#8690" data-id="233757916" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8690</a>) (Victor Hom)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b5a70b4e8c20dc1ea3e31137706fc20da339f379" class="commit-link"><tt>b5a70b4</tt></a> Update: fix multiline binary operator/parentheses indentation (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8719" class="issue-link js-issue-link" data-url="eslint/eslint#8719" data-id="235421314" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8719</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/ab8b0167bdaf3b8851eab3fbc2769f2bdd71677b" class="commit-link"><tt>ab8b016</tt></a> Update: fix MemberExpression indentation with "off" option (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8721" class="issue-link js-issue-link" data-url="eslint/eslint#8721" data-id="235434741" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8721</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8724" class="issue-link js-issue-link" data-url="eslint/eslint#8724" data-id="235459105" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8724</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/eb5d12c15a32084907f1c58bcbec721b5008495d" class="commit-link"><tt>eb5d12c</tt></a> Update: Add Fixer method to Linter API (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8631" class="issue-link js-issue-link" data-url="eslint/eslint#8631" data-id="230242473" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8631</a>) (Gyandeep Singh)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/26a2daab311c8c59942c52f436d380a195db2bd4" class="commit-link"><tt>26a2daa</tt></a> Chore: Cache fs reads in ignored-paths (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8363" class="issue-link js-issue-link" data-url="eslint/eslint#8363" data-id="218136776" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8363</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8706" class="issue-link js-issue-link" data-url="eslint/eslint#8706" data-id="235004396" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8706</a>) (Victor Hom)</li> </ul> </details> <details> <summary>Commits</summary> <p>The new version differs by 141 commits.</p> <ul> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7d9e3beeb58c1ee71d53dfcfd3e3b0721dd79b46"><code>7d9e3be</code></a> <code>4.1.0</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e727b7bdfcfb0564aabd713b32364e6f4afcfeec"><code>e727b7b</code></a> <code>Build: changelog update for 4.1.0</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e8f1362ab640c883a5d296e951308fab22073e7f"><code>e8f1362</code></a> <code>Docs: Remove wrong descriptions in <code>padded-block</code> rule (#8783)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/291a78302c1d5d402c6582b3f4cc836e61fde787"><code>291a783</code></a> <code>Update: <code>enforceForArrowConditionals</code> to <code>no-extra-parens</code> (fixes #6196) (#8439)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a21dd32c46f95bc232a67929c224824692f94b70"><code>a21dd32</code></a> <code>New: Add <code>overrides</code>/<code>files</code> options for glob-based config (fixes #3611) (#8081)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/879688ce96f80aa0692f732759c6f67a0c36c4c3"><code>879688c</code></a> <code>Update: Add ignoreComments option to no-trailing-spaces (#8061)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b58ae2e6d6bd4662b549ca5c0472943055a74df8"><code>b58ae2e</code></a> <code>Chore: Only instantiate fileEntryCache when cache flage set (perf) (#8763)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/98512881f1fc2417011247931fa089d987ee8cc6"><code>9851288</code></a> <code>Update: fix indent errors on multiline destructure (fixes #8729) (#8756)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3608f06c2a412587c2d05dec0297803b25f3e630"><code>3608f06</code></a> <code>Docs: Increase visibility of code of conduct (fixes #8758) (#8764)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/673a58bc8420075ba698cee6762e17322a5263c3"><code>673a58b</code></a> <code>Update: support multiple fixes in a report (fixes #7348) (#8101)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7a1bc3893ab55d0ab16ccf4b7a62c85329ab4007"><code>7a1bc38</code></a> <code>Fix: don't pass default parserOptions to custom parsers (fixes #8744) (#8745)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/c5b405280409698d14b62cbf3c87b7cf6cf71391"><code>c5b4052</code></a> <code>Chore: enable computed-property-spacing on ESLint codebase (#8760)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3419f6446e205d79d9db77f6c176b9167d1fd8a7"><code>3419f64</code></a> <code>Docs: describe how to use formatters on the formatter demo page (#8754)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a3ff8f21106cf8eca55978d4b3e053973f5e1bf2"><code>a3ff8f2</code></a> <code>Chore: combine tests in tests/lib/eslint.js and tests/lib/linter.js (#8746)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b7cc1e6fe995d52e581fcb2b1a44e37a18680e90"><code>b7cc1e6</code></a> <code>Fix: Space-infix-ops should ignore type annotations in TypeScript (#8341)</code></li> </ul> <p>There are 141 commits in total.</p> <p>See the <a href="https://urls.greenkeeper.io/eslint/eslint/compare/421aab44a9c167c82210bed52f68cf990b7edbea...7d9e3beeb58c1ee71d53dfcfd3e3b0721dd79b46">full diff</a></p> </details> <details> <summary>Not sure how things should work exactly?</summary> There is a collection of [frequently asked questions](https://greenkeeper.io/faq.html) and of course you may always [ask my humans](https://github.com/greenkeeperio/greenkeeper/issues/new). </details> --- Your [Greenkeeper](https://greenkeeper.io) Bot 🌴
What is the purpose of this pull request? (put an "X" next to item)
The ability to override config values based on glob pattern matching relative to the config path. #3611
What changes did you make? (Give an overview)
Starting from @CrabDude's work in #7177, I rebased the branch against the latest master, addressed several comments from the original PR, rewrote and expanded many of the JSDoc comments, tweaked documentation, and split as much logic as I could from
lib/config.js
intolib/config/config-cache.js
,lib/config/config-file.js
, andlib/config/config-ops.js
.Is there anything you'd like reviewers to focus on?
Validating the approach -- does the separation of logic make sense? Is this still on the right track? Any edge cases that need tests?