-
Notifications
You must be signed in to change notification settings - Fork 46.9k
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
use different eslint config for es6 and es5 #11794
Conversation
scripts/eslint/baseConfig.js
Outdated
|
||
module.exports = { | ||
config: eslintrc, | ||
OFF, |
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 think this is a bit confusing. Let's just copy and paste these constants, and completely remove this file :-) ESLint also actually accepts strings so we can later remove them altogether.
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.
ok
scripts/eslint/es5Config.js
Outdated
@@ -0,0 +1,3 @@ | |||
const baseConfig = require('./baseConfig'); | |||
|
|||
module.exports = baseConfig.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.
I think there's more to it. I think we want to have ecmaVersion
set to 6
for the ES6 config and to 5
for the ES5 config. It's not just about var, but about all the other features too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I add it on new commit.
const file = jsFiles[index]; | ||
for (let pathIndex in es5Path) { | ||
const pattern = es5Path[pathIndex]; | ||
const isES5 = minimatch(file, pattern); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this efficient? What's the full yarn lint
time before and after the change?
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 also want to refactor it. But currently I don't think of other refactor way.
But it doesn't affect too much efficiency, because this script will only be used on yarn linc
to distinguish es5
and es6
files: here.
For yarn lint
, because the es5
, and es6
pattern is known, we don't need to judge files' ecma version.
Here is the yarn lint
run time after the change:
Before: 22.50s
After: 17.86s.
The reason for runtime decrease is because, before the change, the filePattern
was [.]
(ref), after the change we use specific es path.
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.
Maybe there’s something clever we can do to have ESLint do the filtering instead of us? I’m not sure but since Prettier can do this, maybe you can find a way with ESLint API too.
scripts/prettier/index.js
Outdated
'packages/*/src/**/*.js', | ||
'packages/shared/**/*.js', | ||
], | ||
patterns: es6Path, | ||
ignore: ['**/node_modules/**'], |
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.
Should ignore patterns also be a part of the respective configs? That would make sense to me. The fact that they’re currently duplicated in eslintignore is a bit confusing.
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.
OK, I'll move it to respective config.
Does it mean we should put all the eslintignore
setting to the shared config file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that could mess with the editor integrations people on the team might be using. So maybe we shouldn’t do it. What do you think?
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 think we should keep the .eslintrc
to make editor work as usual.
If we want to avoid ignore pattern duplicate, maybe we can write a script to read .eslintrc
to use in prettier
ignore part.
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.
That sounds a bit convoluted.
How about:
- We use top level eslintignore/prettierignore for things that should never be touched (like build products and third party code)
- For ES5/ES6, we always negate the other pattern to get a list of extra ignores. For example ES5 = everything in ES5 patterns except anything that is ES6. And vice versa.
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’s even simpler.
ES6 doesn’t need a pattern. It should just be “everything”. The global ignores (in ESLint and Prettier top lebel ignore files) should filter out build artefacts and dependencies.
ES5 needs a pattern that just says “these files are ES5”. It’s a subset of all files.
You run ES5 passing it as “include” set.
Then you run ES6 by passing ES5 as “exclude” set. Because everything else is ES6 (or already excluded by global config).
In either case ES5 is the only pattern that needs to be explicitly specified.
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.
Cool! It's more clear. I will correct it in this way.
BTW, for the lint change, eslint provide a ignorePattern
params.
So when linting es5 files, we can pass es6 path as ignore pattern, vice versa.
However, it will cause this warning when the file is ignored: (related issue: eslint/eslint#5623)
0:0 warning File ignored because of a matching ignore pattern. Use "--no-ignore" to override
To turn off this warning is to set quiet
as true, but it will quiet "all warning". I think it's inappropriate.
Therefore, I think write the filter to distinguish es5 files and es6 files is needed. I'll try a cleaner method to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just filter this particular warning from the output (and maybe raise an issue to ask for an option to completely disable this warning).
const minimatch = require('minimatch'); | ||
const {es5Path} = require('./esPath'); | ||
|
||
module.exports = function(jsFiles) { |
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.
If this is only used in linc
task let’s just move it and inline it there. I wouldn’t worry too much about having a test for this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
const file = jsFiles[index]; | ||
for (let pathIndex in es5Path) { | ||
const pattern = es5Path[pathIndex]; | ||
const isES5 = minimatch(file, pattern); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there’s something clever we can do to have ESLint do the filtering instead of us? I’m not sure but since Prettier can do this, maybe you can find a way with ESLint API too.
@gaearon, this new commit I use eslint params In the earlier discussion, we talk about use |
scripts/eslint/index.js
Outdated
@@ -8,12 +8,30 @@ | |||
'use strict'; | |||
|
|||
const CLIEngine = require('eslint').CLIEngine; | |||
const cli = new CLIEngine(); | |||
const formatter = cli.getFormatter(); | |||
const eslintPath = './scripts/eslint'; |
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 called __dirname
in Node :-)
scripts/eslint/es6Config.js
Outdated
var ERROR = 2; | ||
|
||
module.exports = Object.assign({}, eslintrc, { | ||
parseOptions: { |
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.
parserOptions
, not parseOptions
.
scripts/eslint/es6Config.js
Outdated
@@ -0,0 +1,16 @@ | |||
const eslintrc = require('../../.eslintrc'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this could possibly work. By the pattern, this file should be treated as ES5. But then const
should not parse. However it lints just fine.
This brings up a separate point: we're actually okay with treating our Node /scripts/
as ES6. It's just that we don't want trailing commas in them. So maybe we need three different file types (ESnext+JSX, ES6, and ES5).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the main different lint setting of ES6 and ESnext is we turn off comma-dangle
rule at es6?
Currently, I can't find other different of ESnext and ES6 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.
JSX, Flow should also be disabled in ES6. And it should use the espree parser.
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.
OK, so there are some files in scripts
should be ignored.
Like:
/scripts/flow/environment.js
/scripts/rollup/shims/react-native/NativeMethodsMixin.js
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.
All shims should be treated as source (ESNext). Good catch.
My impression is that ESLint CLIEngine ignores the explicit |
Seems like these are the options we need to use to force ESLint to treat file as ES5: parser: 'espree',
parserOptions: {
ecmaVersion: 5,
sourceType: 'script'
}, This won't work for our Node scripts, so as I mentioned above, we need to divide files into three different sets:
And then supply different options above depending on the types. |
@gaearon, I've pushed new commits to solve it. As what we discussed, I separate the es path to
|
scripts/bench/server.js
Outdated
@@ -21,7 +21,7 @@ function createHTTP2Server(benchmark) { | |||
__dirname, | |||
'benchmarks', | |||
benchmark, | |||
request.url | |||
request.url, |
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 won't work. Everything inside scripts/bench
(and scripts
in general, except scripts/rollup/shims
) should be normal ES6 without trailing commas in function calls. Otherwise it won't run on Node.
const stories = 50; | ||
|
||
async function getStory(id) { | ||
const storyRes = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`); | ||
const storyRes = await fetch( | ||
`https://hacker-news.firebaseio.com/v0/item/${id}.json`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this could work. It should be ES6 (which doesn't support trailing commas).
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's my fault. On previous commit, I was uncareful to ignore benchmark, so it ran prettier on those files.
I've reverted it on latest commit.
scripts/eslint/es6Config.js
Outdated
sourceType: 'module', | ||
ecmaFeatures: { | ||
jsx: true, | ||
experimentalObjectRestSpread: 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.
Why do we need these features for ES6? I’d expect both to be false.
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.
Cause this files scripts/release/build-commands/parse-build-parameters.js use this syntax.
So we don't allow this syntax?
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.
Why does it work? Did it get enabled by default in some Node version?
In this case let’s leave it on. But JSX shouldn’t be.
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 think that's because our devEngines
is required node v8.x
, so this syntax works.
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 going in the right direction. Let's make a few changes.
- Rename ESLint configs to
eslintrc.source.js
(ESNext),eslintrc.node.js
(ES6) andeslintrc.npm.js
(ES5). - The
eslintrc.node.js
config should not enable JSXor object spread. It also should have'script'
rather than'module'
type. Additionally, it should include a lint rule that requires'use strict'
to be specified in every file. - The
eslintrc.npm.js
config should disallow JSX. fixtures/**/*.js
should be ES6 (aka "node" in new naming), rather than ES5.- After these changes are done, please revert any changes to files that were automatic. Then rebase this PR on top of master. Then reapply the automatic changes. Otherwise this isn't up to date.
efa53c8
to
adb36b7
Compare
@gaearon, I've updated the config naming, revert automatic changed files and rebase to master 😄 |
yarn.lock
Outdated
@@ -3358,7 +3358,7 @@ minimatch@^2.0.3: | |||
|
|||
minimatch@^3.0.4: | |||
version "3.0.4" | |||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" | |||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" |
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.
Unintentional?
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.
yarn
seems to have a bug where it occasionally alternates between registries on some packages; not sure what causes it, but I've seen it once in a while
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 just mean we can safely omit this change from a PR.
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.
ok, I'll revert it.
scripts/prettier/index.js
Outdated
ignore: [ | ||
'**/node_modules/**', | ||
// Built files and React repo clone | ||
'scripts/bench/benchmarks/**', | ||
// shims & flow treat as ESNext | ||
'scripts/flow/*.js', | ||
'scripts/rollup/shims/**/*.js', |
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 feels confusing that we still have to explicitly ignore some paths here but ESLint is fully covered by just “patterns” config.
scripts/eslint/index.js
Outdated
@@ -8,12 +8,54 @@ | |||
'use strict'; | |||
|
|||
const CLIEngine = require('eslint').CLIEngine; | |||
const cli = new CLIEngine(); | |||
const formatter = cli.getFormatter(); | |||
const {npmPath, nodePath, sourcePath} = require('../shared/esPath'); |
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.
Let’s rename that file to filesByLanguageVersion
?
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.
ok
scripts/prettier/index.js
Outdated
'scripts/flow/*.js', | ||
'scripts/rollup/shims/**/*.js', | ||
], | ||
ignore: ['**/node_modules/**'], |
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 think remove the scripts in ignore will cause other issues. Some patterns are covered (like 'scripts/flow/*.js'
) will run on both prettier process.
Because we run prettier twice (default
-> scripts
), the results seem work as our expect, but actually some changes on default prettier is covered by scripts prettier.
Maybe we can expand the scripts pattern to make it more clear?
const nodePath = [
'scripts/babel/*.js',
'scripts/circleci/*.js',
'scripts/error-codes/*.js',
...
];
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 see. Let me look at that.
I think I can take this PR from here, thanks a lot!
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.
You're welcome. Thanks for your patience.
sorry to jump in late and snipe the PR! Eslint now supports overriding and configuration by file glob in the eslintrc. (example here) that may help simplify this a bit and reduce the extra code needed for the different paths eslint docs: https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns |
Oh nice. I think we'll get a version of this in first, but then file another issue to refactor it :-) |
This is great. Thank you! |
This pr uses different eslint config to solve issues #11783.
The following is the updated part:
share es path: I move the es path pattern to a shared file
scripts/shared/esPath.js
, so thatprettier
andeslint
can use same es path patternseparate lint call: https://github.com/ctxhou/react/blob/c6b94daaabe89d7ac0b08a9c608ff734ced271d2/scripts/tasks/eslint.js#L13-L14
judge es version: For
lint changed
, because we need to define which changed files are es5 and others are es6, I create a filescripts/shared/judgeJSFilesVersion.js
to get this info.So now, when we run
yarn lint
oryarn linc
, it will lint es5 and es6 separately.