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
Rules redefining: shallow or deep? #6361
Comments
This is a similar discussion to #6144. Currently, rule configurations are merged, not replaced. I don't think there is a way to unset options from object properties. @eslint/eslint-team should we change this? |
I would be 👍 to changing this. Three reasons:
|
I don't think we can change this. This would affect too many users. Even marking it as breaking might not be enough at this point. |
@ilyavolodin Maybe it would be possible to add top parsing option for shallow redefining and turn it off by default to not break the old behavior unexpectedly? |
I've tried to detect some rules with array options by this script: const rules = JSON.parse(require('child_process').execSync(
`eslint --print-config ${__filename}`, { encoding: 'utf8' }
)).rules;
console.log(
Object.keys(rules)
.filter(k => Array.isArray(rules[k]) &&
rules[k].some(param => typeof param === 'string')
)
.map(k => `${k}: ${JSON.stringify(rules[k])}`)
); First I've run it with just this .eslintrc.json: {
"extends": [
"eslint:recommended",
"airbnb-base"
]
} The output:
@alberto , you could analyze these rules if any of them are candidates for PR like your #6342. However I've found some strange redefining behavior after I had run the script with my default rules set: {
"root": true,
"extends": [
"eslint:recommended",
"airbnb-base"
],
"parserOptions": {
"ecmaVersion": 7,
"sourceType": "script"
},
"env": {
"browser": false,
"es6": true,
"node": true
},
"rules": {
"arrow-parens": [2, "as-needed"],
"eqeqeq": 2,
"key-spacing": [2, { "beforeColon": false, "afterColon": true, "mode": "minimum" }],
"no-console": 0,
"no-eq-null": 2,
"no-extra-parens": [2, "all"],
"no-multi-spaces": 0,
"no-unused-vars": [2, { "vars": "all", "args": "all" }],
"no-use-before-define": [2, { "functions": false }],
"quotes": [2, "single"],
"spaced-comment": [2, "always", { "exceptions": ["/", "*"] }],
"strict": [2, "global"],
"unicode-bom": [2, "always"]
}
} These lines from script output puzzle me:
So:
It seems that the redefining is half-shallow and half-deep. I don't know if this is worth a new issue post. |
|
I don't think it's worth making any code change here. We have millions of installs using the current system and once you understand how it works, and we can't risk breaking all those configs. We can probably better explain how merging works in the docs, though, to have some place to point people to. |
@nzakas So is this an intentional merging scheme?
while
|
So we'll point users to documentation that tells them there's no way to do something that is very reasonable to want to do? 😟 I don't think that makes it much better. We should fix this. It's a broken design. |
@michaelficarra can you be more descriptive? What exactly do you think should change? And what would you suggest to avoid breaking the configurations of existing users? |
I assume @michaelficarra will mostly agree with this (speak up if I've missed anything). Definitions (I assume this is unnecessary but just to avoid ambiguity):
Proposals:
@nzakas Hope this helps |
@platinumazure May be this case is also worth mention (current behavior):
How |
I think I'm with @platinumazure and @michaelficarra it's a broken design in a sense that it doesn't allow you to remove some of the properties that were set in the higher level config. I am, however, of the opinion that we couldn't change the default behavior right now. We can add it as a flag, that would be perfectly fine, but changing default behavior might be a bit too much, unfortunately. |
@platinumazure thanks, that does help. It also solidifies my belief that what we are doing right now makes the most sense. This merging mechanism was designed for what we thought would be the common use case: changing a rule's severity without changing the options. So what we have right now:
We definitely want people to be able to change severity without needing to re-state every other option that was already defined elsewhere. This is by design. @vsemozhetbyt this behavior is intentional:
When you're changing just the severity, we can safely assume that you want all other options for the rule to remain as they were. When you change something other than the severity, we can't assume that you want every other option as it was previous defined except for the ones you specified. Doing that would mean you'd need to search through all other configs that have altered the options of the rule in some way to be 100% sure of the options you're now applying, and that's pretty confusing. While I can understand how the current system is a bit confusing when you run into edge cases, I do think it's the probably the best way to handle things given our large user base and the design goals of the system. |
@nzakas I don't think any of us thought rules overriding worked that way. I think it makes sense, and just needs to be documented |
@alberto I agree (#6361 (comment)) |
Well, it is really not so obvious principle, but I could obey the tradition) By the way, then the team should check all the rules like old |
@vsemozhetbyt Agreed. The current behavior is more than just confusing in certain cases, so documentation will not help. It can prevent you from overwriting options inherited from parent configs, as detailed in #6144. This prevented me from extending the airbnb config entirely. @alberto Thanks for adding the |
(it's gone a bit quiet...) Is anyone working on documenting this, or introducing a new feature that doesn't break the world ? |
We agreed to update documentation, but that hasn't been done yet. Do you want to submit a PR? |
Got a PR up here! |
* Update docs to explain config option merging There was a lot of [confusion](#6361) generated by the merging behavior of rules inherited from base configs, so I thought I would clear that up here. There still may be [scenarios](#6144) which arise where options cannot be overridden from base configs, but we'll deal with those on a per-case basis. * Use 4 spaces, not 2 * Use string notation, instead of numeric * Fix level
This was closed by #7499 |
@vsemozhetbyt thanks for sharing that script, made it really easy to figure out the proper value to override with 👍 |
@GGAlanSmithee There is another slightly different one. I use it to check the final unfiltered sum of the merged sets: 'use strict';
const rules = JSON.parse(require('child_process').execSync(
`eslint --print-config ${__filename}`, { encoding: 'utf8' }
)).rules;
console.log(
Object.keys(rules)
.map(k => `${k}: ${JSON.stringify(rules[k])}`)
.sort()
.join('\n')
); |
Continuing from @vsemozhetbyt's example above, how does one achieve this? Is it even possible?
|
@danny-andrews Too bad. But thanks for the answer!!!! :) |
What version of ESLint are you using?
2.11.1
What parser (default, Babel-ESLint, etc.) are you using?
default
Please show your full configuration:
What did you do?...
After reading the documentation about cascading, hierarchy and rules redefining, I wrongly supposed that
rules
in the user.eslintrc
file redefine rules in theextends
files as a whole, i.e. if theairbnb-base
sets'no-unused-vars': [2, { 'vars': 'local', 'args': 'after-used' }]
and I sets"no-unused-vars": 2
the results will be just"no-unused-vars": 2
.However, the
eslint --print-config
tests have taught me that I should redefine each option fromextends
file manually (i.e. the results above will be still"no-unused-vars": [2, { "vars": "local", "args": "after-used" }]
if I does not redefinevars
andargs
).Maybe I've missed something in the docs. If I have not, maybe it is worth more clarirfication.
However, I don't understend how can I cancel array options from
extends
files rules. So, ifairbnb-base
sets'eqeqeq': [2, 'allow-null']
, how can I cancel'allow-null'
?With .eslintrc.json example above and this file:
eslint says just:
and
eslint --print-config
inticates that result rule is stillThe text was updated successfully, but these errors were encountered: