diff --git a/.eslintrc.js b/.eslintrc.js index 62db4c47c0008..a155becfafb67 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -183,7 +183,10 @@ module.exports = { }, }, { - files: ['packages/eslint-plugin-react-hooks/src/*.js'], + files: [ + 'scripts/eslint-rules/*.js', + 'packages/eslint-plugin-react-hooks/src/*.js' + ], plugins: ['eslint-plugin'], rules: { 'eslint-plugin/prefer-object-rule': ERROR, diff --git a/scripts/eslint-rules/__tests__/invariant-args-test.internal.js b/scripts/eslint-rules/__tests__/invariant-args-test.internal.js index eb84d8dd45a96..c36171a62c1d2 100644 --- a/scripts/eslint-rules/__tests__/invariant-args-test.internal.js +++ b/scripts/eslint-rules/__tests__/invariant-args-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../invariant-args'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester(); ruleTester.run('eslint-rules/invariant-args', rule, { diff --git a/scripts/eslint-rules/__tests__/no-cross-fork-imports-test.internal.js b/scripts/eslint-rules/__tests__/no-cross-fork-imports-test.internal.js index 2adfc9a9f9cd6..40ba3a2b42e5c 100644 --- a/scripts/eslint-rules/__tests__/no-cross-fork-imports-test.internal.js +++ b/scripts/eslint-rules/__tests__/no-cross-fork-imports-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../no-cross-fork-imports'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8, diff --git a/scripts/eslint-rules/__tests__/no-cross-fork-types-test.internal.js b/scripts/eslint-rules/__tests__/no-cross-fork-types-test.internal.js index 93a3c7e663e45..daf40a1bd22cc 100644 --- a/scripts/eslint-rules/__tests__/no-cross-fork-types-test.internal.js +++ b/scripts/eslint-rules/__tests__/no-cross-fork-types-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../no-cross-fork-types'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8, diff --git a/scripts/eslint-rules/__tests__/no-primitive-constructors-test.internal.js b/scripts/eslint-rules/__tests__/no-primitive-constructors-test.internal.js index c440b30920f3f..67cee01439a2b 100644 --- a/scripts/eslint-rules/__tests__/no-primitive-constructors-test.internal.js +++ b/scripts/eslint-rules/__tests__/no-primitive-constructors-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../no-primitive-constructors'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester(); ruleTester.run('eslint-rules/no-primitive-constructors', rule, { diff --git a/scripts/eslint-rules/__tests__/no-production-logging-test.internal.js b/scripts/eslint-rules/__tests__/no-production-logging-test.internal.js index 81dc18b7e639e..ea5c2fc8a2abc 100644 --- a/scripts/eslint-rules/__tests__/no-production-logging-test.internal.js +++ b/scripts/eslint-rules/__tests__/no-production-logging-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../no-production-logging'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester(); ruleTester.run('no-production-logging', rule, { diff --git a/scripts/eslint-rules/__tests__/no-to-warn-dev-within-to-throw-test.internal.js b/scripts/eslint-rules/__tests__/no-to-warn-dev-within-to-throw-test.internal.js index 3a0da89f04fb4..35c7bc2e84810 100644 --- a/scripts/eslint-rules/__tests__/no-to-warn-dev-within-to-throw-test.internal.js +++ b/scripts/eslint-rules/__tests__/no-to-warn-dev-within-to-throw-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../no-to-warn-dev-within-to-throw'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester(); ruleTester.run('eslint-rules/no-to-warn-dev-within-to-throw', rule, { diff --git a/scripts/eslint-rules/__tests__/warning-args-test.internal.js b/scripts/eslint-rules/__tests__/warning-args-test.internal.js index 66f51fc717c5b..e8cdc9161caeb 100644 --- a/scripts/eslint-rules/__tests__/warning-args-test.internal.js +++ b/scripts/eslint-rules/__tests__/warning-args-test.internal.js @@ -10,7 +10,7 @@ 'use strict'; const rule = require('../warning-args'); -const RuleTester = require('eslint').RuleTester; +const {RuleTester} = require('eslint'); const ruleTester = new RuleTester(); ruleTester.run('eslint-rules/warning-args', rule, { diff --git a/scripts/eslint-rules/invariant-args.js b/scripts/eslint-rules/invariant-args.js index 4f1b336f600de..dd1bb201ec1f3 100644 --- a/scripts/eslint-rules/invariant-args.js +++ b/scripts/eslint-rules/invariant-args.js @@ -24,83 +24,86 @@ Object.keys(existingErrorMap).forEach(key => * argument. */ -module.exports = function(context) { - // we also allow literal strings and concatenated literal strings - function getLiteralString(node) { - if (node.type === 'Literal' && typeof node.value === 'string') { - return node.value; - } else if (node.type === 'BinaryExpression' && node.operator === '+') { - const l = getLiteralString(node.left); - const r = getLiteralString(node.right); - if (l !== null && r !== null) { - return l + r; +module.exports = { + meta: { + schema: [], + }, + create(context) { + // we also allow literal strings and concatenated literal strings + function getLiteralString(node) { + if (node.type === 'Literal' && typeof node.value === 'string') { + return node.value; + } else if (node.type === 'BinaryExpression' && node.operator === '+') { + const l = getLiteralString(node.left); + const r = getLiteralString(node.right); + if (l !== null && r !== null) { + return l + r; + } } + return null; } - return null; - } - return { - CallExpression: function(node) { - // This could be a little smarter by checking context.getScope() to see - // how warning/invariant was defined. - const isInvariant = - node.callee.type === 'Identifier' && node.callee.name === 'invariant'; - if (!isInvariant) { - return; - } - if (node.arguments.length < 2) { - context.report(node, '{{name}} takes at least two arguments', { - name: node.callee.name, - }); - return; - } - const format = getLiteralString(node.arguments[1]); - if (format === null) { - context.report( - node, - 'The second argument to {{name}} must be a string literal', - {name: node.callee.name} - ); - return; - } - if (format.length < 10 || /^[s\W]*$/.test(format)) { - context.report( - node, - 'The {{name}} format should be able to uniquely identify this ' + - '{{name}}. Please, use a more descriptive format than: {{format}}', - {name: node.callee.name, format: format} - ); - return; - } - // count the number of formatting substitutions, plus the first two args - const expectedNArgs = (format.match(/%s/g) || []).length + 2; - if (node.arguments.length !== expectedNArgs) { - context.report( - node, - 'Expected {{expectedNArgs}} arguments in call to {{name}} based on ' + - 'the number of "%s" substitutions, but got {{length}}', - { - expectedNArgs: expectedNArgs, + return { + CallExpression: function(node) { + // This could be a little smarter by checking context.getScope() to see + // how warning/invariant was defined. + const isInvariant = + node.callee.type === 'Identifier' && node.callee.name === 'invariant'; + if (!isInvariant) { + return; + } + if (node.arguments.length < 2) { + context.report(node, '{{name}} takes at least two arguments', { name: node.callee.name, - length: node.arguments.length, - } - ); - } + }); + return; + } + const format = getLiteralString(node.arguments[1]); + if (format === null) { + context.report( + node, + 'The second argument to {{name}} must be a string literal', + {name: node.callee.name} + ); + return; + } + if (format.length < 10 || /^[s\W]*$/.test(format)) { + context.report( + node, + 'The {{name}} format should be able to uniquely identify this ' + + '{{name}}. Please, use a more descriptive format than: {{format}}', + {name: node.callee.name, format: format} + ); + return; + } + // count the number of formatting substitutions, plus the first two args + const expectedNArgs = (format.match(/%s/g) || []).length + 2; + if (node.arguments.length !== expectedNArgs) { + context.report( + node, + 'Expected {{expectedNArgs}} arguments in call to {{name}} based on ' + + 'the number of "%s" substitutions, but got {{length}}', + { + expectedNArgs: expectedNArgs, + name: node.callee.name, + length: node.arguments.length, + } + ); + } - if (!messages.has(format)) { - context.report( - node, - 'Error message does not have a corresponding production ' + - 'error code.\n\n' + - 'Run `yarn extract-errors` to add the message to error code ' + - 'map, so it can be stripped from the production builds. ' + - "Alternatively, if you're updating an existing error " + - 'message, you can modify ' + - '`scripts/error-codes/codes.json` directly.' - ); - } - }, - }; + if (!messages.has(format)) { + context.report( + node, + 'Error message does not have a corresponding production ' + + 'error code.\n\n' + + 'Run `yarn extract-errors` to add the message to error code ' + + 'map, so it can be stripped from the production builds. ' + + "Alternatively, if you're updating an existing error " + + 'message, you can modify ' + + '`scripts/error-codes/codes.json` directly.' + ); + } + }, + }; + }, }; - -module.exports.schema = []; diff --git a/scripts/eslint-rules/no-cross-fork-types.js b/scripts/eslint-rules/no-cross-fork-types.js index eaa9f07d74e06..1590178f77923 100644 --- a/scripts/eslint-rules/no-cross-fork-types.js +++ b/scripts/eslint-rules/no-cross-fork-types.js @@ -46,7 +46,6 @@ function warnIfOldField(context, oldFields, identifier) { module.exports = { meta: { type: 'problem', - fixable: 'code', }, create(context) { const sourceFilename = context.getFilename(); diff --git a/scripts/eslint-rules/no-primitive-constructors.js b/scripts/eslint-rules/no-primitive-constructors.js index 51ddde284e747..bbba8ccd54fd6 100644 --- a/scripts/eslint-rules/no-primitive-constructors.js +++ b/scripts/eslint-rules/no-primitive-constructors.js @@ -9,42 +9,47 @@ 'use strict'; -module.exports = function(context) { - function report(node, name, msg) { - context.report(node, `Do not use the ${name} constructor. ${msg}`); - } +module.exports = { + meta: { + schema: [], + }, + create(context) { + function report(node, name, msg) { + context.report(node, `Do not use the ${name} constructor. ${msg}`); + } - function check(node) { - const name = node.callee.name; - switch (name) { - case 'Boolean': - report( - node, - name, - 'To cast a value to a boolean, use double negation: !!value' - ); - break; - case 'String': - report( - node, - name, - 'To cast a value to a string, concat it with the empty string ' + - "(unless it's a symbol, which has different semantics): " + - "'' + value" - ); - break; - case 'Number': - report( - node, - name, - 'To cast a value to a number, use the plus operator: +value' - ); - break; + function check(node) { + const name = node.callee.name; + switch (name) { + case 'Boolean': + report( + node, + name, + 'To cast a value to a boolean, use double negation: !!value' + ); + break; + case 'String': + report( + node, + name, + 'To cast a value to a string, concat it with the empty string ' + + "(unless it's a symbol, which has different semantics): " + + "'' + value" + ); + break; + case 'Number': + report( + node, + name, + 'To cast a value to a number, use the plus operator: +value' + ); + break; + } } - } - return { - CallExpression: check, - NewExpression: check, - }; + return { + CallExpression: check, + NewExpression: check, + }; + }, }; diff --git a/scripts/eslint-rules/no-production-logging.js b/scripts/eslint-rules/no-production-logging.js index ae6d909f19424..26f72db39c143 100644 --- a/scripts/eslint-rules/no-production-logging.js +++ b/scripts/eslint-rules/no-production-logging.js @@ -12,6 +12,7 @@ module.exports = { meta: { fixable: 'code', + schema: [], }, create: function(context) { function isInDEVBlock(node) { diff --git a/scripts/eslint-rules/no-to-warn-dev-within-to-throw.js b/scripts/eslint-rules/no-to-warn-dev-within-to-throw.js index ff83f4e1bcede..dd272ad4f6860 100644 --- a/scripts/eslint-rules/no-to-warn-dev-within-to-throw.js +++ b/scripts/eslint-rules/no-to-warn-dev-within-to-throw.js @@ -9,28 +9,33 @@ 'use strict'; -module.exports = function(context) { - return { - Identifier(node) { - if (node.name === 'toWarnDev' || node.name === 'toErrorDev') { - let current = node; - while (current.parent) { - if (current.type === 'CallExpression') { - if ( - current && - current.callee && - current.callee.property && - current.callee.property.name === 'toThrow' - ) { - context.report( - node, - node.name + '() matcher should not be nested' - ); +module.exports = { + meta: { + schema: [], + }, + create(context) { + return { + Identifier(node) { + if (node.name === 'toWarnDev' || node.name === 'toErrorDev') { + let current = node; + while (current.parent) { + if (current.type === 'CallExpression') { + if ( + current && + current.callee && + current.callee.property && + current.callee.property.name === 'toThrow' + ) { + context.report( + node, + node.name + '() matcher should not be nested' + ); + } } + current = current.parent; } - current = current.parent; } - } - }, - }; + }, + }; + }, }; diff --git a/scripts/eslint-rules/warning-args.js b/scripts/eslint-rules/warning-args.js index b3cd6cbc3805b..41a709c67774e 100644 --- a/scripts/eslint-rules/warning-args.js +++ b/scripts/eslint-rules/warning-args.js @@ -24,76 +24,79 @@ Object.keys(existingErrorMap).forEach(key => * argument. */ -module.exports = function(context) { - // we also allow literal strings and concatenated literal strings - function getLiteralString(node) { - if (node.type === 'Literal' && typeof node.value === 'string') { - return node.value; - } else if (node.type === 'BinaryExpression' && node.operator === '+') { - const l = getLiteralString(node.left); - const r = getLiteralString(node.right); - if (l !== null && r !== null) { - return l + r; +module.exports = { + meta: { + schema: [], + }, + create(context) { + // we also allow literal strings and concatenated literal strings + function getLiteralString(node) { + if (node.type === 'Literal' && typeof node.value === 'string') { + return node.value; + } else if (node.type === 'BinaryExpression' && node.operator === '+') { + const l = getLiteralString(node.left); + const r = getLiteralString(node.right); + if (l !== null && r !== null) { + return l + r; + } } + return null; } - return null; - } - return { - CallExpression: function(node) { - // This could be a little smarter by checking context.getScope() to see - // how warning/invariant was defined. - const isWarning = - node.callee.type === 'MemberExpression' && - node.callee.object.type === 'Identifier' && - node.callee.object.name === 'console' && - node.callee.property.type === 'Identifier' && - (node.callee.property.name === 'error' || - node.callee.property.name === 'warn'); - if (!isWarning) { - return; - } - const name = 'console.' + node.callee.property.name; - if (node.arguments.length < 1) { - context.report(node, '{{name}} takes at least one argument', { - name, - }); - return; - } - const format = getLiteralString(node.arguments[0]); - if (format === null) { - context.report( - node, - 'The first argument to {{name}} must be a string literal', - {name} - ); - return; - } - if (format.length < 10 || /^[s\W]*$/.test(format)) { - context.report( - node, - 'The {{name}} format should be able to uniquely identify this ' + - 'warning. Please, use a more descriptive format than: {{format}}', - {name, format} - ); - return; - } - // count the number of formatting substitutions, plus the first two args - const expectedNArgs = (format.match(/%s/g) || []).length + 1; - if (node.arguments.length !== expectedNArgs) { - context.report( - node, - 'Expected {{expectedNArgs}} arguments in call to {{name}} based on ' + - 'the number of "%s" substitutions, but got {{length}}', - { - expectedNArgs: expectedNArgs, + return { + CallExpression: function(node) { + // This could be a little smarter by checking context.getScope() to see + // how warning/invariant was defined. + const isWarning = + node.callee.type === 'MemberExpression' && + node.callee.object.type === 'Identifier' && + node.callee.object.name === 'console' && + node.callee.property.type === 'Identifier' && + (node.callee.property.name === 'error' || + node.callee.property.name === 'warn'); + if (!isWarning) { + return; + } + const name = 'console.' + node.callee.property.name; + if (node.arguments.length < 1) { + context.report(node, '{{name}} takes at least one argument', { name, - length: node.arguments.length, - } - ); - } - }, - }; + }); + return; + } + const format = getLiteralString(node.arguments[0]); + if (format === null) { + context.report( + node, + 'The first argument to {{name}} must be a string literal', + {name} + ); + return; + } + if (format.length < 10 || /^[s\W]*$/.test(format)) { + context.report( + node, + 'The {{name}} format should be able to uniquely identify this ' + + 'warning. Please, use a more descriptive format than: {{format}}', + {name, format} + ); + return; + } + // count the number of formatting substitutions, plus the first two args + const expectedNArgs = (format.match(/%s/g) || []).length + 1; + if (node.arguments.length !== expectedNArgs) { + context.report( + node, + 'Expected {{expectedNArgs}} arguments in call to {{name}} based on ' + + 'the number of "%s" substitutions, but got {{length}}', + { + expectedNArgs: expectedNArgs, + name, + length: node.arguments.length, + } + ); + } + }, + }; + }, }; - -module.exports.schema = [];