From b991640176d5dce4750f7cc71c56cd6f284c882f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= Date: Wed, 21 Jun 2023 01:12:06 +0800 Subject: [PATCH] chore: switch eslint-config-eslint to the flat format (#17247) * chore: switch eslint-config-eslint to the flat format 1. convert eslint-config-eslint to the flat format. 2. export eslint-config-eslint/eslintrc (used by testing). 3. upgrade `eslint-plugin-n` v16 (added flat config supports). 4. change eslint plugins peerDependencies => dependencies. 5. change lib/eslint/eslint.js, lib/eslint/flat-eslint.js test cases to make the ci happy. note: it's a breaking change for eslint-config-eslint. refs: https://eslint.org/docs/latest/use/configure/configuration-files-new * fix: add linterOptions * chore: update comments as .eslintrc.js is no longer needed for testing --- .eslintrc.js | 5 +- eslint.config.js | 10 +- package.json | 2 +- packages/eslint-config-eslint/README.md | 9 +- packages/eslint-config-eslint/default.yml | 340 ---------------- packages/eslint-config-eslint/eslintrc.js | 452 +++++++++++++++++++++ packages/eslint-config-eslint/index.js | 409 ++++++++++++++++++- packages/eslint-config-eslint/package.json | 11 +- tests/lib/cli-engine/cli-engine.js | 8 +- tests/lib/eslint/eslint.js | 21 +- tests/lib/eslint/flat-eslint.js | 18 +- 11 files changed, 897 insertions(+), 388 deletions(-) delete mode 100644 packages/eslint-config-eslint/default.yml create mode 100644 packages/eslint-config-eslint/eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index ae258dc6441..79812915fbf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,8 +6,7 @@ * Internally, ESLint is using the eslint.config.js file to lint itself. * This file is needed too, because: * - * 1. There are tests that expect .eslintrc.js to be present to actually run. - * 2. ESLint VS Code extension expects eslintrc config files to be + * 1. ESLint VS Code extension expects eslintrc config files to be * present to work correctly. * * Once we no longer need to support both eslintrc and flat config, we will @@ -63,7 +62,7 @@ module.exports = { "internal-rules" ], extends: [ - "eslint" + "eslint/eslintrc" ], parserOptions: { ecmaVersion: 2021 diff --git a/eslint.config.js b/eslint.config.js index 492e6793ffa..95612e901ca 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -29,20 +29,14 @@ const path = require("path"); const internalPlugin = require("eslint-plugin-internal-rules"); const eslintPluginRulesRecommendedConfig = require("eslint-plugin-eslint-plugin/configs/rules-recommended"); const eslintPluginTestsRecommendedConfig = require("eslint-plugin-eslint-plugin/configs/tests-recommended"); -const { FlatCompat } = require("@eslint/eslintrc"); -const js = require("./packages/js"); const globals = require("globals"); const merge = require("lodash.merge"); +const baseConfig = require("eslint-config-eslint"); //----------------------------------------------------------------------------- // Helpers //----------------------------------------------------------------------------- -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended -}); - const INTERNAL_FILES = { CLI_ENGINE_PATTERN: "lib/cli-engine/**/*", LINTER_PATTERN: "lib/linter/**/*", @@ -81,7 +75,7 @@ function createInternalFilesPatterns(pattern = null) { } module.exports = [ - ...compat.extends("eslint"), + ...baseConfig, { ignores: [ "build/**", diff --git a/package.json b/package.json index 8a35ba94ed1..05c76fa4122 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "eslint-plugin-eslint-plugin": "^5.1.0", "eslint-plugin-internal-rules": "file:tools/internal-rules", "eslint-plugin-jsdoc": "^38.1.6", - "eslint-plugin-n": "^15.2.4", + "eslint-plugin-n": "^16.0.0", "eslint-plugin-unicorn": "^42.0.0", "eslint-release": "^3.2.0", "eslump": "^3.0.0", diff --git a/packages/eslint-config-eslint/README.md b/packages/eslint-config-eslint/README.md index c12625d58d3..6be0d1c91f1 100644 --- a/packages/eslint-config-eslint/README.md +++ b/packages/eslint-config-eslint/README.md @@ -22,12 +22,11 @@ npm install eslint-config-eslint --save-dev ## Usage -In your `.eslintrc` file, add: +In your `eslint.config.js` file, add: -```json -{ - "extends": "eslint" -} +```js +const eslintConfig = require("eslint-config-eslint"); +module.exports = eslintConfig; ``` ### Where to ask for help? diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml deleted file mode 100644 index afaabe4f7ab..00000000000 --- a/packages/eslint-config-eslint/default.yml +++ /dev/null @@ -1,340 +0,0 @@ -reportUnusedDisableDirectives: true -extends: - - "eslint:recommended" - - "plugin:n/recommended" - - "plugin:jsdoc/recommended" - - "plugin:eslint-comments/recommended" -plugins: - - unicorn -settings: - jsdoc: - tagNamePreference: - file: "fileoverview" - augments: "extends" - class: "constructor" - preferredTypes: - "*": - message: "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`" - replacement: "any" - Any: - message: "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`" - replacement: "any" - # Function: - # message: "Point to a `@callback` namepath or `GenericCallback` if truly arbitrary in form" - # replacement: "GenericCallback" - # function: - # message: "Point to a `@callback` namepath or `GenericCallback` if truly arbitrary in form" - # replacement: "GenericCallback" - function: - message: "Point to a `@callback` namepath or `Function` if truly arbitrary in form" - replacement: "Function" - Promise: - message: "Specify the specific Promise type, including, if necessary, the type `any`" - ".<>": - message: "Prefer type form without dot" - replacement: "<>" - # Object: - # message: "Use the specific object type or `PlainObject` if truly arbitrary" - # replacement: "PlainObject" - # object: - # message: "Use the specific object type or `PlainObject` if truly arbitrary" - # replacement: "PlainObject" - object: - message: "Use the specific object type or `Object` if truly arbitrary" - replacement: "Object" - # Array: - # message: "Use the specific array type or `GenericArray` if it is truly arbitrary." - # replacement: "GenericArray" - # array: - # message: "Use specific array type or `GenericArray` if it is truly arbitrary." - # replacement: "GenericArray" - array: "Array" - -rules: - array-bracket-spacing: "error" - array-callback-return: "error" - arrow-body-style: ["error", "as-needed"] - arrow-parens: ["error", "as-needed"] - arrow-spacing: "error" - indent: ["error", 4, { SwitchCase: 1 }] - block-spacing: "error" - brace-style: ["error", "1tbs"] - camelcase: "error" - class-methods-use-this: "error" - comma-dangle: "error" - comma-spacing: "error" - comma-style: ["error", "last"] - computed-property-spacing: "error" - consistent-return: "error" - curly: ["error", "all"] - default-case: "error" - default-case-last: "error" - default-param-last: "error" - dot-location: ["error", "property"] - dot-notation: ["error", { allowKeywords: true }] - eol-last: "error" - eqeqeq: "error" - - eslint-comments/disable-enable-pair: ["error"] - eslint-comments/no-unused-disable: "error" - eslint-comments/require-description: "error" - - func-call-spacing: "error" - func-style: ["error", "declaration"] - function-call-argument-newline: ["error", "consistent"] - function-paren-newline: ["error", "consistent"] - generator-star-spacing: "error" - grouped-accessor-pairs: "error" - guard-for-in: "error" - - # jsdoc: adopt non-recommended rules or change recommended configuration - # jsdoc/check-examples: "error" - # jsdoc/check-indentation: "error" # Revisit if allowing configurable spaces after tag line breaks - jsdoc/check-line-alignment: ["error", "never"] - jsdoc/check-syntax: "error" - # jsdoc/check-types': ["error', { exemptTagContexts: [ { tag: "typedef", types: ["object", "GenericObject"] } ] } - - jsdoc/check-values: ["error", { allowedLicenses: true }] - jsdoc/newline-after-description: ["error", "never"] - jsdoc/no-bad-blocks: "error" - jsdoc/require-asterisk-prefix: "error" - jsdoc/require-description: ["error", { checkConstructors: false }] - # jsdoc/require-file-overview: "error" - jsdoc/require-hyphen-before-param-description: ["error", "never"] - jsdoc/require-returns: - ["error", { forceRequireReturn: true, forceReturnsWithAsync: true }] - jsdoc/require-throws: "error" - jsdoc/tag-lines: - [ - "error", - "never", - { - tags: - { - example: { lines: "always" }, - fileoverview: { lines: "any" }, - }, - }, - ] - - # jsdoc: disable recommended rules - jsdoc/no-undefined-types: "off" - jsdoc/require-yields: "off" - - # jsdoc: change recommended rules from warnings into errors - jsdoc/check-access: "error" - jsdoc/check-alignment: "error" - jsdoc/check-param-names: "error" - jsdoc/check-property-names: "error" - jsdoc/check-tag-names: "error" - jsdoc/check-types: "error" - jsdoc/empty-tags: "error" - jsdoc/implements-on-classes: "error" - jsdoc/multiline-blocks: "error" - jsdoc/no-multi-asterisks: "error" - jsdoc/require-jsdoc: ["error", { require: { ClassDeclaration: true } }] - jsdoc/require-param: "error" - jsdoc/require-param-description: "error" - jsdoc/require-param-name: "error" - jsdoc/require-param-type: "error" - jsdoc/require-property: "error" - jsdoc/require-property-description: "error" - jsdoc/require-property-name: "error" - jsdoc/require-property-type: "error" - jsdoc/require-returns-check: "error" - jsdoc/require-returns-description: "error" - jsdoc/require-returns-type: "error" - jsdoc/require-yields-check: "error" - jsdoc/valid-types: "error" - - key-spacing: ["error", { beforeColon: false, afterColon: true }] - keyword-spacing: "error" - lines-around-comment: - [ - "error", - { - beforeBlockComment: true, - afterBlockComment: false, - beforeLineComment: true, - afterLineComment: false, - }, - ] - max-len: - [ - "error", - 160, - { - "ignoreComments": true, - "ignoreUrls": true, - "ignoreStrings": true, - "ignoreTemplateLiterals": true, - "ignoreRegExpLiterals": true, - }, - ] - max-statements-per-line: "error" - new-cap: "error" - new-parens: "error" - no-alert: "error" - no-array-constructor: "error" - no-caller: "error" - no-confusing-arrow: "error" - no-console: "error" - no-constant-binary-expression: "error" - no-constructor-return: "error" - no-else-return: ["error", { allowElseIf: false }] - no-eval: "error" - no-extend-native: "error" - no-extra-bind: "error" - no-floating-decimal: "error" - no-implied-eval: "error" - no-invalid-this: "error" - no-iterator: "error" - no-label-var: "error" - no-labels: "error" - no-lone-blocks: "error" - no-loop-func: "error" - no-mixed-spaces-and-tabs: ["error", false] # Modified from recommended - no-multi-spaces: "error" - no-multi-str: "error" - no-multiple-empty-lines: ["error", { max: 2, maxBOF: 0, maxEOF: 0 }] - no-nested-ternary: "error" - no-new: "error" - no-new-func: "error" - no-new-object: "error" - no-new-wrappers: "error" - no-octal-escape: "error" - no-param-reassign: "error" - no-proto: "error" - no-process-exit: "off" - no-restricted-properties: - [ - "error", - { - property: "substring", - message: "Use .slice instead of .substring.", - }, - { property: "substr", message: "Use .slice instead of .substr." }, - { - object: "assert", - property: "equal", - message: "Use assert.strictEqual instead of assert.equal.", - }, - { - object: "assert", - property: "notEqual", - message: "Use assert.notStrictEqual instead of assert.notEqual.", - }, - { - object: "assert", - property: "deepEqual", - message: "Use assert.deepStrictEqual instead of assert.deepEqual.", - }, - { - object: "assert", - property: "notDeepEqual", - message: "Use assert.notDeepStrictEqual instead of assert.notDeepEqual.", - }, - ] - no-return-assign: "error" - no-script-url: "error" - no-self-compare: "error" - no-sequences: "error" - no-shadow: "error" - no-tabs: "error" - no-throw-literal: "error" - no-trailing-spaces: "error" - no-undef: ["error", { typeof: true }] # Modified from recommended - no-undef-init: "error" - no-undefined: "error" - no-underscore-dangle: ["error", { allowAfterThis: true }] - no-unmodified-loop-condition: "error" - no-unneeded-ternary: "error" - no-unreachable-loop: "error" - no-unused-expressions: "error" - no-unused-vars: [ - "error", - { vars: "all", args: "after-used", caughtErrors: "all" }, - ] # Modified from recommended - no-use-before-define: "error" - no-useless-call: "error" - no-useless-computed-key: "error" - no-useless-concat: "error" - no-useless-constructor: "error" - no-useless-rename: "error" - no-useless-return: "error" - no-whitespace-before-property: "error" - no-var: "error" - - n/callback-return: ["error", ["cb", "callback", "next"]] - n/handle-callback-err: ["error", "err"] - n/no-deprecated-api: "error" - n/no-mixed-requires: "error" - n/no-new-require: "error" - n/no-path-concat: "error" - - object-curly-newline: ["error", { "consistent": true, "multiline": true }] - object-curly-spacing: ["error", "always"] - object-property-newline: ["error", { "allowAllPropertiesOnSameLine": true }] - object-shorthand: ["error", "always", { "avoidExplicitReturnArrows": true }] - one-var-declaration-per-line: "error" - operator-assignment: "error" - operator-linebreak: "error" - padding-line-between-statements: - [ - "error", - { blankLine: "always", prev: ["const", "let", "var"], next: "*" }, - { - blankLine: "any", - prev: ["const", "let", "var"], - next: ["const", "let", "var"], - }, - ] - prefer-arrow-callback: "error" - prefer-const: "error" - prefer-exponentiation-operator: "error" - prefer-numeric-literals: "error" - prefer-promise-reject-errors: "error" - prefer-regex-literals: "error" - prefer-rest-params: "error" - prefer-spread: "error" - prefer-template: "error" - quotes: ["error", "double", { avoidEscape: true }] - quote-props: ["error", "as-needed"] - radix: "error" - require-unicode-regexp: "error" - rest-spread-spacing: "error" - semi: "error" - semi-spacing: ["error", { before: false, after: true }] - semi-style: "error" - space-before-blocks: "error" - space-before-function-paren: - [ - "error", - { "anonymous": "never", "named": "never", "asyncArrow": "always" }, - ] - space-in-parens: "error" - space-infix-ops: "error" - space-unary-ops: ["error", { words: true, nonwords: false }] - spaced-comment: ["error", "always", { exceptions: ["-"] }] - strict: ["error", "global"] - switch-colon-spacing: "error" - symbol-description: "error" - template-curly-spacing: ["error", "never"] - template-tag-spacing: "error" - unicode-bom: "error" - - # Selectively-enable unicorn rules since many of its recommended rules are too aggressive/stylistic for us. - unicorn/prefer-array-find: "error" - unicorn/prefer-array-flat-map: "error" - unicorn/prefer-array-flat: "error" - unicorn/prefer-array-index-of: "error" - unicorn/prefer-array-some: "error" - unicorn/prefer-includes: "error" - unicorn/prefer-set-has: "error" - unicorn/prefer-string-slice: "error" - unicorn/prefer-string-starts-ends-with: "error" - unicorn/prefer-string-trim-start-end: "error" - - wrap-iife: "error" - yield-star-spacing: "error" - yoda: ["error", "never", { exceptRange: true }] diff --git a/packages/eslint-config-eslint/eslintrc.js b/packages/eslint-config-eslint/eslintrc.js new file mode 100644 index 00000000000..cdb312e40e8 --- /dev/null +++ b/packages/eslint-config-eslint/eslintrc.js @@ -0,0 +1,452 @@ +/** + * TODO: the config will be removed in the future, please use the index config. + * @deprecated + * @fileoverview the eslintrc config - it's exported as ESLint VS Code extension + * expects eslintrc config files to be present to work correctly.. + * @author 唯然 + */ +"use strict"; + +module.exports = { + reportUnusedDisableDirectives: true, + extends: [ + "eslint:recommended", + "plugin:n/recommended", + "plugin:jsdoc/recommended", + "plugin:eslint-comments/recommended" + ], + plugins: ["unicorn"], + settings: { + jsdoc: { + tagNamePreference: { + file: "fileoverview", + augments: "extends", + class: "constructor" + }, + preferredTypes: { + "*": { + message: + "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`", + replacement: "any" + }, + Any: { + message: + "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`", + replacement: "any" + }, + function: { + message: + "Point to a `@callback` namepath or `Function` if truly arbitrary in form", + replacement: "Function" + }, + Promise: { + message: + "Specify the specific Promise type, including, if necessary, the type `any`" + }, + ".<>": { + message: "Prefer type form without dot", + replacement: "<>" + }, + object: { + message: + "Use the specific object type or `Object` if truly arbitrary", + replacement: "Object" + }, + array: "Array" + } + } + }, + rules: { + "array-bracket-spacing": "error", + "array-callback-return": "error", + "arrow-body-style": ["error", "as-needed"], + "arrow-parens": ["error", "as-needed"], + "arrow-spacing": "error", + indent: [ + "error", + 4, + { + SwitchCase: 1 + } + ], + "block-spacing": "error", + "brace-style": ["error", "1tbs"], + camelcase: "error", + "class-methods-use-this": "error", + "comma-dangle": "error", + "comma-spacing": "error", + "comma-style": ["error", "last"], + "computed-property-spacing": "error", + "consistent-return": "error", + curly: ["error", "all"], + "default-case": "error", + "default-case-last": "error", + "default-param-last": "error", + "dot-location": ["error", "property"], + "dot-notation": [ + "error", + { + allowKeywords: true + } + ], + "eol-last": "error", + eqeqeq: "error", + "eslint-comments/disable-enable-pair": ["error"], + "eslint-comments/no-unused-disable": "error", + "eslint-comments/require-description": "error", + "func-call-spacing": "error", + "func-style": ["error", "declaration"], + "function-call-argument-newline": ["error", "consistent"], + "function-paren-newline": ["error", "consistent"], + "generator-star-spacing": "error", + "grouped-accessor-pairs": "error", + "guard-for-in": "error", + "jsdoc/check-line-alignment": ["error", "never"], + "jsdoc/check-syntax": "error", + "jsdoc/check-values": [ + "error", + { + allowedLicenses: true + } + ], + "jsdoc/newline-after-description": ["error", "never"], + "jsdoc/no-bad-blocks": "error", + "jsdoc/require-asterisk-prefix": "error", + "jsdoc/require-description": [ + "error", + { + checkConstructors: false + } + ], + "jsdoc/require-hyphen-before-param-description": ["error", "never"], + "jsdoc/require-returns": [ + "error", + { + forceRequireReturn: true, + forceReturnsWithAsync: true + } + ], + "jsdoc/require-throws": "error", + "jsdoc/tag-lines": [ + "error", + "never", + { + tags: { + example: { + lines: "always" + }, + fileoverview: { + lines: "any" + } + } + } + ], + "jsdoc/no-undefined-types": "off", + "jsdoc/require-yields": "off", + "jsdoc/check-access": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-param-names": "error", + "jsdoc/check-property-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/empty-tags": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/multiline-blocks": "error", + "jsdoc/no-multi-asterisks": "error", + "jsdoc/require-jsdoc": [ + "error", + { + require: { + ClassDeclaration: true + } + } + ], + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-name": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-property": "error", + "jsdoc/require-property-description": "error", + "jsdoc/require-property-name": "error", + "jsdoc/require-property-type": "error", + "jsdoc/require-returns-check": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "error", + "jsdoc/require-yields-check": "error", + "jsdoc/valid-types": "error", + "key-spacing": [ + "error", + { + beforeColon: false, + afterColon: true + } + ], + "keyword-spacing": "error", + "lines-around-comment": [ + "error", + { + beforeBlockComment: true, + afterBlockComment: false, + beforeLineComment: true, + afterLineComment: false + } + ], + "max-len": [ + "error", + 160, + { + ignoreComments: true, + ignoreUrls: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + ignoreRegExpLiterals: true + } + ], + "max-statements-per-line": "error", + "new-cap": "error", + "new-parens": "error", + "no-alert": "error", + "no-array-constructor": "error", + "no-caller": "error", + "no-confusing-arrow": "error", + "no-console": "error", + "no-constant-binary-expression": "error", + "no-constructor-return": "error", + "no-else-return": [ + "error", + { + allowElseIf: false + } + ], + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-floating-decimal": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-mixed-spaces-and-tabs": ["error", false], + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": [ + "error", + { + max: 2, + maxBOF: 0, + maxEOF: 0 + } + ], + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-proto": "error", + "no-process-exit": "off", + "no-restricted-properties": [ + "error", + { + property: "substring", + message: "Use .slice instead of .substring." + }, + { + property: "substr", + message: "Use .slice instead of .substr." + }, + { + object: "assert", + property: "equal", + message: "Use assert.strictEqual instead of assert.equal." + }, + { + object: "assert", + property: "notEqual", + message: + "Use assert.notStrictEqual instead of assert.notEqual." + }, + { + object: "assert", + property: "deepEqual", + message: + "Use assert.deepStrictEqual instead of assert.deepEqual." + }, + { + object: "assert", + property: "notDeepEqual", + message: + "Use assert.notDeepStrictEqual instead of assert.notDeepEqual." + } + ], + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": "error", + "no-tabs": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef": [ + "error", + { + typeof: true + } + ], + "no-undef-init": "error", + "no-undefined": "error", + "no-underscore-dangle": [ + "error", + { + allowAfterThis: true + } + ], + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + "no-unreachable-loop": "error", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + vars: "all", + args: "after-used", + caughtErrors: "all" + } + ], + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-whitespace-before-property": "error", + "no-var": "error", + "n/callback-return": ["error", ["cb", "callback", "next"]], + "n/handle-callback-err": ["error", "err"], + "n/no-deprecated-api": "error", + "n/no-mixed-requires": "error", + "n/no-new-require": "error", + "n/no-path-concat": "error", + "object-curly-newline": [ + "error", + { + consistent: true, + multiline: true + } + ], + "object-curly-spacing": ["error", "always"], + "object-property-newline": [ + "error", + { + allowAllPropertiesOnSameLine: true + } + ], + "object-shorthand": [ + "error", + "always", + { + avoidExplicitReturnArrows: true + } + ], + "one-var-declaration-per-line": "error", + "operator-assignment": "error", + "operator-linebreak": "error", + "padding-line-between-statements": [ + "error", + { + blankLine: "always", + prev: ["const", "let", "var"], + next: "*" + }, + { + blankLine: "any", + prev: ["const", "let", "var"], + next: ["const", "let", "var"] + } + ], + "prefer-arrow-callback": "error", + "prefer-const": "error", + "prefer-exponentiation-operator": "error", + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "prefer-regex-literals": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + quotes: [ + "error", + "double", + { + avoidEscape: true + } + ], + "quote-props": ["error", "as-needed"], + radix: "error", + "require-unicode-regexp": "error", + "rest-spread-spacing": "error", + semi: "error", + "semi-spacing": [ + "error", + { + before: false, + after: true + } + ], + "semi-style": "error", + "space-before-blocks": "error", + "space-before-function-paren": [ + "error", + { + anonymous: "never", + named: "never", + asyncArrow: "always" + } + ], + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": [ + "error", + { + words: true, + nonwords: false + } + ], + "spaced-comment": [ + "error", + "always", + { + exceptions: ["-"] + } + ], + strict: ["error", "global"], + "switch-colon-spacing": "error", + "symbol-description": "error", + "template-curly-spacing": ["error", "never"], + "template-tag-spacing": "error", + "unicode-bom": "error", + "unicorn/prefer-array-find": "error", + "unicorn/prefer-array-flat-map": "error", + "unicorn/prefer-array-flat": "error", + "unicorn/prefer-array-index-of": "error", + "unicorn/prefer-array-some": "error", + "unicorn/prefer-includes": "error", + "unicorn/prefer-set-has": "error", + "unicorn/prefer-string-slice": "error", + "unicorn/prefer-string-starts-ends-with": "error", + "unicorn/prefer-string-trim-start-end": "error", + "wrap-iife": "error", + "yield-star-spacing": "error", + yoda: [ + "error", + "never", + { + exceptRange: true + } + ] + } +}; diff --git a/packages/eslint-config-eslint/index.js b/packages/eslint-config-eslint/index.js index 1304f34a870..14e044726d9 100644 --- a/packages/eslint-config-eslint/index.js +++ b/packages/eslint-config-eslint/index.js @@ -1,9 +1,404 @@ -/** - * @fileoverview Index file to allow YAML file to be loaded - * @author Teddy Katz - */ "use strict"; -module.exports = { - extends: ["./default.yml"] -}; +const nodeRecommendedConfig = require("eslint-plugin-n/configs/recommended-script"); +const js = require("@eslint/js"); +const jsdoc = require("eslint-plugin-jsdoc"); +const eslintComments = require("eslint-plugin-eslint-comments"); +const unicorn = require("eslint-plugin-unicorn"); + +/* + * the plugins' configs are not updated to support the flat config, + * need to manually update the `plugins` property + */ +jsdoc.configs.recommended.plugins = { jsdoc }; +eslintComments.configs.recommended.plugins = { "eslint-comments": eslintComments }; + +// extends eslint-plugin-n's recommended config +const nodeConfigs = [nodeRecommendedConfig, { + rules: { + "n/callback-return": ["error", ["cb", "callback", "next"]], + "n/handle-callback-err": ["error", "err"], + "n/no-deprecated-api": "error", + "n/no-mixed-requires": "error", + "n/no-new-require": "error", + "n/no-path-concat": "error" + } +}]; + +// extends eslint recommended config +const jsConfigs = [js.configs.recommended, { + rules: { + "array-bracket-spacing": "error", + "array-callback-return": "error", + "arrow-body-style": ["error", "as-needed"], + "arrow-parens": ["error", "as-needed"], + "arrow-spacing": "error", + indent: ["error", 4, { SwitchCase: 1 }], + "block-spacing": "error", + "brace-style": ["error", "1tbs"], + camelcase: "error", + "class-methods-use-this": "error", + "comma-dangle": "error", + "comma-spacing": "error", + "comma-style": ["error", "last"], + "computed-property-spacing": "error", + "consistent-return": "error", + curly: ["error", "all"], + "default-case": "error", + "default-case-last": "error", + "default-param-last": "error", + "dot-location": ["error", "property"], + "dot-notation": [ + "error", + { allowKeywords: true } + ], + "eol-last": "error", + eqeqeq: "error", + "func-call-spacing": "error", + "func-style": ["error", "declaration"], + "function-call-argument-newline": ["error", "consistent"], + "function-paren-newline": ["error", "consistent"], + "generator-star-spacing": "error", + "grouped-accessor-pairs": "error", + "guard-for-in": "error", + "key-spacing": ["error", { beforeColon: false, afterColon: true }], + "keyword-spacing": "error", + "lines-around-comment": ["error", + { + beforeBlockComment: true, + afterBlockComment: false, + beforeLineComment: true, + afterLineComment: false + } + ], + "max-len": ["error", 160, + { + ignoreComments: true, + ignoreUrls: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + ignoreRegExpLiterals: true + } + ], + "max-statements-per-line": "error", + "new-cap": "error", + "new-parens": "error", + "no-alert": "error", + "no-array-constructor": "error", + "no-caller": "error", + "no-confusing-arrow": "error", + "no-console": "error", + "no-constant-binary-expression": "error", + "no-constructor-return": "error", + "no-else-return": ["error", { allowElseIf: false } + ], + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-floating-decimal": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-mixed-spaces-and-tabs": ["error", false], + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": [ + "error", + { + max: 2, + maxBOF: 0, + maxEOF: 0 + } + ], + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-proto": "error", + "no-process-exit": "off", + "no-restricted-properties": ["error", + { + property: "substring", + message: "Use .slice instead of .substring." + }, + { + property: "substr", + message: "Use .slice instead of .substr." + }, + { + object: "assert", + property: "equal", + message: "Use assert.strictEqual instead of assert.equal." + }, + { + object: "assert", + property: "notEqual", + message: "Use assert.notStrictEqual instead of assert.notEqual." + }, + { + object: "assert", + property: "deepEqual", + message: "Use assert.deepStrictEqual instead of assert.deepEqual." + }, + { + object: "assert", + property: "notDeepEqual", + message: "Use assert.notDeepStrictEqual instead of assert.notDeepEqual." + } + ], + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": "error", + "no-tabs": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef": ["error", { typeof: true }], + "no-undef-init": "error", + "no-undefined": "error", + "no-underscore-dangle": ["error", { allowAfterThis: true } + ], + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + "no-unreachable-loop": "error", + "no-unused-expressions": "error", + "no-unused-vars": ["error", { + vars: "all", + args: "after-used", + caughtErrors: "all" + } + ], + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-whitespace-before-property": "error", + "no-var": "error", + "object-curly-newline": ["error", + { + consistent: true, + multiline: true + } + ], + "object-curly-spacing": ["error", "always"], + "object-property-newline": ["error", + { + allowAllPropertiesOnSameLine: true + } + ], + "object-shorthand": ["error", + "always", + { + avoidExplicitReturnArrows: true + } + ], + "one-var-declaration-per-line": "error", + "operator-assignment": "error", + "operator-linebreak": "error", + "padding-line-between-statements": ["error", + { + blankLine: "always", + prev: ["const", "let", "var"], + next: "*" + }, + { + blankLine: "any", + prev: ["const", "let", "var"], + next: ["const", "let", "var"] + } + ], + "prefer-arrow-callback": "error", + "prefer-const": "error", + "prefer-exponentiation-operator": "error", + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "prefer-regex-literals": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + quotes: ["error", "double", { avoidEscape: true }], + "quote-props": ["error", "as-needed"], + radix: "error", + "require-unicode-regexp": "error", + "rest-spread-spacing": "error", + semi: "error", + "semi-spacing": ["error", + { + before: false, + after: true + } + ], + "semi-style": "error", + "space-before-blocks": "error", + "space-before-function-paren": ["error", + { + anonymous: "never", + named: "never", + asyncArrow: "always" + } + ], + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": ["error", + { + words: true, + nonwords: false + } + ], + "spaced-comment": ["error", + "always", + { + exceptions: ["-"] + } + ], + strict: ["error", "global"], + "switch-colon-spacing": "error", + "symbol-description": "error", + "template-curly-spacing": ["error", "never"], + "template-tag-spacing": "error", + "unicode-bom": "error", + "wrap-iife": "error", + "yield-star-spacing": "error", + yoda: ["error", "never", { exceptRange: true }] + } +}]; + +// extends eslint-plugin-jsdoc's recommended config +const jsdocConfigs = [jsdoc.configs.recommended, { + settings: { + jsdoc: { + tagNamePreference: { + file: "fileoverview", + augments: "extends", + class: "constructor" + }, + preferredTypes: { + "*": { + message: "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`", + replacement: "any" + }, + Any: { + message: "Use a more precise type or if necessary use `any` or `ArbitraryCallbackResult`", + replacement: "any" + }, + function: { + message: "Point to a `@callback` namepath or `Function` if truly arbitrary in form", + replacement: "Function" + }, + Promise: { + message: "Specify the specific Promise type, including, if necessary, the type `any`" + }, + ".<>": { + message: "Prefer type form without dot", + replacement: "<>" + }, + object: { + message: "Use the specific object type or `Object` if truly arbitrary", + replacement: "Object" + }, + array: "Array" + } + } + }, + rules: { + "jsdoc/check-line-alignment": ["error", "never"], + "jsdoc/check-syntax": "error", + "jsdoc/check-values": ["error", { allowedLicenses: true }], + "jsdoc/newline-after-description": ["error", "never"], + "jsdoc/no-bad-blocks": "error", + "jsdoc/require-asterisk-prefix": "error", + "jsdoc/require-description": ["error", { checkConstructors: false }], + "jsdoc/require-hyphen-before-param-description": ["error", "never"], + "jsdoc/require-returns": ["error", + { + forceRequireReturn: true, + forceReturnsWithAsync: true + } + ], + "jsdoc/require-throws": "error", + "jsdoc/tag-lines": ["error", "never", + { + tags: { + example: { + lines: "always" + }, + fileoverview: { + lines: "any" + } + } + } + ], + "jsdoc/no-undefined-types": "off", + "jsdoc/require-yields": "off", + "jsdoc/check-access": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-param-names": "error", + "jsdoc/check-property-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/empty-tags": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/multiline-blocks": "error", + "jsdoc/no-multi-asterisks": "error", + "jsdoc/require-jsdoc": ["error", { require: { ClassDeclaration: true } }], + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-name": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-property": "error", + "jsdoc/require-property-description": "error", + "jsdoc/require-property-name": "error", + "jsdoc/require-property-type": "error", + "jsdoc/require-returns-check": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "error", + "jsdoc/require-yields-check": "error", + "jsdoc/valid-types": "error" + } +}]; + +// extends eslint-plugin-unicorn's config +const unicornConfigs = [{ + plugins: { unicorn }, + rules: { + "unicorn/prefer-array-find": "error", + "unicorn/prefer-array-flat-map": "error", + "unicorn/prefer-array-flat": "error", + "unicorn/prefer-array-index-of": "error", + "unicorn/prefer-array-some": "error", + "unicorn/prefer-includes": "error", + "unicorn/prefer-set-has": "error", + "unicorn/prefer-string-slice": "error", + "unicorn/prefer-string-starts-ends-with": "error", + "unicorn/prefer-string-trim-start-end": "error" + } +}]; + +// extends eslint-plugin-eslint-comments's recommended config +const eslintCommentsConfigs = [eslintComments.configs.recommended, { + rules: { + "eslint-comments/disable-enable-pair": ["error"], + "eslint-comments/no-unused-disable": "error", + "eslint-comments/require-description": "error" + } +}]; + +module.exports = [ + { linterOptions: { reportUnusedDisableDirectives: true } }, + ...jsConfigs, + ...nodeConfigs, + ...unicornConfigs, + ...jsdocConfigs, + ...eslintCommentsConfigs +]; diff --git a/packages/eslint-config-eslint/package.json b/packages/eslint-config-eslint/package.json index 00c10811fb8..6a01573446a 100644 --- a/packages/eslint-config-eslint/package.json +++ b/packages/eslint-config-eslint/package.json @@ -19,11 +19,12 @@ }, "homepage": "https://eslint.org", "bugs": "https://github.com/eslint/eslint/issues/", - "peerDependencies": { - "eslint-plugin-eslint-comments": ">=3.2.0", - "eslint-plugin-jsdoc": ">=38.1.6", - "eslint-plugin-n": ">=15.2.4", - "eslint-plugin-unicorn": ">=42.0.0" + "dependencies": { + "@eslint/js": "^8.42.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-jsdoc": "^38.1.6", + "eslint-plugin-n": "^16.0.0", + "eslint-plugin-unicorn": "^42.0.0" }, "keywords": [ "eslintconfig", diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js index 971d6e60964..5012867c395 100644 --- a/tests/lib/cli-engine/cli-engine.js +++ b/tests/lib/cli-engine/cli-engine.js @@ -5184,9 +5184,9 @@ describe("CLIEngine", () => { }); it("should expose the list of plugin rules", () => { - const engine = new CLIEngine({ plugins: ["n"] }); + const engine = new CLIEngine({ plugins: ["internal-rules"] }); - assert(engine.getRules().has("n/no-deprecated-api"), "n/no-deprecated-api is present"); + assert(engine.getRules().has("internal-rules/no-invalid-meta"), "internal-rules/no-invalid-meta is present"); }); it("should expose the list of rules from a preloaded plugin", () => { @@ -5194,11 +5194,11 @@ describe("CLIEngine", () => { plugins: ["foo"] }, { preloadedPlugins: { - foo: require("eslint-plugin-n") + foo: require("eslint-plugin-internal-rules") } }); - assert(engine.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present"); + assert(engine.getRules().has("foo/no-invalid-meta"), "foo/no-invalid-meta is present"); }); }); diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js index cb43823fbc5..74abaf42e5d 100644 --- a/tests/lib/eslint/eslint.js +++ b/tests/lib/eslint/eslint.js @@ -46,7 +46,7 @@ describe("ESLint", () => { const originalDir = process.cwd(); const fixtureDir = path.resolve(fs.realpathSync(os.tmpdir()), "eslint/fixtures"); - /** @type {import("../../../lib/eslint").ESLint} */ + /** @type {import("../../../lib/eslint/eslint").ESLint} */ let ESLint; /** @@ -5125,30 +5125,35 @@ describe("ESLint", () => { }); it("should return multiple rule meta when there are multiple linting errors from a plugin", async () => { - const nodePlugin = require("eslint-plugin-n"); + const customPlugin = { + rules: { + "no-var": require("../../../lib/rules/no-var") + } + }; + const engine = new ESLint({ useEslintrc: false, plugins: { - node: nodePlugin + "custom-plugin": customPlugin }, overrideConfig: { - plugins: ["n"], + plugins: ["custom-plugin"], rules: { - "n/no-new-require": 2, + "custom-plugin/no-var": 2, semi: 2, quotes: [2, "double"] } } }); - const results = await engine.lintText("new require('hi')"); + const results = await engine.lintText("var foo = 0; var bar = '1'"); const rulesMeta = engine.getRulesMetaForResults(results); assert.strictEqual(rulesMeta.semi, coreRules.get("semi").meta); assert.strictEqual(rulesMeta.quotes, coreRules.get("quotes").meta); assert.strictEqual( - rulesMeta["n/no-new-require"], - nodePlugin.rules["no-new-require"].meta + rulesMeta["custom-plugin/no-var"], + customPlugin.rules["no-var"].meta ); }); diff --git a/tests/lib/eslint/flat-eslint.js b/tests/lib/eslint/flat-eslint.js index 0a692e9e7f9..0865a071070 100644 --- a/tests/lib/eslint/flat-eslint.js +++ b/tests/lib/eslint/flat-eslint.js @@ -69,7 +69,7 @@ describe("FlatESLint", () => { const originalDir = process.cwd(); const fixtureDir = path.resolve(fs.realpathSync(os.tmpdir()), "eslint/fixtures"); - /** @type {import("../../../lib/flat-eslint").FlatESLint} */ + /** @type {import("../../../lib/eslint/flat-eslint").FlatESLint} */ let FlatESLint; /** @@ -4379,29 +4379,33 @@ describe("FlatESLint", () => { }); it("should return multiple rule meta when there are multiple linting errors from a plugin", async () => { - const nodePlugin = require("eslint-plugin-n"); + const customPlugin = { + rules: { + "no-var": require("../../../lib/rules/no-var") + } + }; const engine = new FlatESLint({ overrideConfigFile: true, overrideConfig: { plugins: { - n: nodePlugin + "custom-plugin": customPlugin }, rules: { - "n/no-new-require": 2, + "custom-plugin/no-var": 2, semi: 2, quotes: [2, "double"] } } }); - const results = await engine.lintText("new require('hi')"); + const results = await engine.lintText("var foo = 0; var bar = '1'"); const rulesMeta = engine.getRulesMetaForResults(results); assert.strictEqual(rulesMeta.semi, coreRules.get("semi").meta); assert.strictEqual(rulesMeta.quotes, coreRules.get("quotes").meta); assert.strictEqual( - rulesMeta["n/no-new-require"], - nodePlugin.rules["no-new-require"].meta + rulesMeta["custom-plugin/no-var"], + customPlugin.rules["no-var"].meta ); });