Skip to content

Commit 2b1fb91

Browse files
authored
ESLint upgrade to use hermes-eslint (#25915)
Hermes parser is the preferred parser for Flow code going forward. We need to upgrade to this parser to support new Flow syntax like function `this` context type annotations or `ObjectType['prop']` syntax. Unfortunately, there's quite a few upgrades here to make it work somehow (dependencies between the changes) - ~Upgrade `eslint` to `8.*`~ reverted this as the React eslint plugin tests depend on the older version and there's a [yarn bug](yarnpkg/yarn#6285) that prevents `devDependencies` and `peerDependencies` to different versions. - Remove `eslint-config-fbjs` preset dependency and inline the rules, imho this makes it a lot clearer what the rules are. - Remove the turned off `jsx-a11y/*` rules and it's dependency instead of inlining those from the `fbjs` config. - Update parser and dependency from `babel-eslint` to `hermes-eslint`. - `ft-flow/no-unused-expressions` rule replaces `no-unused-expressions` which now allows standalone type asserts, e.g. `(foo: number);` - Bunch of globals added to the eslint config - Disabled `no-redeclare`, seems like the eslint upgrade started making this more precise and warn against re-defined globals like `__EXPERIMENTAL__` (in rollup scripts) or `fetch` (when importing fetch from node-fetch). - Minor lint fixes like duplicate keys in objects.
1 parent fabef7a commit 2b1fb91

36 files changed

+604
-260
lines changed

.eslintrc.js

Lines changed: 249 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,26 @@ const {
88
const restrictedGlobals = require('confusing-browser-globals');
99

1010
const OFF = 0;
11+
const WARNING = 1;
1112
const ERROR = 2;
1213

1314
module.exports = {
14-
extends: ['fbjs', 'prettier'],
15+
extends: ['prettier'],
1516

1617
// Stop ESLint from looking for a configuration file in parent folders
1718
root: true,
1819

1920
plugins: [
21+
'babel',
22+
'ft-flow',
2023
'jest',
2124
'no-for-of-loops',
2225
'no-function-declare-after-return',
2326
'react',
2427
'react-internal',
2528
],
2629

27-
parser: 'babel-eslint',
30+
parser: 'hermes-eslint',
2831
parserOptions: {
2932
ecmaVersion: 9,
3033
sourceType: 'script',
@@ -33,6 +36,190 @@ module.exports = {
3336
// We're stricter than the default config, mostly. We'll override a few rules
3437
// and then enable some React specific ones.
3538
rules: {
39+
'ft-flow/array-style-complex-type': [OFF, 'verbose'],
40+
'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING
41+
'ft-flow/boolean-style': ERROR,
42+
'ft-flow/no-dupe-keys': ERROR,
43+
'ft-flow/no-primitive-constructor-types': ERROR,
44+
'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR
45+
'ft-flow/no-unused-expressions': ERROR,
46+
// 'ft-flow/no-weak-types': WARNING,
47+
// 'ft-flow/require-valid-file-annotation': ERROR,
48+
49+
'no-cond-assign': OFF,
50+
'no-constant-condition': OFF,
51+
'no-control-regex': OFF,
52+
'no-debugger': ERROR,
53+
'no-dupe-args': ERROR,
54+
'no-dupe-keys': ERROR,
55+
'no-duplicate-case': WARNING,
56+
'no-empty-character-class': WARNING,
57+
'no-empty': OFF,
58+
'no-ex-assign': WARNING,
59+
'no-extra-boolean-cast': WARNING,
60+
'no-func-assign': ERROR,
61+
'no-invalid-regexp': WARNING,
62+
'no-irregular-whitespace': WARNING,
63+
'no-negated-in-lhs': ERROR,
64+
'no-obj-calls': ERROR,
65+
'no-regex-spaces': WARNING,
66+
'no-sparse-arrays': ERROR,
67+
'no-unreachable': ERROR,
68+
'use-isnan': ERROR,
69+
'valid-jsdoc': OFF,
70+
'block-scoped-var': OFF,
71+
complexity: OFF,
72+
'default-case': OFF,
73+
'guard-for-in': OFF,
74+
'no-alert': OFF,
75+
'no-caller': ERROR,
76+
'no-case-declarations': OFF,
77+
'no-div-regex': OFF,
78+
'no-else-return': OFF,
79+
'no-empty-pattern': WARNING,
80+
'no-eq-null': OFF,
81+
'no-eval': ERROR,
82+
'no-extend-native': WARNING,
83+
'no-extra-bind': WARNING,
84+
'no-fallthrough': WARNING,
85+
'no-implicit-coercion': OFF,
86+
'no-implied-eval': ERROR,
87+
'no-invalid-this': OFF,
88+
'no-iterator': OFF,
89+
'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}],
90+
'no-lone-blocks': WARNING,
91+
'no-loop-func': OFF,
92+
'no-magic-numbers': OFF,
93+
'no-multi-str': ERROR,
94+
'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}],
95+
'no-new-func': ERROR,
96+
'no-new': WARNING,
97+
'no-new-wrappers': WARNING,
98+
'no-octal-escape': WARNING,
99+
'no-octal': WARNING,
100+
'no-param-reassign': OFF,
101+
'no-process-env': OFF,
102+
'no-proto': ERROR,
103+
'no-redeclare': OFF, // TODO should be WARNING?
104+
'no-return-assign': OFF,
105+
'no-script-url': ERROR,
106+
'no-self-compare': WARNING,
107+
'no-sequences': WARNING,
108+
'no-throw-literal': ERROR,
109+
'no-useless-call': WARNING,
110+
'no-void': OFF,
111+
'no-warning-comments': OFF,
112+
'no-with': OFF,
113+
radix: WARNING,
114+
'vars-on-top': OFF,
115+
yoda: OFF,
116+
'init-declarations': OFF,
117+
'no-catch-shadow': ERROR,
118+
'no-delete-var': ERROR,
119+
'no-label-var': WARNING,
120+
'no-shadow-restricted-names': WARNING,
121+
'no-undef-init': OFF,
122+
'no-undef': ERROR,
123+
'no-undefined': OFF,
124+
'callback-return': OFF,
125+
'global-require': OFF,
126+
'handle-callback-err': OFF,
127+
'no-mixed-requires': OFF,
128+
'no-new-require': OFF,
129+
'no-path-concat': OFF,
130+
'no-process-exit': OFF,
131+
'no-restricted-modules': OFF,
132+
'no-sync': OFF,
133+
camelcase: [OFF, {properties: 'always'}],
134+
'consistent-this': [OFF, 'self'],
135+
'func-names': OFF,
136+
'func-style': [OFF, 'declaration'],
137+
'id-length': OFF,
138+
'id-match': OFF,
139+
'max-depth': OFF,
140+
'max-nested-callbacks': OFF,
141+
'max-params': OFF,
142+
'max-statements': OFF,
143+
'new-cap': OFF,
144+
'newline-after-var': OFF,
145+
'no-array-constructor': ERROR,
146+
'no-continue': OFF,
147+
'no-inline-comments': OFF,
148+
'no-lonely-if': OFF,
149+
'no-negated-condition': OFF,
150+
'no-nested-ternary': OFF,
151+
'no-new-object': WARNING,
152+
'no-plusplus': OFF,
153+
'no-ternary': OFF,
154+
'no-underscore-dangle': OFF,
155+
'no-unneeded-ternary': WARNING,
156+
'one-var': [WARNING, {initialized: 'never'}],
157+
'operator-assignment': [WARNING, 'always'],
158+
'require-jsdoc': OFF,
159+
'sort-vars': OFF,
160+
'spaced-comment': [
161+
OFF,
162+
'always',
163+
{exceptions: ['jshint', 'jslint', 'eslint', 'global']},
164+
],
165+
'constructor-super': ERROR,
166+
'no-class-assign': WARNING,
167+
'no-const-assign': ERROR,
168+
'no-dupe-class-members': ERROR,
169+
'no-this-before-super': ERROR,
170+
'object-shorthand': OFF,
171+
'prefer-const': OFF,
172+
'prefer-spread': OFF,
173+
'prefer-reflect': OFF,
174+
'prefer-template': OFF,
175+
'require-yield': OFF,
176+
'babel/generator-star-spacing': OFF,
177+
'babel/new-cap': OFF,
178+
'babel/array-bracket-spacing': OFF,
179+
'babel/object-curly-spacing': OFF,
180+
'babel/object-shorthand': OFF,
181+
'babel/arrow-parens': OFF,
182+
'babel/no-await-in-loop': OFF,
183+
'babel/flow-object-type': OFF,
184+
'react/display-name': OFF,
185+
'react/forbid-prop-types': OFF,
186+
'react/jsx-closing-bracket-location': OFF,
187+
'react/jsx-curly-spacing': OFF,
188+
'react/jsx-equals-spacing': WARNING,
189+
'react/jsx-filename-extension': OFF,
190+
'react/jsx-first-prop-new-line': OFF,
191+
'react/jsx-handler-names': OFF,
192+
'react/jsx-indent': OFF,
193+
'react/jsx-indent-props': OFF,
194+
'react/jsx-key': OFF,
195+
'react/jsx-max-props-per-line': OFF,
196+
'react/jsx-no-bind': OFF,
197+
'react/jsx-no-duplicate-props': ERROR,
198+
'react/jsx-no-literals': OFF,
199+
'react/jsx-no-target-blank': OFF,
200+
'react/jsx-pascal-case': OFF,
201+
'react/jsx-sort-props': OFF,
202+
'react/jsx-uses-vars': ERROR,
203+
'react/no-comment-textnodes': OFF,
204+
'react/no-danger': OFF,
205+
'react/no-deprecated': OFF,
206+
'react/no-did-mount-set-state': OFF,
207+
'react/no-did-update-set-state': OFF,
208+
'react/no-direct-mutation-state': OFF,
209+
'react/no-multi-comp': OFF,
210+
'react/no-render-return-value': OFF,
211+
'react/no-set-state': OFF,
212+
'react/no-string-refs': OFF,
213+
'react/no-unknown-property': OFF,
214+
'react/prefer-es6-class': OFF,
215+
'react/prefer-stateless-function': OFF,
216+
'react/prop-types': OFF,
217+
'react/require-extension': OFF,
218+
'react/require-optimization': OFF,
219+
'react/require-render-return': OFF,
220+
'react/sort-comp': OFF,
221+
'react/sort-prop-types': OFF,
222+
36223
'accessor-pairs': OFF,
37224
'brace-style': [ERROR, '1tbs'],
38225
'consistent-return': OFF,
@@ -51,7 +238,6 @@ module.exports = {
51238
'no-restricted-globals': [ERROR].concat(restrictedGlobals),
52239
'no-restricted-syntax': [ERROR, 'WithStatement'],
53240
'no-shadow': ERROR,
54-
'no-unused-expressions': ERROR,
55241
'no-unused-vars': [ERROR, {args: 'none'}],
56242
'no-use-before-define': OFF,
57243
'no-useless-concat': OFF,
@@ -74,8 +260,6 @@ module.exports = {
74260
// deal. But I turned it off because loading the plugin causes some obscure
75261
// syntax error and it didn't seem worth investigating.
76262
'max-len': OFF,
77-
// Prettier forces semicolons in a few places
78-
'flowtype/object-type-delimiter': OFF,
79263

80264
// React & JSX
81265
// Our transforms set this automatically
@@ -166,7 +350,7 @@ module.exports = {
166350
// We apply these settings to the source files that get compiled.
167351
// They can use all features including JSX (but shouldn't use `var`).
168352
files: esNextPaths,
169-
parser: 'babel-eslint',
353+
parser: 'hermes-eslint',
170354
parserOptions: {
171355
ecmaVersion: 8,
172356
sourceType: 'module',
@@ -204,14 +388,6 @@ module.exports = {
204388
ERROR,
205389
{isProductionUserAppCode: false},
206390
],
207-
208-
// Disable accessibility checks
209-
'jsx-a11y/aria-role': OFF,
210-
'jsx-a11y/no-noninteractive-element-interactions': OFF,
211-
'jsx-a11y/no-static-element-interactions': OFF,
212-
'jsx-a11y/role-has-required-aria-props': OFF,
213-
'jsx-a11y/no-noninteractive-tabindex': OFF,
214-
'jsx-a11y/tabindex-no-positive': OFF,
215391
},
216392
},
217393
{
@@ -253,10 +429,69 @@ module.exports = {
253429
},
254430
],
255431

432+
env: {
433+
browser: true,
434+
es6: true,
435+
node: true,
436+
jest: true,
437+
jasmine: true,
438+
},
439+
256440
globals: {
441+
$Call: 'readonly',
442+
$ElementType: 'readonly',
443+
$Flow$ModuleRef: 'readonly',
444+
$FlowFixMe: 'readonly',
445+
$Keys: 'readonly',
446+
$NonMaybeType: 'readonly',
447+
$PropertyType: 'readonly',
448+
$ReadOnly: 'readonly',
449+
$ReadOnlyArray: 'readonly',
450+
$Shape: 'readonly',
451+
AnimationFrameID: 'readonly',
452+
Class: 'readonly',
453+
ClientRect: 'readonly',
454+
CopyInspectedElementPath: 'readonly',
455+
DOMHighResTimeStamp: 'readonly',
456+
EventListener: 'readonly',
457+
Iterable: 'readonly',
458+
Iterator: 'readonly',
459+
JSONValue: 'readonly',
460+
JSResourceReference: 'readonly',
461+
MouseEventHandler: 'readonly',
462+
PropagationPhases: 'readonly',
463+
PropertyDescriptor: 'readonly',
464+
React$AbstractComponent: 'readonly',
465+
React$Component: 'readonly',
466+
React$ComponentType: 'readonly',
467+
React$Config: 'readonly',
468+
React$Context: 'readonly',
469+
React$Element: 'readonly',
470+
React$ElementConfig: 'readonly',
471+
React$ElementProps: 'readonly',
472+
React$ElementRef: 'readonly',
473+
React$ElementType: 'readonly',
474+
React$Key: 'readonly',
475+
React$Node: 'readonly',
476+
React$Portal: 'readonly',
477+
React$Ref: 'readonly',
478+
React$StatelessFunctionalComponent: 'readonly',
479+
ReadableStreamController: 'readonly',
480+
RequestInfo: 'readonly',
481+
RequestOptions: 'readonly',
482+
ResponseState: 'readonly',
483+
StoreAsGlobal: 'readonly',
484+
symbol: 'readonly',
485+
SyntheticEvent: 'readonly',
486+
SyntheticMouseEvent: 'readonly',
487+
Thenable: 'readonly',
488+
TimeoutID: 'readonly',
489+
WheelEventHandler: 'readonly',
490+
257491
spyOnDev: 'readonly',
258492
spyOnDevAndProd: 'readonly',
259493
spyOnProd: 'readonly',
494+
__DEV__: 'readonly',
260495
__EXPERIMENTAL__: 'readonly',
261496
__EXTENSION__: 'readonly',
262497
__PROFILE__: 'readonly',

package.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
"packages/*"
55
],
66
"devDependencies": {
7+
"@actuallyworks/node-fetch": "^2.6.0",
78
"@babel/cli": "^7.10.5",
89
"@babel/code-frame": "^7.10.4",
910
"@babel/core": "^7.11.1",
10-
"@babel/eslint-parser": "^7.11.4",
1111
"@babel/helper-module-imports": "^7.10.4",
1212
"@babel/parser": "^7.11.3",
1313
"@babel/plugin-external-helpers": "^7.10.4",
@@ -38,7 +38,6 @@
3838
"@babel/traverse": "^7.11.0",
3939
"abort-controller": "^3.0.0",
4040
"art": "0.10.1",
41-
"babel-eslint": "^10.0.3",
4241
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
4342
"chalk": "^3.0.0",
4443
"cli-table": "^0.3.1",
@@ -50,13 +49,12 @@
5049
"danger": "^9.2.10",
5150
"error-stack-parser": "^2.0.6",
5251
"eslint": "^7.7.0",
53-
"eslint-config-fbjs": "^3.1.1",
5452
"eslint-config-prettier": "^6.9.0",
5553
"eslint-plugin-babel": "^5.3.0",
5654
"eslint-plugin-eslint-plugin": "^3.5.3",
5755
"eslint-plugin-flowtype": "^2.25.0",
56+
"eslint-plugin-ft-flow": "^2.0.3",
5857
"eslint-plugin-jest": "^22.15.0",
59-
"eslint-plugin-jsx-a11y": "^6.3.1",
6058
"eslint-plugin-no-for-of-loops": "^1.0.0",
6159
"eslint-plugin-no-function-declare-after-return": "^1.0.0",
6260
"eslint-plugin-react": "^6.7.1",
@@ -68,6 +66,7 @@
6866
"glob-stream": "^6.1.0",
6967
"google-closure-compiler": "^20200517.0.0",
7068
"gzip-size": "^5.1.1",
69+
"hermes-eslint": "^0.9.0",
7170
"jasmine-check": "^1.0.0-rc.0",
7271
"jest": "^26.6.3",
7372
"jest-cli": "^26.6.3",
@@ -77,7 +76,6 @@
7776
"minimist": "^1.2.3",
7877
"mkdirp": "^0.5.1",
7978
"ncp": "^2.0.0",
80-
"@actuallyworks/node-fetch": "^2.6.0",
8179
"pacote": "^10.3.0",
8280
"prettier": "1.19.1",
8381
"prop-types": "^15.6.2",

packages/eslint-plugin-react-hooks/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
3232
},
3333
"devDependencies": {
34+
"@babel/eslint-parser": "^7.11.4",
3435
"@typescript-eslint/parser-v2": "npm:@typescript-eslint/parser@^2.26.0",
3536
"@typescript-eslint/parser-v3": "npm:@typescript-eslint/parser@^3.10.0",
3637
"@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@^4.1.0",
37-
"@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.0.0-0"
38+
"@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.0.0-0",
39+
"babel-eslint": "^10.0.3"
3840
}
3941
}

0 commit comments

Comments
 (0)