Update eslint and eslint configuration

This commit updates eslint from v4 to v6. In doing so, I've moved off of
the create-react-app base eslint config. We were on an old version (v2)
and it doesn't make sense to update to v4, as in v4 create-react-app
uses typescript. Also, it didn't make sense to stay on
create-react-app's v2 config, because then it had unmet peer dependency
constraints on old versions of eslint.

Instead, I've moved us to use the default rules for eslint,
eslint-plugin-react, and eslint-plugin-flowtype.

I also made some changes to the codebase to satisfy the new lint rules
that came with this change.

Test plan: `yarn test` passes.
This commit is contained in:
Dandelion Mané 2019-07-05 18:36:43 +01:00
parent 6a40d962fb
commit 7a493b596d
11 changed files with 380 additions and 283 deletions

View File

@ -1,8 +1,25 @@
// @flow // @flow
module.exports = { module.exports = {
parser: "babel-eslint", parser: "babel-eslint",
plugins: ["flowtype"], plugins: ["flowtype", "react"],
extends: "react-app", env: {
browser: true,
es6: true,
node: true,
jest: true,
},
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:flowtype/recommended",
],
rules: { rules: {
"no-unused-vars": [ "no-unused-vars": [
"warn", "warn",
@ -14,5 +31,14 @@ module.exports = {
], ],
"no-use-before-define": ["off"], "no-use-before-define": ["off"],
"no-useless-constructor": ["off"], "no-useless-constructor": ["off"],
"no-case-declarations": ["off"],
"react/prop-types": ["off"],
"flowtype/generic-spacing": ["off"],
"flowtype/space-after-type-colon": ["off"],
},
settings: {
react: {
version: "detect",
},
}, },
}; };

View File

@ -32,7 +32,7 @@
}, },
"devDependencies": { "devDependencies": {
"babel-core": "6.26.0", "babel-core": "6.26.0",
"babel-eslint": "7.2.3", "babel-eslint": "10.0.2",
"babel-jest": "20.0.3", "babel-jest": "20.0.3",
"babel-loader": "7.1.2", "babel-loader": "7.1.2",
"babel-plugin-transform-es2015-for-of": "^6.23.0", "babel-plugin-transform-es2015-for-of": "^6.23.0",
@ -45,12 +45,12 @@
"enzyme": "^3.3.0", "enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1", "enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.3", "enzyme-to-json": "^3.3.3",
"eslint": "4.10.0", "eslint": "6.0.1",
"eslint-plugin-flowtype": "3.11.1",
"eslint-config-react-app": "^2.1.0", "eslint-config-react-app": "^2.1.0",
"eslint-plugin-flowtype": "2.50.0", "eslint-plugin-import": "2.18.0",
"eslint-plugin-import": "2.8.0", "eslint-plugin-jsx-a11y": "6.2.3",
"eslint-plugin-jsx-a11y": "5.1.1", "eslint-plugin-react": "7.14.2",
"eslint-plugin-react": "7.4.0",
"file-loader": "1.1.5", "file-loader": "1.1.5",
"flow-bin": "^0.102.0", "flow-bin": "^0.102.0",
"jest": "^24.8.0", "jest": "^24.8.0",

View File

@ -55,7 +55,7 @@ describe("core/address", () => {
const {FooAddress} = makeModules(); const {FooAddress} = makeModules();
expect(() => { expect(() => {
// $ExpectFlowError // $ExpectFlowError
FooAddress.assertValid = FooAddress.assertValid; FooAddress.assertValid = FooAddress.assertValid; // eslint-disable-line no-self-assign
}).toThrow(/read.only property/); }).toThrow(/read.only property/);
}); });

View File

