Skip to content
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

Merged
merged 15 commits into from Jun 22, 2017

Conversation

smably
Copy link
Contributor

@smably smably commented Feb 15, 2017

What is the purpose of this pull request? (put an "X" next to item)

  • Documentation update
  • Other, please explain:

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 into lib/config/config-cache.js, lib/config/config-file.js, and lib/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?

@jsf-clabot
Copy link

jsf-clabot commented Feb 15, 2017

CLA assistant check
All committers have signed the CLA.

@eslintbot
Copy link

LGTM

@mention-bot
Copy link

@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.

@not-an-aardvark
Copy link
Member

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)?

@not-an-aardvark not-an-aardvark added accepted There is consensus among the team that this change meets the criteria for inclusion core Relates to ESLint's core APIs and features feature This change adds a new feature to ESLint labels Feb 25, 2017
@smably
Copy link
Contributor Author

smably commented Feb 26, 2017

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.

@eslintbot
Copy link

LGTM

@smably
Copy link
Contributor Author

smably commented Feb 26, 2017

Added comments to the original PR and fixed the merge conflict.

@eslintbot
Copy link

Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:

  • The commit summary needs to begin with a tag (such as Fix: or Update:). Please check out our guide for how to properly format your commit summary and update it on this pull request.

Can you please update the pull request to address these?

(More information can be found in our pull request guide.)

@smably
Copy link
Contributor Author

smably commented Feb 26, 2017

@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.

@not-an-aardvark
Copy link
Member

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.

@eslintbot
Copy link

Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:

  • The commit summary needs to begin with a tag (such as Fix: or Update:). Please check out our guide for how to properly format your commit summary and update it on this pull request.

Can you please update the pull request to address these?

(More information can be found in our pull request guide.)

Copy link
Member

@ilyavolodin ilyavolodin left a 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);
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

} else if (config.files) {
delete config.files;
}
configCache.setMergedVectorConfig(vector, config);
Copy link
Member

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.

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--) {
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

*/
pathMatchesGlobs(filePath, patterns) {
patterns = [].concat(patterns);
return patterns.every(pattern => minimatch(filePath, pattern, { matchBase: true }));
Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor Author

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 @@
/**
Copy link
Member

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?

subvector.pop();
}

if (config) {
Copy link
Member

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).

Copy link
Member

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.

@ilyavolodin
Copy link
Member

Performance numbers look pretty good (although we are not testing for anything with overrides):

Before:

Single File:
  CPU Speed is 3500 with multiplier 13000000
  Performance Run #1:  5168.491679ms
  Performance Run #2:  3631.0344720000003ms
  Performance Run #3:  3644.98604ms
  Performance Run #4:  3630.521594ms
  Performance Run #5:  3626.206455ms

  Performance budget ok:  3631.0344720000003ms (limit: 3714.285714285714ms)


Multi Files (0 files):
  CPU Speed is 3500 with multiplier 39000000
  Performance Run #1:  13425.494453ms
  Performance Run #2:  13795.64753ms
  Performance Run #3:  13960.317346ms
  Performance Run #4:  13530.801789ms
  Performance Run #5:  13425.006736ms

  Performance budget exceeded: 13530.801789ms (limit: 11142.857142857143ms)

After:

Single File:
  CPU Speed is 3500 with multiplier 13000000
  Performance Run #1:  3705.140804ms
  Performance Run #2:  3714.937271ms
  Performance Run #3:  3817.76126ms
  Performance Run #4:  3948.772472ms
  Performance Run #5:  3707.20636ms

  Performance budget exceeded: 3714.937271ms (limit: 3714.285714285714ms)


Multi Files (0 files):
  CPU Speed is 3500 with multiplier 39000000
  Performance Run #1:  13963.964251ms
  Performance Run #2:  13807.104047ms
  Performance Run #3:  14118.498804ms
  Performance Run #4:  14127.543946ms
  Performance Run #5:  13701.669443ms

  Performance budget exceeded: 13963.964251ms (limit: 11142.857142857143ms)

Copy link
Member

@not-an-aardvark not-an-aardvark left a 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
Copy link
Member

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: { /* ... */ }
    }
  ]
}

