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 ESLint v8 #305

Merged
merged 6 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['12.14', '14.x', '16.x']
node-version: ['12.22', '14.x', '16.x']
timeout-minutes: 10

steps:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"devDependencies": {
"@shopify/tophat": "^0.0.4",
"@types/jest": "^26.0.24",
"eslint": "^7.30.0",
"eslint": "^8.3.0",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"jest": "^27.0.6",
Expand Down
21 changes: 21 additions & 0 deletions packages/eslint-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Breaking Change

- Updated peer dependency on `eslint` to require at least v8.3.0. [[#305](https://github.com/Shopify/web-configs/pull/305)]
- Replaced usage of the long-deprecated `babel-eslint` and `eslint-plugin-babel` with `@babel/eslint-parser` and `@babel/eslint-plugin`. [[#305](https://github.com/Shopify/web-configs/pull/305)]
- Updated the minimum version of several eslint plugins. [[#305](https://github.com/Shopify/web-configs/pull/305)]

| Package | Old version | New version |
| ---------------------------------- | ----------- | ----------- |
| `typescript-eslint/eslint-plugin` | `^4.28.2` | `^5.4.0` |
| `typescript-eslint/parser` | `^4.28.2` | `^5.4.0` |
| `eslint-plugin-import` | `^2.23.4` | `^2.25.3` |
| `eslint-plugin-jest` | `^24.3.6` | `^25.3.0` |
| `eslint-plugin-jest-formatting` | `^3.0.0` | `^3.1.0` |
| `eslint-plugin-jsx-a11y` | `^6.4.1` | `^6.5.0` |
| `eslint-plugin-prettier` | `^3.4.0` | `^4.0.0` |
| `eslint-plugin-promise` | `^5.1.0` | `^5.1.1` |
| `eslint-plugin-react` | `^7.24.0` | `^7.27.1` |
| `eslint-plugin-react-hooks` | `^4.2.0` | `^4.3.0` |
| `eslint-plugin-sort-class-members` | `^1.11.0` | `^1.14.0` |


### Changed

- Update env and ecmaVersion to '2021' in `esnext` and`typescript` presets to support modern language features. [[#296](https://github.com/Shopify/web-configs/pull/296), [#304](https://github.com/Shopify/web-configs/pull/304)]
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/lib/config/esnext.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const merge = require('merge');

module.exports = {
extends: 'plugin:@shopify/core',
parser: 'babel-eslint',
parser: '@babel/eslint-parser',

env: {
es2021: true,
Expand All @@ -13,7 +13,7 @@ module.exports = {
sourceType: 'module',
},

plugins: ['babel', 'promise', 'sort-class-members', 'import'],
plugins: ['@babel/eslint-plugin', 'promise', 'sort-class-members', 'import'],

settings: {
'import/ignore': ['node_modules', '\\.s?css'],
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/lib/config/graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {

overrides: [
{
parser: 'babel-eslint',
parser: '@babel/eslint-parser',
files: ['*.graphql'],
rules: require('./rules/graphql'),
},
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/lib/config/prettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ module.exports = {

rules: merge(require('./rules/prettier'), {
// rules to disable to prefer prettier
'@babel/semi': 'off',
'@babel/object-curly-spacing': 'off',
'@shopify/class-property-semi': 'off',
'@shopify/binary-assignment-parens': 'off',
'babel/semi': 'off',
'babel/object-curly-spacing': 'off',
'prefer-arrow-callback': 'off',
'arrow-body-style': 'off',

Expand Down
14 changes: 5 additions & 9 deletions packages/eslint-plugin/lib/config/rules/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@
// also turned off in configs that include these rules.

module.exports = {
// Doesn't complain about optional chaining
'babel/camelcase': ['error', {properties: 'always'}],
// Ignores capitalized decorators (@Decorator)
'babel/new-cap': ['error', {newIsCap: true, capIsNew: false}],
'@babel/new-cap': ['error', {newIsCap: true, capIsNew: false}],
// Doesn't complain about export x from "mod"; or export * as x from "mod";
'babel/object-curly-spacing': ['error', 'never'],
'@babel/object-curly-spacing': ['error', 'never'],
// Doesn't fail when inside class properties
'babel/no-invalid-this': 'error',
'@babel/no-invalid-this': 'error',
// Doesn't fail when using do expressions or optional chaining
'babel/no-unused-expressions': 'error',
'@babel/no-unused-expressions': 'error',
// Rule to flag missing semicolons
'babel/semi': 'error',
// Doesn't complain when used with BigInt
'babel/valid-typeof': 'error',
'@babel/semi': 'error',
};
25 changes: 13 additions & 12 deletions packages/eslint-plugin/lib/config/rules/jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,24 @@ module.exports = {
'jest/no-interpolation-in-snapshots': 'error',
// For better failure messages, use `toHaveLength()` to on object lengths.
'jest/prefer-to-have-length': 'error',
// Suggest using toMatchInlineSnapshot()
'jest/prefer-inline-snapshots': 'off',
// For better failure messages, use `toBeNull()` to assert on null values.
'jest/prefer-to-be-null': 'error',
// For better failure messages, use `toBeUndefined()` to assert on undefined values.
'jest/prefer-to-be-undefined': 'error',
// For better failure messages, use toBe()` for native value and `toBeNull()`/`toBeUndefined()` to assert on null/undefined values.
'jest/prefer-to-be': 'error',
// Ensure `expect()` is called with a single argument and there is an actual expectation made.
'jest/valid-expect': 'error',
// Suggest using expect.assertions() OR expect.hasAssertions()
'jest/prefer-expect-assertions': 'off',
// Enforce having return statement when testing with promises
'jest/valid-expect-in-promise': 'error',
// Enforce valid describe() callback
'jest/valid-describe': 'error',
'jest/valid-describe-callback': 'error',
// Have control over test and it usages
'jest/consistent-test-it': 'error',
// Use .only and .skip over f and x
'jest/no-test-prefixes': 'error',
// Disallow explicitly returning from tests
'jest/no-test-return-statement': 'error',
// Enforce lowercase test names
'jest/lowercase-name': ['error', {ignore: ['describe']}],
'jest/prefer-lowercase-title': ['error', {ignore: ['describe']}],
// Disallow importing Jest
'jest/no-jest-import': 'error',
// Disallow alias methods
Expand All @@ -47,8 +43,15 @@ module.exports = {
'jest/no-hooks': 'off',
// Using a callback in asynchronous tests
'jest/no-done-callback': 'error',
// Disallow using toBeTruthy() & toBeFalsy()
'jest/no-truthy-falsy': 'error',
// Disallow using toBeTruthy(), toBeFalsy(), expect.resolves
'jest/no-restricted-matchers': [
'error',
{
toBeTruthy: 'Avoid `toBeTruthy`',
toBeFalsy: 'Avoid `toBeFalsy`',
resolves: 'Use `expect(await promise)` instead.',
},
],
// Suggest using toBeCalledWith() OR toHaveBeenCalledWith()
'jest/prefer-called-with': 'off',
// Suggest using jest.spyOn()
Expand All @@ -75,8 +78,6 @@ module.exports = {
'jest/no-export': 'error',
// Prevents `expect` statements outside of a `test` or `it` block
'jest/no-standalone-expect': 'error',
// Avoid using `expect().resolves`
'jest/no-expect-resolves': 'error',
// Enforce titles don't duplicate the test function name or start with a space
'jest/valid-title': 'error',
// Suggest to have all hooks at top-level before tests
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-plugin/lib/config/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = {
// TypeScript provides a better mechanism (explicit `this` type)
// for ensuring proper `this` usage in functions not assigned to
// object properties.
'babel/no-invalid-this': 'off',
'@babel/no-invalid-this': 'off',

// Handled by TypeScript itself
'no-undef': 'off',
Expand All @@ -35,7 +35,6 @@ module.exports = {
'no-empty-function': 'off',
'func-call-spacing': 'off',
'@shopify/no-fully-static-classes': 'off',
'babel/camelcase': 'off',
'sort-class-members/sort-class-members': 'off',
camelcase: 'off',
'no-array-constructor': 'off',
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/lib/rules/class-property-semi.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ module.exports = {
}

return {
ClassProperty: checkClassProperty,
'ClassProperty,PropertyDefinition': checkClassProperty,
};
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function checkContent(
) {
function isInvalidContent(contentNode) {
return (
(contentNode.type === 'Literal' &&
((contentNode.type === 'Literal' || contentNode.type === 'JSXText') &&
((!allowStrings &&
typeof contentNode.value === 'string' &&
!isEmptyString(contentNode.value)) ||
Expand Down
4 changes: 3 additions & 1 deletion packages/eslint-plugin/lib/rules/no-fully-static-classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ module.exports = {
create(context) {
function isStaticMember(node) {
return (
(node.type === 'MethodDefinition' || node.type === 'ClassProperty') &&
(node.type === 'MethodDefinition' ||
node.type === 'ClassProperty' ||
node.type === 'PropertyDefinition') &&
node.static
);
}
Expand Down
6 changes: 5 additions & 1 deletion packages/eslint-plugin/lib/rules/prefer-class-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ module.exports = {

function getClassInstanceProperties(classNode) {
return classNode.body.body.filter((propertyNode) => {
return propertyNode.type === 'ClassProperty' && !propertyNode.static;
return (
(propertyNode.type === 'ClassProperty' ||
propertyNode.type === 'PropertyDefinition') &&
!propertyNode.static
);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ function isSpreadElement(node) {
if (!node) {
return false;
}
return (
node.type === 'SpreadElement' || node.type === 'ExperimentalSpreadProperty'
);
return node.type === 'SpreadElement';
}

function getVariableByName(initialScope, name) {
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/lib/rules/react-initialize-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = {
declaredState: false,
};
},
ClassProperty(node) {
'ClassProperty,PropertyDefinition': function (node) {
if (classInfo == null || getName(node.key) !== 'state') {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module.exports = {
isES6Component--;
}
},
ClassProperty(node) {
'ClassProperty,PropertyDefinition': function (node) {
if (isES6Component === 0 || isValid(node)) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/lib/rules/react-type-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = {
ClassDeclaration(node) {
inTypeScriptReactComponent = looksLikeTypeScriptComponent(node);
},
ClassProperty(node) {
'ClassProperty,PropertyDefinition': function (node) {
if (
!inTypeScriptReactComponent ||
getName(node.key) !== 'state' ||
Expand Down
4 changes: 1 addition & 3 deletions packages/eslint-plugin/lib/rules/restrict-full-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ module.exports = {
(left.type === 'ObjectPattern' &&
left.properties.some((prop) => {
return (
prop.type === 'SpreadProperty' ||
prop.type === 'ExperimentalRestProperty' ||
prop.type === 'RestElement'
prop.type === 'SpreadProperty' || prop.type === 'RestElement'
);
})) ||
(left.type === 'ArrayPattern' &&
Expand Down
34 changes: 17 additions & 17 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,30 @@
"typescript": "^3.9.2"
},
"peerDependencies": {
"eslint": "^7.0.0"
"eslint": "^8.3.0"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"babel-eslint": "^10.1.0",
"@babel/eslint-parser": "^7.16.3",
"@babel/eslint-plugin": "^7.14.5",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"change-case": "^4.1.2",
"common-tags": "^1.8.0",
"common-tags": "^1.8.2",
"eslint-config-prettier": "^8.3.0",
"eslint-module-utils": "^2.6.1",
"eslint-plugin-babel": "^5.3.1",
"eslint-module-utils": "^2.7.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-graphql": "^4.0.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jest": "^24.3.6",
"eslint-plugin-jest-formatting": "^3.0.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jest": "^25.3.0",
"eslint-plugin-jest-formatting": "^3.1.0",
"eslint-plugin-jsx-a11y": "^6.5.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-sort-class-members": "^1.11.0",
"jsx-ast-utils": "^3.2.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-sort-class-members": "^1.14.0",
"jsx-ast-utils": "^3.2.1",
"merge": "^2.1.1",
"pkg-dir": "^5.0.0",
"pluralize": "^8.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const {RuleTester} = require('eslint');
const rule = require('../../../lib/rules/class-property-semi');

const ruleTester = new RuleTester({
parser: require.resolve('babel-eslint'),
parser: require.resolve('@babel/eslint-parser'),
});

const classPropNoSemi = 'class Foo { bar = 1 }';
Expand Down Expand Up @@ -31,7 +31,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Missing semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand All @@ -41,7 +41,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Missing semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand All @@ -51,7 +51,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Extra semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand All @@ -60,7 +60,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Missing semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand All @@ -70,7 +70,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Missing semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand All @@ -80,7 +80,7 @@ ruleTester.run('class-property-semi', rule, {
errors: [
{
message: 'Extra semicolon.',
type: 'ClassProperty',
type: 'PropertyDefinition',
},
],
},
Expand Down
Loading