@ -17,9 +17,10 @@ describe("explorer/pagerankTable/TableRow", () => {
description={<span data-test-description={true} />} description={<span data-test-description={true} />}
multiuseColumn={"50.00%"} multiuseColumn={"50.00%"}
cred={133.7} cred={133.7}
children={<div data-test-children={true} />}
showPadding={false} showPadding={false}
/> >
<div data-test-children={true} />{" "}
</TableRow>
); );
} }
it("depth parameter changes the color, but not the indentation", () => { it("depth parameter changes the color, but not the indentation", () => {
@ -32,8 +33,9 @@ describe("explorer/pagerankTable/TableRow", () => {
description={<span data-test-description={true} />} description={<span data-test-description={true} />}
multiuseColumn={"50.00%"} multiuseColumn={"50.00%"}
cred={133.7} cred={133.7}
children={<div data-test-children={true} />} >
/> <div data-test-children={true} />
</TableRow>
); );
const tr = el.find("tr"); const tr = el.find("tr");
const trStyle = tr.props().style; const trStyle = tr.props().style;
@ -52,8 +54,9 @@ describe("explorer/pagerankTable/TableRow", () => {
description={<span data-test-description={true} />} description={<span data-test-description={true} />}
multiuseColumn={"50.00%"} multiuseColumn={"50.00%"}
cred={133.7} cred={133.7}
children={<div data-test-children={true} />} >
/> <div data-test-children={true} />
</TableRow>
); );
const tr = el.find("tr"); const tr = el.find("tr");
const trStyle = tr.props().style; const trStyle = tr.props().style;
@ -138,9 +141,10 @@ describe("explorer/pagerankTable/TableRow", () => {
description={<span data-test-description={true} />} description={<span data-test-description={true} />}
multiuseColumn={"50.00%"} multiuseColumn={"50.00%"}
cred={133.7} cred={133.7}
children={<div data-test-children={true} />}
showPadding={true} showPadding={true}
/> >
<div data-test-children={true} />
</TableRow>
); );
} }
it("has two identical padding rows", () => { it("has two identical padding rows", () => {

View File

@ -84,6 +84,19 @@ export type NestedFieldType = {|
const ID_FIELD_NAME = "id"; const ID_FIELD_NAME = "id";
export function schema(types: {[Typename]: NodeType}): Schema { export function schema(types: {[Typename]: NodeType}): Schema {
function assertKind(path, elementTypename, validKinds) {
const self = `field ${path.map((x) => JSON.stringify(x)).join("/")}`;
const elementType = types[elementTypename];
if (elementType == null) {
throw new Error(`${self} has unknown type: "${elementTypename}"`);
}
if (!validKinds.includes(elementType.type)) {
throw new Error(
`${self} has invalid type "${elementTypename}" ` +
`of kind "${elementType.type}"`
);
}
}
const result = {}; const result = {};
for (const typename of Object.keys(types)) { for (const typename of Object.keys(types)) {
const type = types[typename]; const type = types[typename];
@ -100,21 +113,6 @@ export function schema(types: {[Typename]: NodeType}): Schema {
case "OBJECT": case "OBJECT":
for (const fieldname of Object.keys(type.fields)) { for (const fieldname of Object.keys(type.fields)) {
const field = type.fields[fieldname]; const field = type.fields[fieldname];
function assertKind(path, elementTypename, validKinds) {
const self = `field ${path
.map((x) => JSON.stringify(x))
.join("/")}`;
const elementType = types[elementTypename];
if (elementType == null) {
throw new Error(`${self} has unknown type: "${elementTypename}"`);
}
if (!validKinds.includes(elementType.type)) {
throw new Error(
`${self} has invalid type "${elementTypename}" ` +
`of kind "${elementType.type}"`
);
}
}
switch (field.type) { switch (field.type) {
case "ID": case "ID":
// Nothing to check. // Nothing to check.

View File

@ -34,5 +34,5 @@ ReactDOM.hydrate(<App routeData={routeData} history={history} />, target);
for (const el of document.querySelectorAll('link[rel="shortcut icon"]')) { for (const el of document.querySelectorAll('link[rel="shortcut icon"]')) {
const link: HTMLLinkElement = (el: any); const link: HTMLLinkElement = (el: any);
// (Appearances aside, this is not a no-op.) // (Appearances aside, this is not a no-op.)
link.href = link.href; link.href = link.href; // eslint-disable-line no-self-assign
} }

View File

@ -44,7 +44,7 @@ export default class FileUploaderInspectionTest extends React.Component<
{this.state.json ? ( {this.state.json ? (
<pre style={{backgroundColor: "#efefef"}}>{displayContents}</pre> <pre style={{backgroundColor: "#efefef"}}>{displayContents}</pre>
) : ( ) : (
<p>"No JSON uploaded."</p> <p>{"No JSON uploaded."}</p>
)} )}
</div> </div>
); );

View File

@ -16,6 +16,7 @@ describe("webutil/Link", () => {
// Static type checks // Static type checks
void [ void [
/* eslint-disable react/jsx-key */
// Must specify either `href` or `to` // Must specify either `href` or `to`
<Link href="https://example.com/">click me</Link>, <Link href="https://example.com/">click me</Link>,
<Link to="/prototype/">click me, too</Link>, <Link to="/prototype/">click me, too</Link>,
@ -27,6 +28,7 @@ describe("webutil/Link", () => {
// May specify extra properties // May specify extra properties
<Link href="#" onClick={() => void alert("hi")} tabIndex={3} />, <Link href="#" onClick={() => void alert("hi")} tabIndex={3} />,
/* eslint-enable react/jsx-key */
]; ];
it("renders a styled external link", () => { it("renders a styled external link", () => {

View File

@ -49,12 +49,7 @@ export default class BrowserLocalStore implements LocalStore {
} }
const stringified = JSON.stringify(data); const stringified = JSON.stringify(data);
try { window.localStorage[this.cacheKey(key)] = stringified;
window.localStorage[this.cacheKey(key)] = stringified;
} catch (e) {
// Probably went over the storage limit... that's not good.
throw e;
}
} }
/* /*

View File

@ -43,7 +43,7 @@ export default class CheckedLocalStore implements LocalStore {
if (deepEqual(data, JSON.parse(JSON.stringify(data)))) { if (deepEqual(data, JSON.parse(JSON.stringify(data)))) {
return; return;
} }
} catch (_) {} } catch (_) {} // eslint-disable-line no-empty
throw new Error(`bad value: ${data}`); throw new Error(`bad value: ${data}`);
} }
} }

556
yarn.lock

File diff suppressed because it is too large Load Diff