diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 0e16146..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -const _module = require("module"); -const path = require("path"); -const findPath = _module._findPath; -const hacks = [ - "eslint-plugin-autofix", - "eslint-plugin-no-autofix" -]; - -_module._findPath = (request, paths, isMain) => { - const r = findPath(request, paths, isMain); - - if (!r && hacks.includes(request)) { - try { - return require.resolve(`./node_modules/${request}`); - - // Keep the variable in place to ensure that ESLint started by older Node.js - // versions work as expected. - // eslint-disable-next-line no-unused-vars - } catch (e) { - return path.join(__dirname, `./packages/${request.slice("eslint-plugin-".length)}`); - } - } - return r; -}; - -module.exports = { - extends: [ - "eslint-config-eslint", - "plugin:eslint-plugin/recommended" - ], - plugins: [ - "eslint-plugin", - "eslint-plugin-autofix", - "eslint-plugin-no-autofix" - ], - rules: { - "no-autofix/eslint-plugin/test-case-shorthand-strings": "error" - }, - overrides: [ - { - files: ["packages/*/tests/**/*"], - env: { - mocha: true - } - } - ] -}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e3ce8a..1ad0556 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,47 +12,37 @@ jobs: fail-fast: false matrix: node-version: - - '18' - - '17' - - '16' + - 22 + - 21 + - 20 + - 18 os: - ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - - run: npm install + - run: npm install --force # ts-eslint does not support eslint v9 yet. - run: npm test lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: - node-version: '16' - - run: npm install + node-version: "lts/*" + - run: npm install --force # ts-eslint does not support eslint v9 yet. - run: npm run lint - eslint6: + eslint8: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: - node-version: '16' - - run: npm install - - run: npm install --save-dev eslint@6 - - run: npm test - - eslint7: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: '16' - - run: npm install - - run: npm install --save-dev eslint@7 + node-version: "lts/*" + - run: npm install --force + - run: npm install --save-dev eslint@8 - run: npm test diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..6515104 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,17 @@ +import baseConfig from "eslint-config-eslint"; +import eslintPlugin from "eslint-plugin-eslint-plugin"; +import autofixPlugin from "eslint-plugin-autofix"; +import noAutofixPlugin from "eslint-plugin-no-autofix"; +import nPlugin from "eslint-plugin-n"; // eslint-disable-line n/no-extraneous-import +import globals from "globals"; + +export default [ + ...baseConfig, + eslintPlugin.configs["flat/recommended"], + { files: ["packages/*/tests/**/*"], languageOptions: { globals: globals.mocha } }, + { + plugins: { autofix: autofixPlugin, "no-autofix": noAutofixPlugin }, + rules: { "eslint-comments/require-description": 0, "no-autofix/eslint-plugin/test-case-shorthand-strings": "error" } + }, + ...nPlugin.configs["flat/mixed-esm-and-cjs"] +]; diff --git a/package.json b/package.json index 36af133..ddd194f 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,12 @@ "author": "薛定谔的猫 ", "description": "some eslint plugins", "devDependencies": { - "eslint": "^8.1.0", - "eslint-config-eslint": "^7.0.0", - "eslint-plugin-eslint-plugin": "^4.0.1", - "eslint-plugin-jsdoc": "^37.0.3", - "eslint-plugin-node": "^11.1.0" + "eslint": "^9.1.1", + "eslint-config-eslint": "^9.0.0", + "eslint-plugin-autofix": "file:./packages/autofix", + "eslint-plugin-eslint-plugin": "^6.0.0", + "eslint-plugin-no-autofix": "file:./packages/no-autofix", + "globals": "^15.0.0" }, "scripts": { "lint": "eslint packages/", diff --git a/packages/autofix/lib/configs/all.js b/packages/autofix/lib/configs/all.js index a65d833..51c32df 100644 --- a/packages/autofix/lib/configs/all.js +++ b/packages/autofix/lib/configs/all.js @@ -1,24 +1,25 @@ -/** - * @fileoverview configs:all for the plugin - * @author 唯然 - */ -"use strict"; - -const packageMetadata = require("../../package"); -const PLUGIN_NAME = packageMetadata.name.replace(/^eslint-plugin-/u, ""); -const allRules = require("../rules"); - -const all = { - plugins: [PLUGIN_NAME], - rules: {} -}; - -// turn off core rules -Object.keys(allRules) - .reduce((rules, ruleName) => Object.assign(rules, { [ruleName]: "off" }), all.rules); - -// turn on plugin rules -Object.keys(allRules) - .reduce((rules, ruleName) => Object.assign(rules, { [`${PLUGIN_NAME}/${ruleName}`]: "error" }), all.rules); - -module.exports = all; +/** + * @fileoverview configs:all for the plugin + * @author 唯然 + */ +"use strict"; + +const packageMetadata = require("../../package"); +const PLUGIN_NAME = packageMetadata.name.replace(/^eslint-plugin-/u, ""); +const allRules = require("../rules"); + +const all = { + plugins: [PLUGIN_NAME], + rules: {} +}; + +// turn off core rules +Object.keys(allRules) + .reduce((rules, ruleName) => Object.assign(rules, { [ruleName]: "off" }), all.rules); + +// turn on plugin rules +Object.keys(allRules) + .reduce((rules, ruleName) => Object.assign(rules, { [`${PLUGIN_NAME}/${ruleName}`]: "error" }), all.rules); + +module.exports = all; + diff --git a/packages/autofix/lib/index.js b/packages/autofix/lib/index.js index 0f4472e..3a2b875 100644 --- a/packages/autofix/lib/index.js +++ b/packages/autofix/lib/index.js @@ -1,19 +1,27 @@ -/** - * @fileoverview An ESLint plugin provides autofix for some core rules. - * @author 唯然 - */ -"use strict"; - -const all = require("./configs/all"); -const recommended = require("./configs/recommended"); -const unsafe = require("./configs/unsafe"); -const rules = require("./rules"); - -module.exports = { - configs: { - all, - recommended, - unsafe - }, - rules -}; +/** + * @fileoverview An ESLint plugin provides autofix for some core rules. + * @author 唯然 + */ +"use strict"; + +const all = require("./configs/all"); +const recommended = require("./configs/recommended"); +const unsafe = require("./configs/unsafe"); +const rules = require("./rules"); + +const pkg = { + configs: { + all, + recommended, + unsafe + }, + rules +}; + +Object.assign(pkg.configs, { + "flat/all": { ...pkg.configs.all, plugins: { autofix: pkg }, rules: pkg.configs.all.rules }, + "flat/recommended": { ...pkg.configs.recommended, plugins: { autofix: pkg }, rules: pkg.configs.recommended.rules }, + "flat/unsafe": { ...pkg.configs.unsafe, plugins: { autofix: pkg }, rules: pkg.configs.unsafe.rules } +}); + +module.exports = pkg; diff --git a/packages/autofix/lib/rules.js b/packages/autofix/lib/rules.js index 0cb6297..fa3424f 100644 --- a/packages/autofix/lib/rules.js +++ b/packages/autofix/lib/rules.js @@ -11,7 +11,7 @@ const fs = require("fs"); const path = require("path"); -const eslintVersion = Number.parseInt(require("eslint/package.json").version, 10); +const {eslintVersion} = require("./utils.js") /** @@ -30,10 +30,10 @@ function loadRule(ruleName) { const allRules = {}; -// eslint v6 restructed its codebase +// eslint v6 restructured its codebase // TODO: this might be unreliable if (eslintVersion >= 8) { - const { builtinRules } = require("eslint/use-at-your-own-risk"); // eslint-disable-line node/no-missing-require + const { builtinRules } = require("eslint/use-at-your-own-risk"); for (const [ruleId, rule] of builtinRules) { if (rule.meta.fixable) { @@ -49,7 +49,7 @@ if (eslintVersion >= 8) { } } } else { - const builtin = require("eslint/lib/built-in-rules-index"); // eslint-disable-line node/no-missing-require + const builtin = require("eslint/lib/built-in-rules-index"); // eslint-disable-line n/no-missing-require Object.keys(builtin) .filter(rule => builtin[rule].meta.fixable) diff --git a/packages/autofix/lib/utils.js b/packages/autofix/lib/utils.js index 628e223..6a88783 100644 --- a/packages/autofix/lib/utils.js +++ b/packages/autofix/lib/utils.js @@ -1,15 +1,28 @@ -/** - * @fileoverview utils used by the rule fixers. - * @author 唯然 - */ -"use strict"; -const eslint = require("eslint"); -const linter = new eslint.Linter(); - -exports.getFixableRule = function(ruleName, recommended = false, fixable = "code") { - const rule = linter.getRules().get(ruleName); - - rule.meta.recommended = recommended; - rule.meta.fixable = fixable; - return rule; -}; +/** + * @fileoverview utils used by the rule fixers. + * @author 唯然 + */ +"use strict"; + +exports.eslintVersion = Number.parseInt(require("eslint/package.json").version, 10); + +// eslint v6 restructured its codebase +// TODO: this might be unreliable +if (exports.eslintVersion >= 8) { + const { builtinRules } = require("eslint/use-at-your-own-risk"); + exports.builtinRules = builtinRules; +} else if (exports.eslintVersion >= 6) { + const builtin = require("eslint/lib/rules"); + exports.builtinRules = builtin; +} else { + const builtin = require("eslint/lib/built-in-rules-index"); // eslint-disable-line n/no-missing-require + exports.builtinRules = builtin; +} + +exports.getFixableRule = function(ruleName, recommended = false, fixable = "code") { + const rule = exports.builtinRules[ruleName] || exports.builtinRules.get(ruleName); + + rule.meta.recommended = recommended; + rule.meta.fixable = fixable; + return rule; +}; diff --git a/packages/autofix/package.json b/packages/autofix/package.json index 8fddd69..d2dc2ad 100644 --- a/packages/autofix/package.json +++ b/packages/autofix/package.json @@ -32,7 +32,7 @@ "mocha": "^9.1.3" }, "peerDependencies": { - "eslint": ">= 5.12.1" + "eslint": ">=8" }, "keywords": [ "eslint plugin", diff --git a/packages/autofix/tests/lib/rules/no-caller.js b/packages/autofix/tests/lib/rules/no-caller.js index 4c66037..8d7f502 100644 --- a/packages/autofix/tests/lib/rules/no-caller.js +++ b/packages/autofix/tests/lib/rules/no-caller.js @@ -1,58 +1,57 @@ -/** - * @fileoverview Tests for rule no-caller. - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-caller"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ type: "MemberExpression" }]; - -ruleTester.run("no-caller", rule, { - valid: [ - "function foo() { foo(); }" - ], - invalid: [ - { - code: "function foo() { arguments.caller }", - output: null, - errors - }, - { - code: "arguments.callee", - output: null, - errors - }, - { - code: "var foo = function () { arguments.callee }", - output: null, - errors - }, - { - code: "var foo = () => { arguments.callee }", - parserOptions: { ecmaVersion: 6 }, - output: null, - errors - }, - { - code: "function foo() { arguments.callee }", - output: "function foo() { foo }", - errors - }, - { - code: "var foo = function foo() { arguments.callee }", - output: "var foo = function foo() { foo }", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-caller. + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-caller"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-caller", rule, { + valid: [ + "function foo() { foo(); }" + ], + invalid: [ + { + code: "function foo() { arguments.caller }", + output: null, + errors + }, + { + code: "arguments.callee", + output: null, + errors + }, + { + code: "var foo = function () { arguments.callee }", + output: null, + errors + }, + { + code: "var foo = () => { arguments.callee }", + output: null, + errors + }, + { + code: "function foo() { arguments.callee }", + output: "function foo() { foo }", + errors + }, + { + code: "var foo = function foo() { arguments.callee }", + output: "var foo = function foo() { foo }", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-console.js b/packages/autofix/tests/lib/rules/no-console.js index 5870fa4..0e97bc8 100644 --- a/packages/autofix/tests/lib/rules/no-console.js +++ b/packages/autofix/tests/lib/rules/no-console.js @@ -25,7 +25,7 @@ ruleTester.run("no-console", rule, { invalid: [ { code: "console.log", - output: "console.log", + output: null, errors: [{ messageId: "unexpected", type: "MemberExpression" }] }, { diff --git a/packages/autofix/tests/lib/rules/no-new-symbol.js b/packages/autofix/tests/lib/rules/no-new-symbol.js index b1fcac8..668dd99 100644 --- a/packages/autofix/tests/lib/rules/no-new-symbol.js +++ b/packages/autofix/tests/lib/rules/no-new-symbol.js @@ -1,32 +1,32 @@ -/** - * @fileoverview Tests for rule no-new-symbol - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-new-symbol"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester({ env: { es6: true } }); -const errors = [{ type: "Identifier" }]; - -ruleTester.run("no-new-symbol", rule, { - valid: [ - "Symbol('a')" - ], - invalid: [ - { - code: "new Symbol('a')", - output: "Symbol('a')", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-new-symbol + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-new-symbol"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-new-symbol", rule, { + valid: [ + "Symbol('a')" + ], + invalid: [ + { + code: "new Symbol('a')", + output: "Symbol('a')", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-proto.js b/packages/autofix/tests/lib/rules/no-proto.js index b6dbefe..d206253 100644 --- a/packages/autofix/tests/lib/rules/no-proto.js +++ b/packages/autofix/tests/lib/rules/no-proto.js @@ -1,37 +1,37 @@ -/** - * @fileoverview Tests for rule no-proto. - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-proto"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ type: "MemberExpression" }]; - -ruleTester.run("no-proto", rule, { - valid: [ - "Object.getPrototypeOf(obj)" - ], - invalid: [ - { - code: "obj.__proto__", - output: "Object.getPrototypeOf(obj)", - errors - }, - { - code: "obj['__proto__']", - output: "Object.getPrototypeOf(obj)", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-proto. + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-proto"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-proto", rule, { + valid: [ + "Object.getPrototypeOf(obj)" + ], + invalid: [ + { + code: "obj.__proto__", + output: "Object.getPrototypeOf(obj)", + errors + }, + { + code: "obj['__proto__']", + output: "Object.getPrototypeOf(obj)", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-prototype-builtins.js b/packages/autofix/tests/lib/rules/no-prototype-builtins.js index 0057649..12c79b7 100644 --- a/packages/autofix/tests/lib/rules/no-prototype-builtins.js +++ b/packages/autofix/tests/lib/rules/no-prototype-builtins.js @@ -1,47 +1,47 @@ -/** - * @fileoverview Tests for rule no-prototype-builtins - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-prototype-builtins"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ type: "CallExpression" }]; - -ruleTester.run("no-prototype-builtins", rule, { - valid: [ - "Object.prototype.hasOwnProperty.call(foo, \"bar\")" - ], - invalid: [ - { - code: "foo.hasOwnProperty('bar')", - output: "Object.prototype.hasOwnProperty.call(foo, 'bar')", - errors - }, - { - code: "foo.bar.hasOwnProperty('baz')", - output: "Object.prototype.hasOwnProperty.call(foo.bar, 'baz')", - errors - }, - { - code: "foo.isPrototypeOf('bar')", - output: "Object.prototype.isPrototypeOf.call(foo, 'bar')", - errors - }, - { - code: "foo.propertyIsEnumerable('bar')", - output: "Object.prototype.propertyIsEnumerable.call(foo, 'bar')", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-prototype-builtins + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-prototype-builtins"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-prototype-builtins", rule, { + valid: [ + "Object.prototype.hasOwnProperty.call(foo, \"bar\")" + ], + invalid: [ + { + code: "foo.hasOwnProperty('bar')", + output: "Object.prototype.hasOwnProperty.call(foo, 'bar')", + errors + }, + { + code: "foo.bar.hasOwnProperty('baz')", + output: "Object.prototype.hasOwnProperty.call(foo.bar, 'baz')", + errors + }, + { + code: "foo.isPrototypeOf('bar')", + output: "Object.prototype.isPrototypeOf.call(foo, 'bar')", + errors + }, + { + code: "foo.propertyIsEnumerable('bar')", + output: "Object.prototype.propertyIsEnumerable.call(foo, 'bar')", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-throw-literal.js b/packages/autofix/tests/lib/rules/no-throw-literal.js index f1c5584..1ccaeb5 100644 --- a/packages/autofix/tests/lib/rules/no-throw-literal.js +++ b/packages/autofix/tests/lib/rules/no-throw-literal.js @@ -1,43 +1,43 @@ -/** - * @fileoverview Tests for rule no-throw-literal. - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-throw-literal"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ type: "ThrowStatement" }]; - -ruleTester.run("no-throw-literal", rule, { - valid: [ - "throw new Error()", - "throw error" - ], - invalid: [ - { - code: "throw 'error'", - output: "throw new Error('error');", - errors - }, - { - code: "throw ''", - output: "throw new Error('');", - errors - }, - { - code: "throw 0", - output: "throw new Error(0);", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-throw-literal. + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-throw-literal"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-throw-literal", rule, { + valid: [ + "throw new Error()", + "throw error" + ], + invalid: [ + { + code: "throw 'error'", + output: "throw new Error('error');", + errors + }, + { + code: "throw ''", + output: "throw new Error('');", + errors + }, + { + code: "throw 0", + output: "throw new Error(0);", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-unused-vars.js b/packages/autofix/tests/lib/rules/no-unused-vars.js index 18e98a1..91c7975 100644 --- a/packages/autofix/tests/lib/rules/no-unused-vars.js +++ b/packages/autofix/tests/lib/rules/no-unused-vars.js @@ -15,13 +15,12 @@ const RuleTester = require("eslint").RuleTester; // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 9 } }); +const ruleTester = new RuleTester(); ruleTester.run("no-unused-vars", rule, { valid: [ { code: "import 'm'", - parserOptions: { sourceType: "module", ecmaVersion: 6 } }, // https://github.com/aladdin-add/eslint-plugin/issues/58 @@ -36,178 +35,158 @@ ruleTester.run("no-unused-vars", rule, { invalid: [ { code: "import * as m from 'm'", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import m from 'm'", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import {m} from 'm'", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import {m1 as m2} from 'm'", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import m, {b} from 'm'; b;", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "import {b} from 'm'; b;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import {a, b} from 'm'; b;", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "import { b} from 'm'; b;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import {a1 as a2, b} from 'm'; b;", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "import { b} from 'm'; b;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import {a, b} from 'm'; a;", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "import {a} from 'm'; a;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "import m, {a} from 'm'; m;", - parserOptions: { sourceType: "module", ecmaVersion: 6 }, output: "import m from 'm'; m;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = undefined", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = null", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = 'b'", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = this", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = `template`", - parserOptions: { ecmaVersion: 6 }, output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = this.value", output: "", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b = c", output: null, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b = c()", output: null, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = `template-${value}`", - parserOptions: { ecmaVersion: 6 }, output: null, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b()", output: null, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = (b()).c", output: null, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var [a] = c", output: "var [] = c", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var [a, b] = c", output: "var [, ] = c", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }, { type: "Identifier" }] + errors: 2 }, { code: "var [a, b] = c; a;", output: "var [a, ] = c; a;", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var [a, b] = c; b;", output: "var [, b] = c; b;", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b, c = d; c;", output: "var c = d; c;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "var a = b, c = d; a;", output: "var a = b ; a;", - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {...a} = b", output: "let {} = b", - parserOptions: { ecmaVersion: 2018 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "function foo(...args){}", output: null, - parserOptions: { ecmaVersion: 2018 }, - errors: [{ type: "Identifier" }, { type: "Identifier" }] + errors: 2 }, { code: "function foo(a, b, c){console.log(b);}; foo(1, 2, 3);", output: "function foo(a, b ){console.log(b);}; foo(1, 2, 3);", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" } - ], + errors:1, options: [{ args: "after-used", argsIgnorePattern: "^_" @@ -216,10 +195,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "const foo = function(a, b, c) {console.log(b);}; foo(1, 2, 3);", output: "const foo = function(a, b ) {console.log(b);}; foo(1, 2, 3);", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" } - ], + errors:1, options: [{ args: "after-used", argsIgnorePattern: "^_" @@ -228,10 +204,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "const foo = (a, b, c) => {console.log(b);}; foo(1, 2, 3);", output: "const foo = (a, b ) => {console.log(b);}; foo(1, 2, 3);", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" } - ], + errors:1, options: [{ args: "after-used", argsIgnorePattern: "^_" @@ -240,10 +213,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "const foo = (a) => {}; foo();", output: "const foo = () => {}; foo();", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" } - ], + errors:1, options: [{ args: "after-used", argsIgnorePattern: "^_" @@ -252,10 +222,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "const foo = a => {}; foo();", output: "const foo = () => {}; foo();", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" } - ], + errors:1, options: [{ args: "after-used", argsIgnorePattern: "^_" @@ -264,11 +231,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "function foo(a, b, c){console.log(b);}; foo(1, 2, 3);", output: "function foo(_a, b, _c){console.log(b);}; foo(1, 2, 3);", - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" }, - { type: "Identifier" } - ], + errors: 2, options: [{ args: "all", argsIgnorePattern: "^_" @@ -277,11 +240,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "function foo(a, b, c){console.log(b);}; foo(1, 2, 3);", output: null, - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" }, - { type: "Identifier" } - ], + errors: 2, options: [{ args: "all", argsIgnorePattern: "_$" @@ -290,11 +249,7 @@ ruleTester.run("no-unused-vars", rule, { { code: "function foo(a, b, c){console.log(b);}; foo(1, 2, 3);", output: null, - parserOptions: { ecmaVersion: 2018 }, - errors: [ - { type: "Identifier" }, - { type: "Identifier" } - ], + errors: 2, options: [{ args: "all" }] @@ -302,44 +257,37 @@ ruleTester.run("no-unused-vars", rule, { { code: "let {a} = b", output: "let {} = b", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a,} = b", output: "let {} = b", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a1: a2} = b", output: "let {} = b", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a = b} = c", output: "let {} = c", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a = b()} = c", output: null, - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a, b} = c; b;", output: "let { b} = c; b;", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 }, { code: "let {a, b} = c; a;", output: "let {a } = c; a;", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "Identifier" }] + errors: 1 } ] }); diff --git a/packages/autofix/tests/lib/rules/no-useless-catch.js b/packages/autofix/tests/lib/rules/no-useless-catch.js index 62f389b..f5269ae 100644 --- a/packages/autofix/tests/lib/rules/no-useless-catch.js +++ b/packages/autofix/tests/lib/rules/no-useless-catch.js @@ -1,47 +1,46 @@ -/** - * @fileoverview Tests for rule no-useless-catch. - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-useless-catch"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); - -ruleTester.run("no-useless-catch", rule, { - valid: [ - "try {} catch (e) {}" - ], - invalid: [ - { - code: "try {} catch (e) { throw e }", - output: "{}", - errors: [{ type: "TryStatement" }] - }, - { - code: "try { fn() } catch (e) { throw e }", - output: "{ fn() }", - errors: [{ type: "TryStatement" }] - }, - { - code: "let a; try { let a } catch (e) { throw e };", - output: "let a; { let a };", - parserOptions: { ecmaVersion: 6 }, - errors: [{ type: "TryStatement" }] - }, - { - code: "try {} catch (e) { throw e } finally {}", - output: "try {} finally {}", - errors: [{ type: "CatchClause" }] - } - ] -}); +/** + * @fileoverview Tests for rule no-useless-catch. + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-useless-catch"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("no-useless-catch", rule, { + valid: [ + "try {} catch (e) {}" + ], + invalid: [ + { + code: "try {} catch (e) { throw e }", + output: "{}", + errors: 1 + }, + { + code: "try { fn() } catch (e) { throw e }", + output: "{ fn() }", + errors: 1 + }, + { + code: "let a; try { let a } catch (e) { throw e };", + output: "let a; { let a };", + errors: 1 + }, + { + code: "try {} catch (e) { throw e } finally {}", + output: "try {} finally {}", + errors:1 + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/no-useless-concat.js b/packages/autofix/tests/lib/rules/no-useless-concat.js index f2cc681..cbc4349 100644 --- a/packages/autofix/tests/lib/rules/no-useless-concat.js +++ b/packages/autofix/tests/lib/rules/no-useless-concat.js @@ -1,33 +1,33 @@ -/** - * @fileoverview Tests for rule no-useless-concat - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-useless-concat"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ type: "BinaryExpression" }]; - -ruleTester.run("no-useless-concat", rule, { - valid: [ - "2 + 3", - "2 + '3'" - ], - invalid: [ - { - code: "'a' + 'b'", - output: "\"ab\"", - errors - } - ] -}); +/** + * @fileoverview Tests for rule no-useless-concat + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-useless-concat"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = 1; + +ruleTester.run("no-useless-concat", rule, { + valid: [ + "2 + 3", + "2 + '3'" + ], + invalid: [ + { + code: "'a' + 'b'", + output: "\"ab\"", + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/prefer-spread.js b/packages/autofix/tests/lib/rules/prefer-spread.js index eae1cb7..756cc6d 100644 --- a/packages/autofix/tests/lib/rules/prefer-spread.js +++ b/packages/autofix/tests/lib/rules/prefer-spread.js @@ -1,95 +1,95 @@ -/** - * @fileoverview Tests for prefer-spread rule. - * @author Toru Nagashima - * source: https://github.com/eslint/eslint/blob/master/tests/lib/rules/prefer-spread.js - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/prefer-spread"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const errors = [{ message: "Use the spread operator instead of '.apply()'.", type: "CallExpression" }]; - -const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); - -ruleTester.run("prefer-spread", rule, { - valid: [ - "foo.apply(obj, args);", - "obj.foo.apply(null, args);", - "obj.foo.apply(otherObj, args);", - "a.b(x, y).c.foo.apply(a.b(x, z).c, args);", - "a.b.foo.apply(a.b.c, args);", - - // ignores non variadic. - "foo.apply(undefined, [1, 2]);", - "foo.apply(null, [1, 2]);", - "obj.foo.apply(obj, [1, 2]);", - - // ignores computed property. - "var apply; foo[apply](null, args);", - - // ignores incomplete things. - "foo.apply();", - "obj.foo.apply();", - "obj.foo.apply(obj, ...args)" - ], - invalid: [ - { - code: "foo.apply(undefined, args);", - output: "foo(...args);", - errors - }, - { - code: "foo.apply(void 0, args);", - output: "foo(...args);", - errors - }, - { - code: "foo.apply(null, args);", - output: "foo(...args);", - errors - }, - { - code: "obj.foo.apply(obj, args);", - output: "obj.foo(...args);", - errors - }, - { - - // Not fixed: a.b.c might activate getters - code: "a.b.c.foo.apply(a.b.c, args);", - output: null, - errors - }, - { - - // Not fixed: a.b(x, y).c might activate getters - code: "a.b(x, y).c.foo.apply(a.b(x, y).c, args);", - output: null, - errors - }, - { - - // Not fixed (not an identifier) - code: "[].concat.apply([ ], args);", - output: null, - errors - }, - { - - // Not fixed (not an identifier) - code: "[].concat.apply([\n/*empty*/\n], args);", - output: null, - errors - } - ] -}); +/** + * @fileoverview Tests for prefer-spread rule. + * @author Toru Nagashima + * source: https://github.com/eslint/eslint/blob/master/tests/lib/rules/prefer-spread.js + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/prefer-spread"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const errors = [{ message: "Use the spread operator instead of '.apply()'.", type: "CallExpression" }]; + +const ruleTester = new RuleTester(); + +ruleTester.run("prefer-spread", rule, { + valid: [ + "foo.apply(obj, args);", + "obj.foo.apply(null, args);", + "obj.foo.apply(otherObj, args);", + "a.b(x, y).c.foo.apply(a.b(x, z).c, args);", + "a.b.foo.apply(a.b.c, args);", + + // ignores non variadic. + "foo.apply(undefined, [1, 2]);", + "foo.apply(null, [1, 2]);", + "obj.foo.apply(obj, [1, 2]);", + + // ignores computed property. + "var apply; foo[apply](null, args);", + + // ignores incomplete things. + "foo.apply();", + "obj.foo.apply();", + "obj.foo.apply(obj, ...args)" + ], + invalid: [ + { + code: "foo.apply(undefined, args);", + output: "foo(...args);", + errors + }, + { + code: "foo.apply(void 0, args);", + output: "foo(...args);", + errors + }, + { + code: "foo.apply(null, args);", + output: "foo(...args);", + errors + }, + { + code: "obj.foo.apply(obj, args);", + output: "obj.foo(...args);", + errors + }, + { + + // Not fixed: a.b.c might activate getters + code: "a.b.c.foo.apply(a.b.c, args);", + output: null, + errors + }, + { + + // Not fixed: a.b(x, y).c might activate getters + code: "a.b(x, y).c.foo.apply(a.b(x, y).c, args);", + output: null, + errors + }, + { + + // Not fixed (not an identifier) + code: "[].concat.apply([ ], args);", + output: null, + errors + }, + { + + // Not fixed (not an identifier) + code: "[].concat.apply([\n/*empty*/\n], args);", + output: null, + errors + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/radix.js b/packages/autofix/tests/lib/rules/radix.js index 91dd56c..a8db766 100644 --- a/packages/autofix/tests/lib/rules/radix.js +++ b/packages/autofix/tests/lib/rules/radix.js @@ -1,43 +1,43 @@ -/** - * @fileoverview Tests for rule radix - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/radix"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); - -ruleTester.run("radix", rule, { - valid: [ - "parseInt(a, 10)", - { code: "parseInt(a)", options: ["as-needed"] } - ], - invalid: [ - { - code: "parseInt(a)", - output: "parseInt(a, 10)", - errors: [{ type: "CallExpression" }] - }, - { - code: "parseInt(a, 10)", - options: ["as-needed"], - output: "parseInt(a)", - errors: [{ type: "CallExpression" }] - }, - { - code: "parseInt(a, '10')", - output: null, - errors: [{ type: "CallExpression" }] - } - ] -}); +/** + * @fileoverview Tests for rule radix + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/radix"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("radix", rule, { + valid: [ + "parseInt(a, 10)", + { code: "parseInt(a)", options: ["as-needed"] } + ], + invalid: [ + { + code: "parseInt(a)", + output: "parseInt(a, 10)", + errors: 1 + }, + { + code: "parseInt(a, 10)", + options: ["as-needed"], + output: "parseInt(a)", + errors: 1 + }, + { + code: "parseInt(a, '10')", + output: null, + errors: 1 + } + ] +}); diff --git a/packages/autofix/tests/lib/rules/valid-typeof.js b/packages/autofix/tests/lib/rules/valid-typeof.js index 40a6096..3aff617 100644 --- a/packages/autofix/tests/lib/rules/valid-typeof.js +++ b/packages/autofix/tests/lib/rules/valid-typeof.js @@ -1,63 +1,62 @@ -/** - * @fileoverview Tests for rule valid-typeof - * @author Pig Fang - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/valid-typeof"); -const RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const errors = [{ messageId: "invalidValue", type: "Literal" }]; - -ruleTester.run("valid-typeof", rule, { - valid: [ - "typeof a === 'string'" - ], - invalid: [ - { - code: "typeof a === 'strnig'", - output: "typeof a === \"string\"", - errors - }, - { - code: "'strnig' === typeof a", - output: "\"string\" === typeof a", - errors - }, - { - code: "typeof a === `strnig`", - parserOptions: { ecmaVersion: 6 }, - output: "typeof a === \"string\"", - errors: [{ messageId: "invalidValue", type: "TemplateLiteral" }] - }, - { - code: "typeof a === 'nunber'", - output: "typeof a === \"number\"", - errors - }, - { - code: "typeof a === 'fucntion'", - output: "typeof a === \"function\"", - errors - }, - { - code: "typeof a === 'undefimed'", - output: "typeof a === \"undefined\"", - errors - }, - { - code: "typeof a === 'biilean'", - output: "typeof a === \"boolean\"", - errors - } - ] -}); +/** + * @fileoverview Tests for rule valid-typeof + * @author Pig Fang + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/valid-typeof"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const errors = [{ messageId: "invalidValue", type: "Literal" }]; + +ruleTester.run("valid-typeof", rule, { + valid: [ + "typeof a === 'string'" + ], + invalid: [ + { + code: "typeof a === 'strnig'", + output: "typeof a === \"string\"", + errors + }, + { + code: "'strnig' === typeof a", + output: "\"string\" === typeof a", + errors + }, + { + code: "typeof a === `strnig`", + output: "typeof a === \"string\"", + errors: [{ messageId: "invalidValue", type: "TemplateLiteral" }] + }, + { + code: "typeof a === 'nunber'", + output: "typeof a === \"number\"", + errors + }, + { + code: "typeof a === 'fucntion'", + output: "typeof a === \"function\"", + errors + }, + { + code: "typeof a === 'undefimed'", + output: "typeof a === \"undefined\"", + errors + }, + { + code: "typeof a === 'biilean'", + output: "typeof a === \"boolean\"", + errors + } + ] +}); diff --git a/packages/autofix/tools/eslint-rules/rule-def-format.js b/packages/autofix/tools/eslint-rules/rule-def-format.js deleted file mode 100644 index f701f50..0000000 --- a/packages/autofix/tools/eslint-rules/rule-def-format.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @fileoverview Rule definition of "rule-def-format" - * @author Pig Fang - */ -"use strict"; - -const path = require("path"); - -module.exports = { - meta: { - fixable: "code", - type: "problem", - schema: [] - }, - create: context => ({ - CallExpression: node => { - if (node.callee.type !== "MemberExpression") { - return; - } - - const { callee: { object: { name: objectName }, property: { name: propertyName } }, arguments: args } = node; - const sourceCode = context.getSourceCode(); - - if (objectName === "utils" && propertyName === "getFixableRule") { - const arg0 = args[0]; - const ruleName = path.basename(context.getFilename(), ".js"); - - if (arg0.value !== ruleName) { - context.report({ - node: arg0, - message: `Rule name should be '${ruleName}'`, - fix: fixer => fixer.replaceText(arg0, `"${ruleName}"`) - }); - } - return; - } - - if (objectName === "ruleComposer") { - if (propertyName === "mapReports") { - const [, predicate] = args; - - if (predicate.type === "ArrowFunctionExpression" || predicate.type === "FunctionExpression") { - if (predicate.body.type !== "BlockStatement") { - context.report({ - node: predicate.body, - message: "Body of predicate should be a block statement." - }); - return; - } - const param0 = predicate.params[0].name; - - const statements = predicate.body.body; - - const returnStatement = statements.find(stmt => stmt.type === "ReturnStatement"); - - if (!returnStatement) { - context.report({ - node: predicate, - message: "Should returning the problem object.", - fix: fixer => { - const lastToken = sourceCode.getLastToken(predicate); - - return fixer.insertTextBefore(lastToken, `\nreturn ${param0};\n`); - } - }); - } else if (returnStatement.argument.name !== param0) { - context.report({ - node: predicate, - message: "Should returning the problem object.", - fix: fixer => fixer.replaceText(returnStatement, `return ${param0};`) - }); - } - } - } else if (propertyName === "joinReports" && args[0].type !== "ArrayExpression") { - context.report({ - node: args[0], - message: "The first argument of 'joinReports' should be an array." - }); - } - } - } - }) -}; diff --git a/packages/no-autofix/lib/index.js b/packages/no-autofix/lib/index.js index 6c09a56..c2a6a14 100644 --- a/packages/no-autofix/lib/index.js +++ b/packages/no-autofix/lib/index.js @@ -7,9 +7,15 @@ const all = require("./configs/all"); const rules = require("./rules"); -module.exports = { +const pkg = { configs: { all }, rules }; + +Object.assign(pkg.configs, { + "flat/all": { plugins: { "no-autofix": pkg }, rules: pkg.configs.all.rules } +}); + +module.exports = pkg; diff --git a/packages/no-autofix/lib/rules.js b/packages/no-autofix/lib/rules.js index 703533c..03778db 100644 --- a/packages/no-autofix/lib/rules.js +++ b/packages/no-autofix/lib/rules.js @@ -1,5 +1,5 @@ /** - * @fileoverview expored all rules in the plugin. + * @fileoverview export all rules in the plugin. * @author 唯然 */ @@ -32,7 +32,7 @@ if (eslintVersion >= 8) { builtinRules[ruleId] = rule; } } else { - const builtin = require("eslint/lib/built-in-rules-index"); // eslint-disable-line node/no-missing-require + const builtin = require("eslint/lib/built-in-rules-index"); // eslint-disable-line n/no-missing-require Object.keys(builtin) .reduce((acc, cur) => { @@ -43,7 +43,7 @@ if (eslintVersion >= 8) { Object.keys(builtinRules).reduce((acc, cur) => { - const rule = linter.getRules().get(cur); + const rule = builtinRules[cur] || builtinRules.get(cur); acc[cur] = getNonFixableRule(rule); return acc; diff --git a/packages/no-autofix/package.json b/packages/no-autofix/package.json index bc3d289..367f6ef 100644 --- a/packages/no-autofix/package.json +++ b/packages/no-autofix/package.json @@ -22,7 +22,7 @@ "mocha": "^8.2.1" }, "peerDependencies": { - "eslint": ">= 5.12.1" + "eslint": ">=8" }, "keywords": [ "eslint plugin", diff --git a/packages/no-autofix/tests/lib/rules/quotes.js b/packages/no-autofix/tests/lib/rules/quotes.js index 52aae65..c32ebb4 100644 --- a/packages/no-autofix/tests/lib/rules/quotes.js +++ b/packages/no-autofix/tests/lib/rules/quotes.js @@ -7,7 +7,7 @@ const rule = require("../../../lib/rules").quotes, RuleTester = require("eslint").RuleTester; -const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 9 } }); +const ruleTester = new RuleTester({ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }); ruleTester.run("quotes", rule, { valid: [ @@ -18,58 +18,57 @@ ruleTester.run("quotes", rule, { { code: "var foo = 1;", options: ["double"] }, { code: "var foo = \"'\";", options: ["single", { avoidEscape: true }] }, { code: "var foo = '\"';", options: ["double", { avoidEscape: true }] }, - { code: "var foo = <>Hello world;", options: ["single"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo = <>Hello world;", options: ["double"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo = <>Hello world;", options: ["double", { avoidEscape: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo = <>Hello world;", options: ["backtick"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo =
Hello world
;", options: ["single"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo =
;", options: ["single"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo =
Hello world
;", options: ["double"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo =
Hello world
;", options: ["double", { avoidEscape: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo = `bar`;", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `bar 'baz'`;", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `bar \"baz\"`;", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, + { code: "var foo = <>Hello world;", options: ["single"], }, + { code: "var foo = <>Hello world;", options: ["double"], }, + { code: "var foo = <>Hello world;", options: ["double", { avoidEscape: true }], }, + { code: "var foo = <>Hello world;", options: ["backtick"], }, + { code: "var foo =
Hello world
;", options: ["single"], }, + { code: "var foo =
;", options: ["single"], }, + { code: "var foo =
Hello world
;", options: ["double"], }, + { code: "var foo =
Hello world
;", options: ["double", { avoidEscape: true }], }, + { code: "var foo = `bar`;", options: ["backtick"], }, + { code: "var foo = `bar 'baz'`;", options: ["backtick"], }, + { code: "var foo = `bar \"baz\"`;", options: ["backtick"], }, { code: "var foo = 1;", options: ["backtick"] }, { code: "var foo = \"a string containing `backtick` quotes\";", options: ["backtick", { avoidEscape: true }] }, - { code: "var foo =
;", options: ["backtick"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, - { code: "var foo =
Hello world
;", options: ["backtick"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { jsx: true } } }, + { code: "var foo =
;", options: ["backtick"], }, + { code: "var foo =
Hello world
;", options: ["backtick"], }, // Backticks are only okay if they have substitutions, contain a line break, or are tagged - { code: "var foo = `back\ntick`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `back\rtick`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `back\u2028tick`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `back\u2029tick`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, + { code: "var foo = `back\ntick`;", options: ["single"], }, + { code: "var foo = `back\rtick`;", options: ["single"], }, + { code: "var foo = `back\u2028tick`;", options: ["single"], }, + { code: "var foo = `back\u2029tick`;", options: ["single"], }, { code: "var foo = `back\\\\\ntick`;", // 2 backslashes followed by a newline options: ["single"], - parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `back\\\\\\\\\ntick`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `\n`;", options: ["single"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `back${x}tick`;", options: ["double"], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = tag`backtick`;", options: ["double"], parserOptions: { ecmaVersion: 6 } }, + { code: "var foo = `back\\\\\\\\\ntick`;", options: ["single"], }, + { code: "var foo = `\n`;", options: ["single"], }, + { code: "var foo = `back${x}tick`;", options: ["double"], }, + { code: "var foo = tag`backtick`;", options: ["double"], }, // Backticks are also okay if allowTemplateLiterals - { code: "var foo = `bar 'foo' baz` + 'bar';", options: ["single", { allowTemplateLiterals: true }], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `bar 'foo' baz` + \"bar\";", options: ["double", { allowTemplateLiterals: true }], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = `bar 'foo' baz` + `bar`;", options: ["backtick", { allowTemplateLiterals: true }], parserOptions: { ecmaVersion: 6 } }, + { code: "var foo = `bar 'foo' baz` + 'bar';", options: ["single", { allowTemplateLiterals: true }], }, + { code: "var foo = `bar 'foo' baz` + \"bar\";", options: ["double", { allowTemplateLiterals: true }], }, + { code: "var foo = `bar 'foo' baz` + `bar`;", options: ["backtick", { allowTemplateLiterals: true }], }, // `backtick` should not warn the directive prologues. - { code: "\"use strict\"; var foo = `backtick`;", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "\"use strict\"; 'use strong'; \"use asm\"; var foo = `backtick`;", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "function foo() { \"use strict\"; \"use strong\"; \"use asm\"; var foo = `backtick`; }", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "(function() { 'use strict'; 'use strong'; 'use asm'; var foo = `backtick`; })();", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "(() => { \"use strict\"; \"use strong\"; \"use asm\"; var foo = `backtick`; })();", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, + { code: "\"use strict\"; var foo = `backtick`;", options: ["backtick"], }, + { code: "\"use strict\"; 'use strong'; \"use asm\"; var foo = `backtick`;", options: ["backtick"], }, + { code: "function foo() { \"use strict\"; \"use strong\"; \"use asm\"; var foo = `backtick`; }", options: ["backtick"], }, + { code: "(function() { 'use strict'; 'use strong'; 'use asm'; var foo = `backtick`; })();", options: ["backtick"], }, + { code: "(() => { \"use strict\"; \"use strong\"; \"use asm\"; var foo = `backtick`; })();", options: ["backtick"], }, // `backtick` should not warn import/export sources. - { code: "import \"a\"; import 'b';", options: ["backtick"], parserOptions: { sourceType: "module" } }, - { code: "import a from \"a\"; import b from 'b';", options: ["backtick"], parserOptions: { sourceType: "module" } }, - { code: "export * from \"a\"; export * from 'b';", options: ["backtick"], parserOptions: { sourceType: "module" } }, + { code: "import \"a\"; import 'b';", options: ["backtick"], }, + { code: "import a from \"a\"; import b from 'b';", options: ["backtick"], }, + { code: "export * from \"a\"; export * from 'b';", options: ["backtick"], }, // `backtick` should not warn property/method names (not computed). - { code: "var obj = {\"key0\": 0, 'key1': 1};", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "class Foo { 'bar'(){} }", options: ["backtick"], parserOptions: { ecmaVersion: 6 } }, - { code: "class Foo { static ''(){} }", options: ["backtick"], parserOptions: { ecmaVersion: 6 } } + { code: "var obj = {\"key0\": 0, 'key1': 1};", options: ["backtick"], }, + { code: "class Foo { 'bar'(){} }", options: ["backtick"], }, + { code: "class Foo { static ''(){} }", options: ["backtick"], } ], invalid: [ { @@ -87,9 +86,6 @@ ruleTester.run("quotes", rule, { code: "var foo = `bar`;", output: null, options: ["single"], - parserOptions: { - ecmaVersion: 6 - }, errors: [{ message: "Strings must use singlequote.", type: "TemplateLiteral" }] }, { @@ -116,9 +112,6 @@ ruleTester.run("quotes", rule, { code: "var foo = `bar`;", output: null, options: ["double"], - parserOptions: { - ecmaVersion: 6 - }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { @@ -187,21 +180,18 @@ ruleTester.run("quotes", rule, { code: "var foo = `backtick`; \"use strict\";", output: null, options: ["backtick"], - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "{ \"use strict\"; var foo = `backtick`; }", output: null, options: ["backtick"], - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "if (1) { \"use strict\"; var foo = `backtick`; }", output: null, options: ["backtick"], - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, @@ -210,7 +200,6 @@ ruleTester.run("quotes", rule, { code: "var obj = {[\"key0\"]: 0, ['key1']: 1};", output: null, options: ["backtick"], - parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Strings must use backtick.", type: "Literal" }, { message: "Strings must use backtick.", type: "Literal" } @@ -220,7 +209,6 @@ ruleTester.run("quotes", rule, { code: "class Foo { ['a'](){} static ['b'](){} }", output: null, options: ["backtick"], - parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Strings must use backtick.", type: "Literal" }, { message: "Strings must use backtick.", type: "Literal" } @@ -232,7 +220,6 @@ ruleTester.run("quotes", rule, { code: "
", output: null, options: ["single"], - parserOptions: { ecmaFeatures: { jsx: true } }, errors: [ { message: "Strings must use singlequote.", type: "Literal" } ] @@ -241,7 +228,6 @@ ruleTester.run("quotes", rule, { code: "
", output: null, options: ["double"], - parserOptions: { ecmaFeatures: { jsx: true } }, errors: [ { message: "Strings must use doublequote.", type: "Literal" } ] @@ -250,7 +236,6 @@ ruleTester.run("quotes", rule, { code: "
", output: null, options: ["backtick"], - parserOptions: { ecmaFeatures: { jsx: true } }, errors: [ { message: "Strings must use backtick.", type: "Literal" } ] @@ -260,37 +245,31 @@ ruleTester.run("quotes", rule, { { code: "`use strict`;", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "function foo() { `use strict`; foo(); }", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "foo = function() { `use strict`; foo(); }", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "() => { `use strict`; foo(); }", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "() => { foo(); `use strict`; }", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "foo(); `use strict`;", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, @@ -298,25 +277,21 @@ ruleTester.run("quotes", rule, { { code: "var foo = `foo\\nbar`;", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "var foo = `foo\\\nbar`;", // 1 backslash followed by a newline output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "var foo = `foo\\\\\\\nbar`;", // 3 backslashes followed by a newline output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral" }] }, { code: "````", output: null, - parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Strings must use doublequote.", type: "TemplateLiteral", line: 1, column: 1 }] } ] diff --git a/packages/web/lib/rules/no-alert.js b/packages/web/lib/rules/no-alert.js index 92c6341..1d3a41a 100644 --- a/packages/web/lib/rules/no-alert.js +++ b/packages/web/lib/rules/no-alert.js @@ -1,127 +1,127 @@ -/** - * @fileoverview Rule to flag use of alert, confirm, prompt - * @author Nicholas C. Zakas - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const getPropertyName = require("../utils").getStaticPropertyName; - -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -/** - * Checks if the given name is a prohibited identifier. - * @param {string} name The name to check - * @returns {boolean} Whether or not the name is prohibited. - */ -function isProhibitedIdentifier(name) { - return /^(alert|confirm|prompt)$/u.test(name); -} - -/** - * Finds the eslint-scope reference in the given scope. - * @param {Object} scope The scope to search. - * @param {ASTNode} node The identifier node. - * @returns {Reference|null} Returns the found reference or null if none were found. - */ -function findReference(scope, node) { - const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] && - reference.identifier.range[1] === node.range[1]); - - if (references.length === 1) { - return references[0]; - } - return null; -} - -/** - * Checks if the given identifier node is shadowed in the given scope. - * @param {Object} scope The current scope. - * @param {string} node The identifier node to check - * @returns {boolean} Whether or not the name is shadowed. - */ -function isShadowed(scope, node) { - const reference = findReference(scope, node); - - return reference && reference.resolved && reference.resolved.defs.length > 0; -} - -/** - * Checks if the given identifier node is a ThisExpression in the global scope or the global window property. - * @param {Object} scope The current scope. - * @param {string} node The identifier node to check - * @returns {boolean} Whether or not the node is a reference to the global object. - */ -function isGlobalThisReferenceOrGlobalWindow(scope, node) { - if (scope.type === "global" && node.type === "ThisExpression") { - return true; - } - if (node.name === "window") { - return !isShadowed(scope, node); - } - - return false; -} - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -module.exports = { - meta: { - type: "suggestion", - - docs: { - description: "disallow the use of `alert`, `confirm`, and `prompt`", - category: "Best Practices", - recommended: false, - url: "https://eslint.org/docs/rules/no-alert" - }, - - schema: [], - - messages: { - unexpected: "Unexpected {{name}}." - } - }, - - create(context) { - return { - CallExpression(node) { - const callee = node.callee, - currentScope = context.getScope(); - - // without window. - if (callee.type === "Identifier") { - const name = callee.name; - - if (!isShadowed(currentScope, callee) && isProhibitedIdentifier(callee.name)) { - context.report({ - node, - messageId: "unexpected", - data: { name } - }); - } - - } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, callee.object)) { - const name = getPropertyName(callee); - - if (isProhibitedIdentifier(name)) { - context.report({ - node, - messageId: "unexpected", - data: { name } - }); - } - } - - } - }; - - } -}; +/** + * @fileoverview Rule to flag use of alert, confirm, prompt + * @author Nicholas C. Zakas + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const getPropertyName = require("../utils").getStaticPropertyName; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Checks if the given name is a prohibited identifier. + * @param {string} name The name to check + * @returns {boolean} Whether or not the name is prohibited. + */ +function isProhibitedIdentifier(name) { + return /^(alert|confirm|prompt)$/u.test(name); +} + +/** + * Finds the eslint-scope reference in the given scope. + * @param {Object} scope The scope to search. + * @param {ASTNode} node The identifier node. + * @returns {Reference|null} Returns the found reference or null if none were found. + */ +function findReference(scope, node) { + const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] && + reference.identifier.range[1] === node.range[1]); + + if (references.length === 1) { + return references[0]; + } + return null; +} + +/** + * Checks if the given identifier node is shadowed in the given scope. + * @param {Object} scope The current scope. + * @param {string} node The identifier node to check + * @returns {boolean} Whether or not the name is shadowed. + */ +function isShadowed(scope, node) { + const reference = findReference(scope, node); + + return reference && reference.resolved && reference.resolved.defs.length > 0; +} + +/** + * Checks if the given identifier node is a ThisExpression in the global scope or the global window property. + * @param {Object} scope The current scope. + * @param {string} node The identifier node to check + * @returns {boolean} Whether or not the node is a reference to the global object. + */ +function isGlobalThisReferenceOrGlobalWindow(scope, node) { + if (scope.type === "global" && node.type === "ThisExpression") { + return true; + } + if (node.name === "window") { + return !isShadowed(scope, node); + } + + return false; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "disallow the use of `alert`, `confirm`, and `prompt`", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/no-alert" + }, + + schema: [], + + messages: { + unexpected: "Unexpected {{name}}." + } + }, + + create(context) { + return { + CallExpression(node) { + const callee = node.callee, + currentScope = context.sourceCode.getScope?.(node) || context.getScope(); + + // without window. + if (callee.type === "Identifier") { + const name = callee.name; + + if (!isShadowed(currentScope, callee) && isProhibitedIdentifier(callee.name)) { + context.report({ + node, + messageId: "unexpected", + data: { name } + }); + } + + } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, callee.object)) { + const name = getPropertyName(callee); + + if (isProhibitedIdentifier(name)) { + context.report({ + node, + messageId: "unexpected", + data: { name } + }); + } + } + + } + }; + + } +}; diff --git a/packages/web/lib/utils.js b/packages/web/lib/utils.js index 29c8b8f..dbced1f 100644 --- a/packages/web/lib/utils.js +++ b/packages/web/lib/utils.js @@ -965,6 +965,7 @@ module.exports = { * 0o5 // false * 5e0 // false * '5' // false + * */ isDecimalInteger(node) { return node.type === "Literal" && typeof node.value === "number" && /^(0|[1-9]\d*)$/u.test(node.raw); @@ -1203,7 +1204,7 @@ module.exports = { return sourceCode.getText().slice(leftToken.range[0], rightToken.range[1]); }, - /* + /** * Determine if a node has a possiblity to be an Error object * @param {ASTNode} node ASTNode to check * @returns {boolean} True if there is a chance it contains an Error obj diff --git a/packages/web/tests/lib/rules/no-alert.js b/packages/web/tests/lib/rules/no-alert.js index 8f5ef1b..3834357 100644 --- a/packages/web/tests/lib/rules/no-alert.js +++ b/packages/web/tests/lib/rules/no-alert.js @@ -1,109 +1,109 @@ -/** - * @fileoverview Tests for no-alert rule. - * @author Nicholas C. Zakas - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/no-alert"), - { RuleTester } = require("eslint"); - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); - -ruleTester.run("no-alert", rule, { - valid: [ - "a[o.k](1)", - "foo.alert(foo)", - "foo.confirm(foo)", - "foo.prompt(foo)", - "function alert() {} alert();", - "var alert = function() {}; alert();", - "function foo() { var alert = bar; alert(); }", - "function foo(alert) { alert(); }", - "var alert = function() {}; function test() { alert(); }", - "function foo() { var alert = function() {}; function test() { alert(); } }", - "function confirm() {} confirm();", - "function prompt() {} prompt();", - "window[alert]();", - "function foo() { this.alert(); }", - "function foo() { var window = bar; window.alert(); }" - ], - invalid: [ - { - code: "alert(foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window.alert(foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window['alert'](foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "confirm(foo)", - errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window.confirm(foo)", - errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window['confirm'](foo)", - errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "prompt(foo)", - errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window.prompt(foo)", - errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "window['prompt'](foo)", - errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "function alert() {} window.alert(foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 21 }] - }, - { - code: "var alert = function() {};\nwindow.alert(foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] - }, - { - code: "function foo(alert) { window.alert(); }", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 23 }] - }, - { - code: "function foo() { alert(); }", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 18 }] - }, - { - code: "function foo() { var alert = function() {}; }\nalert();", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] - }, - { - code: "this.alert(foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "this['alert'](foo)", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] - }, - { - code: "function foo() { var window = bar; window.alert(); }\nwindow.alert();", - errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] - } - ] -}); +/** + * @fileoverview Tests for no-alert rule. + * @author Nicholas C. Zakas + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-alert"), + { RuleTester } = require("eslint"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 5, sourceType: "script" } }); + +ruleTester.run("no-alert", rule, { + valid: [ + "a[o.k](1)", + "foo.alert(foo)", + "foo.confirm(foo)", + "foo.prompt(foo)", + "function alert() {} alert();", + "var alert = function() {}; alert();", + "function foo() { var alert = bar; alert(); }", + "function foo(alert) { alert(); }", + "var alert = function() {}; function test() { alert(); }", + "function foo() { var alert = function() {}; function test() { alert(); } }", + "function confirm() {} confirm();", + "function prompt() {} prompt();", + "window[alert]();", + "function foo() { this.alert(); }", + "function foo() { var window = bar; window.alert(); }" + ], + invalid: [ + { + code: "alert(foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window.alert(foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window['alert'](foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "confirm(foo)", + errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window.confirm(foo)", + errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window['confirm'](foo)", + errors: [{ messageId: "unexpected", data: { name: "confirm" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "prompt(foo)", + errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window.prompt(foo)", + errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "window['prompt'](foo)", + errors: [{ messageId: "unexpected", data: { name: "prompt" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "function alert() {} window.alert(foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 21 }] + }, + { + code: "var alert = function() {};\nwindow.alert(foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] + }, + { + code: "function foo(alert) { window.alert(); }", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 23 }] + }, + { + code: "function foo() { alert(); }", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 18 }] + }, + { + code: "function foo() { var alert = function() {}; }\nalert();", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] + }, + { + code: "this.alert(foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "this['alert'](foo)", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "function foo() { var window = bar; window.alert(); }\nwindow.alert();", + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] + } + ] +});