*/
function loadCached(filePath) {
const cachedConfig = configCache.getConfig(filePath);
let config = {};
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

subvector.pop();
}

if (config) {
Copy link
Member

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.

Copy link
Contributor Author

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",
Copy link
Member

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?

Copy link
Contributor Author

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);
Copy link
Member

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.

Copy link
Contributor Author

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;
}
Copy link
Member

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?

Copy link
Contributor Author

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) {
Copy link
Member

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.
Copy link
Member

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"?

Copy link
Contributor Author

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.

getConfigFromVector(vector) {

const subvector = Array.from(vector);
let config,
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@eslintbot
Copy link

Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:

  • The commit summary needs to begin with a tag (such as Fix: or Update:). Please check out our guide for how to properly format your commit summary and update it on this pull request.

Can you please update the pull request to address these?

(More information can be found in our pull request guide.)

@smably
Copy link
Contributor Author

smably commented Mar 6, 2017

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.

@eslintbot
Copy link

Thanks for the pull request, @smably! I took a look to make sure it's ready for merging and found some changes are needed:

  • The commit summary needs to begin with a tag (such as Fix: or Update:). Please check out our guide for how to properly format your commit summary and update it on this pull request.

Can you please update the pull request to address these?

(More information can be found in our pull request guide.)

@not-an-aardvark
Copy link
Member

@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.)

@smably
Copy link
Contributor Author

smably commented Apr 6, 2017

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.

@not-an-aardvark
Copy link
Member

It looks like the issue is that you're using Array.prototype.includes, which only exists on Node 6+, but the build runs on Node 4+. Switching to indexOf should hopefully fix the problem.

@not-an-aardvark
Copy link
Member

Waiting another day to merge this in case anyone else on @eslint/eslint-team wants to review it.

@smably
Copy link
Contributor Author

smably commented Jun 21, 2017

🎉 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.

@ilyavolodin
Copy link
Member

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!

@not-an-aardvark not-an-aardvark merged commit a21dd32 into eslint:master Jun 22, 2017
@mischah
Copy link

mischah commented Jun 22, 2017

This is great. @smably Thanks for investing your time into that ❤️

@moeriki
Copy link
Contributor

moeriki commented Jun 26, 2017

I noticed I couldn't use extends: [] in overrides: [].

Eg.

{
  overrides: [{
    files: ['test/**'],
    extends: ['my-config/mocha']
  }],
}

It that an intentional limitation?

@platinumazure
Copy link
Member

Ping @smably @not-an-aardvark, see this comment.

If we're intentionally not supporting extends in override configs, I think we might want to see if we can enhance that (as a separate issue). My suggested approach would be to prepend the override's extends array to the parent config's extends array and removing duplicate entries that occur later in the resulting array, but there might be a better way to do that.

@smably
Copy link
Contributor Author

smably commented Jun 26, 2017

@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.

@platinumazure
Copy link
Member

@smably Awesome, thanks for clarifying.

I'll create a new issue.

@CrabDude
Copy link

I am beyond impressed y'all saw this through to fruition, and honestly a little shocked. Awesome.

❤️ ❤️ @smably @not-an-aardvark @ilyavolodin

@CrabDude
Copy link

Does anyone have final performance numbers on a codebase of significant size?

@kaicataldo
Copy link
Member

I just used this feature on a large project at work - really great stuff ❤️

@smably
Copy link
Contributor Author

smably commented Jun 30, 2017

@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. ❤️

bors bot added a commit to IMA-WorldHealth/bhima that referenced this pull request Jul 9, 2017
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 🌴
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Feb 6, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Feb 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion core Relates to ESLint's core APIs and features feature This change adds a new feature to ESLint
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet