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

Support overridable configs #58

Closed
wants to merge 11 commits into from

Conversation

jamestalmage
Copy link
Contributor

Fixes #22.

This allows for overridable configs based on glob patterns.

Usage is as follows:

{
  "xo": {
    "esnext": false,
    "overrides": [
      {
        "files": "test/*.js",
        "esnext": true
      },
      {
         "files": "test/foo.js",
         "space": 3
      }
    ]
  }
}

The base config is:

{
  "esnext": false
}

For everything in the test directory the config is:

{
  "esnext": true
}

With the exception of test/foo.js which has the following config:

{
  "esnext": true,
  "space": 3
}

It is important to note that overrides are cumulative, and processed in the order specified in the array.
If two overrides match the same file, the latter will takes precedence over the former.

@jamestalmage
Copy link
Contributor Author

We had discussed using object hashes for overrides:

"overrides": {
  "**/foo.js": { "esnext": false } 
}

I decided against doing it that way, because it gives you no control over merge order if two patterns match the same file.

@jamestalmage
Copy link
Contributor Author

There is still debate over exactly what to name some of these options. Once that is settled, I will update this PR (including docs).

@SamVerschueren
Copy link
Contributor

The overrides functionality is really nice! Is it possible to provide a concrete example on the benefit of the array versus the object hashes? It seems like it just makes everything more complex because the order in the array is important. It's because of merge conflicts when more globbing patterns matches the same file, right? But why not apply the most specific rules for that file?

"overrides": {
  "test/test.js": {"esnext": true},
  "test/*.js": { "esnext": false } 
}

Because test/test.js is more specific, the esnext rule should be true for the file test/test.js. Independent of the order of the keys.

Just wanted some more information regarding this :).

@jamestalmage
Copy link
Contributor Author

It's because of merge conflicts when more globbing patterns matches the same file, right?

Yes. The array syntax is necessary to support multiple glob patterns anyways:

"overrides": [
  {
    "files": ["test/*.js", "!test/foo.js"]
  }
]

So I think the array syntax needs to be a part of the final solution no matter what. It might be possible to allow both array and object.

To be honest, the array solution was just easier to implement.

But why not apply the most specific rules for that file?

I am not sure how to reliably determine "the most specific match". Which of the following more specifically matches test/foo.js?

  • **/foo.js
  • test/*oo.js

Also, how do we then merge settings? Least specific to most specific? In that case the following is confusing:

"overrides": {
  "test/test.js": {"esnext": true},
  "test/*.js": { "esnext": false, spaces:3} 
}

If we merge every match, in order of specificity., the settings for test/test.js are obtained by merging the least specific ({esnext: false, spaces: 3}), followed by the most specific ({esnext:true}). But that's opposite the order I have them listed above. That is confusing.

I think if we allow the object pattern we should only apply a single "most specific" match (I am still not sure how best to determine that).

@SamVerschueren
Copy link
Contributor

The array syntax is necessary to support multiple glob patterns anyways

Good point

I am not sure how to reliably determine "the most specific match"

Not sure either

But that's opposite the order I have them listed above. That is confusing.

I don't think that's confusing. But maybe that's just me.

In general, whatever gets implemented, as long as it's clearly documented, we're good :). Just wanted to share my opinion. Hopefully others will pick in into this discussion.

@jamestalmage
Copy link
Contributor Author

Yeah, I fully intend to document before it gets merged. Still looking for feedback at this point.

// always use the Babel parser so it won't throw
// on esnext features in normal mode
config.parser = 'babel-eslint';
config.plugins = ['babel'];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I noticed that if opts.esnext is not true, we overwrite any plugins they might have specified. Should we just be appending/prepending babel to the list?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, noes. That's why 90c95ed#commitcomment-14948953 Good eye! :)

It should be prepended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sindresorhus You want me to fix it here or a separate PR from master?

Copy link
Member

Choose a reason for hiding this comment

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

@jamestalmage Master. I need to do a patch release. :)

jamestalmage added a commit to jamestalmage/xo that referenced this pull request Dec 15, 2015
If the `esnext` option is `false`, we currently blow away existing
plugins, replacing it with only the `babel` plugin. This prepends it.

This does not come with a test, as option handling is currently pretty difficult.
We can add the appropriate test for this there.

Reference:
  xojs#58 (comment)
@jamestalmage
Copy link
Contributor Author

@sindresorhus @kevva @vdemedes - Do you guys have any additional feedback? If I get this rebased is it good to merge?

@vadimdemedes
Copy link

Good work, looking forward to using this!

var resolveFrom = require('resolve-from');
var objectAssign = require('object-assign');
var homeOrTmp = require('home-or-tmp');
var mutlimatch = require('multimatch');
Copy link
Member

Choose a reason for hiding this comment

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

mutlimatch => multimatch

@sindresorhus
Copy link
Member

Sorry about the delay. I've just had too many PRs to review. Took a thorough look now and it generally looks fantastic! Also thanks for refactoring the code into a more readable and maintainable state 👌.

I added a few minor inline comments, but it's pretty close to be mergeable. Currently, all the individual pieces are tested, but could use a real world integration test in test.js with a fixture and a real package.json, just to ensure all the "glue" works correctly. Also needs docs, but I would be happy to write that if you don't want / have time.

It's 🎄so no rush on this :)

@jamestalmage
Copy link
Contributor Author

@sindresorhus - this should be all set.

I added an undocumented --no-local flag to disable the local check. Otherwise we were getting our old version for all the tests in test/cli.js

@jamestalmage
Copy link
Contributor Author

@sindresorhus - Are we good to merge here? I would like to avoid rebasing again.

Once merged I suggest we let it live on master and test it against a few projects before release. It was a significant refactor followed by a problematic rebase. I'm fairly confident I got it right, but better to practice caution.

@sindresorhus sindresorhus changed the title Support overridable configs. Fixes #22 Support overridable configs Dec 29, 2015
@sindresorhus
Copy link
Member

Yes, landed :D I'm super happy about how this turned out.

unicorn

@sindresorhus
Copy link
Member

Gonna let it live on master for a few days while I test it on some of my projects.

@dvdln
Copy link

dvdln commented Jan 26, 2016

...any chance this will be released anytime soon?

@sindresorhus
Copy link
Member

@dvdln When this issue is resolved: #71

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants