From b6d759082d5006d78b5c4df3082c2c7305cb8312 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sun, 24 Feb 2019 01:37:10 +0100 Subject: [PATCH 01/17] feat(eslint-plugin): add config all.json --- packages/eslint-plugin/package.json | 2 +- packages/eslint-plugin/src/configs/all.json | 57 ++++++++++ .../src/configs/recommended.json | 3 + packages/eslint-plugin/tools/create-config.ts | 102 ++++++++++++++++++ .../eslint-plugin/tools/update-recommended.ts | 68 ------------ 5 files changed, 163 insertions(+), 69 deletions(-) create mode 100644 packages/eslint-plugin/src/configs/all.json create mode 100644 packages/eslint-plugin/tools/create-config.ts delete mode 100644 packages/eslint-plugin/tools/update-recommended.ts diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index ca82d78f6fbe..d41b375d97cd 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -28,7 +28,7 @@ "docs": "eslint-docs", "docs:check": "eslint-docs check", "test": "jest --coverage", - "recommended:update": "ts-node tools/update-recommended.ts", + "create:config": "ts-node --files tools/create-config.ts", "prebuild": "npm run clean", "build": "tsc -p tsconfig.build.json", "clean": "rimraf dist/", diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json new file mode 100644 index 000000000000..0d7c524d6fdd --- /dev/null +++ b/packages/eslint-plugin/src/configs/all.json @@ -0,0 +1,57 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/ban-ts-ignore": "error", + "@typescript-eslint/ban-types": "error", + "camelcase": "off", + "@typescript-eslint/camelcase": "error", + "@typescript-eslint/class-name-casing": "error", + "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/explicit-member-accessibility": "error", + "@typescript-eslint/generic-type-naming": "warn", + "indent": "off", + "@typescript-eslint/indent": "error", + "@typescript-eslint/interface-name-prefix": "error", + "@typescript-eslint/member-delimiter-style": "error", + "@typescript-eslint/member-naming": "warn", + "@typescript-eslint/member-ordering": "warn", + "@typescript-eslint/no-angle-bracket-type-assertion": "error", + "no-array-constructor": "off", + "@typescript-eslint/no-array-constructor": "error", + "@typescript-eslint/no-empty-interface": "error", + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-extraneous-class": "warn", + "@typescript-eslint/no-for-in-array": "warn", + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "error", + "@typescript-eslint/no-non-null-assertion": "error", + "@typescript-eslint/no-object-literal-type-assertion": "error", + "@typescript-eslint/no-parameter-properties": "error", + "@typescript-eslint/no-require-imports": "error", + "@typescript-eslint/no-this-alias": "warn", + "@typescript-eslint/no-triple-slash-reference": "error", + "@typescript-eslint/no-type-alias": "warn", + "@typescript-eslint/no-unnecessary-qualifier": "warn", + "@typescript-eslint/no-unnecessary-type-assertion": "warn", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-use-before-define": "error", + "@typescript-eslint/no-useless-constructor": "warn", + "@typescript-eslint/no-var-requires": "error", + "@typescript-eslint/prefer-function-type": "warn", + "@typescript-eslint/prefer-interface": "error", + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/prefer-regexp-exec": "warn", + "@typescript-eslint/promise-function-async": "error", + "@typescript-eslint/require-array-sort-compare": "warn", + "@typescript-eslint/restrict-plus-operands": "warn", + "@typescript-eslint/type-annotation-spacing": "error" + } +} diff --git a/packages/eslint-plugin/src/configs/recommended.json b/packages/eslint-plugin/src/configs/recommended.json index e107a6457248..1032727f5765 100644 --- a/packages/eslint-plugin/src/configs/recommended.json +++ b/packages/eslint-plugin/src/configs/recommended.json @@ -7,6 +7,7 @@ "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", + "@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-types": "error", "camelcase": "off", "@typescript-eslint/camelcase": "error", @@ -28,6 +29,7 @@ "@typescript-eslint/no-non-null-assertion": "error", "@typescript-eslint/no-object-literal-type-assertion": "error", "@typescript-eslint/no-parameter-properties": "error", + "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-triple-slash-reference": "error", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "warn", @@ -35,6 +37,7 @@ "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/prefer-interface": "error", "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/promise-function-async": "error", "@typescript-eslint/type-annotation-spacing": "error" } } diff --git a/packages/eslint-plugin/tools/create-config.ts b/packages/eslint-plugin/tools/create-config.ts new file mode 100644 index 000000000000..4f9d0cb83841 --- /dev/null +++ b/packages/eslint-plugin/tools/create-config.ts @@ -0,0 +1,102 @@ +/* eslint-disable no-console */ + +import path from 'path'; +import fs from 'fs'; +import requireIndex from 'requireindex'; + +const MAX_RULE_NAME_LENGTH = 33 + 'typescript-eslint/'.length; +const RULE_NAME_PREFIX = '@typescript-eslint'; + +const all = Object.entries( + requireIndex(path.resolve(__dirname, '../dist/rules')), +); + +const baseConfig = { + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + }, + plugins: ['@typescript-eslint'], +}; + +const bannedRules = new Set([ + 'camelcase', + 'indent', + 'no-array-constructor', + 'no-unused-vars', +]); + +/** + * Helper function reduces records to key - value pairs. + * @param config + * @param entry + */ +const reducer = ( + config: Record, + entry: Record, +): Record => { + const key = entry[0]; + const value = entry[1]; + const ruleName = `${RULE_NAME_PREFIX}/${key}`; + const setting = value.default.meta.docs.recommended; + const usedSetting = !setting ? 'warn' : setting; + + // having this here is just for output niceness (the keys will be ordered) + if (bannedRules.has(key)) { + console.log(key.padEnd(MAX_RULE_NAME_LENGTH), '= off'); + config[key] = 'off'; + } + console.log(ruleName.padEnd(MAX_RULE_NAME_LENGTH), '=', usedSetting); + config[ruleName] = usedSetting; + + return config; +}; + +/** + * Helper function to check for invalid recommended setting. + */ +function checkValidSettings(): boolean { + const validSettings = ['error', 'warn', false]; + let result = true; + + all.forEach(entry => { + const key = entry[0]; + const value = entry[1]; + const setting = value.default.meta.docs.recommended; + + if (!validSettings.includes(setting)) { + console.error(`ERR! Invalid level for rule ${key}: "${setting}"`); + result = false; + } + }); + + return result; +} + +/** + * Helper function generates configuration. + */ +function generate(rules: Record, filePath: string): void { + const config = Object.assign({}, baseConfig, { rules }); + + fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); +} + +if (checkValidSettings()) { + console.log('------------------------- all.json -------------------------'); + generate( + all.reduce(reducer, {}), + path.resolve(__dirname, '../src/configs/all.json'), + ); + + console.log('--------------------- recommended.json ---------------------'); + const recommendedSettings = ['error', 'warn']; + generate( + all + .filter(entry => + recommendedSettings.includes(entry[1].default.meta.docs.recommended), + ) + .reduce(reducer, {}), + path.resolve(__dirname, '../src/configs/recommended.json'), + ); +} diff --git a/packages/eslint-plugin/tools/update-recommended.ts b/packages/eslint-plugin/tools/update-recommended.ts deleted file mode 100644 index 39861d35ee74..000000000000 --- a/packages/eslint-plugin/tools/update-recommended.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable no-console */ - -import path from 'path'; -import fs from 'fs'; -import requireIndex from 'requireindex'; - -const bannedRecommendedRules = new Set([ - 'camelcase', - 'indent', - 'no-array-constructor', - 'no-unused-vars', -]); -const MAX_RULE_NAME_LENGTH = 32 + 'typescript/'.length; - -function padEnd(str: string, length: number): string { - while (str.length < length) { - str += ' '; - } - return str; -} - -/** - * Generate recommended configuration - */ -function generate(): void { - // replace this with Object.entries when node > 8 - const allRules = requireIndex(path.resolve(__dirname, '../dist/lib/rules')); - - const rules = Object.keys(allRules) - .filter(key => !!allRules[key].meta.docs.recommended) - .reduce>((config, key) => { - // having this here is just for output niceness (the keys will be ordered) - if (bannedRecommendedRules.has(key)) { - console.log(padEnd(key, MAX_RULE_NAME_LENGTH), '= off'); - config[key] = 'off'; - } - - const ruleName = `@typescript-eslint/${key}`; - const setting = allRules[key].meta.docs.recommended; - - if (!['error', 'warn'].includes(setting)) { - console.log(`ERR! Invalid level for rule ${key}: "${setting}"`); - // Don't want to throw an error since ^ explains what happened. - // eslint-disable-next-line no-process-exit - process.exit(1); - } - - console.log(padEnd(ruleName, MAX_RULE_NAME_LENGTH), '=', setting); - config[ruleName] = setting; - - return config; - }, {}); - - const filePath = path.resolve(__dirname, '../src/configs/recommended.json'); - - const recommendedConfig = { - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - }, - plugins: ['@typescript-eslint'], - rules, - }; - - fs.writeFileSync(filePath, `${JSON.stringify(recommendedConfig, null, 4)}\n`); -} - -generate(); From 3cb45676a9e80040e7ef6b4e20dccd785f6b7cd0 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Wed, 27 Feb 2019 11:54:50 +0100 Subject: [PATCH 02/17] fix: no new rules for recommended.json and extract base.json --- packages/eslint-plugin/package.json | 2 +- packages/eslint-plugin/src/configs/all.json | 17 +++-------- packages/eslint-plugin/src/configs/base.json | 13 ++++++++ .../src/configs/recommended.json | 13 +------- .../eslint-plugin/src/rules/ban-ts-ignore.ts | 2 +- .../src/rules/no-require-imports.ts | 2 +- .../src/rules/promise-function-async.ts | 2 +- .../{create-config.ts => generate-configs.ts} | 30 ++++--------------- 8 files changed, 27 insertions(+), 54 deletions(-) create mode 100644 packages/eslint-plugin/src/configs/base.json rename packages/eslint-plugin/tools/{create-config.ts => generate-configs.ts} (77%) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index e26c2b26a0b9..cca99252c5d6 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -28,7 +28,7 @@ "docs": "eslint-docs", "docs:check": "eslint-docs check", "test": "jest --coverage", - "create:config": "ts-node --files tools/create-config.ts", + "generate:configs": "ts-node --files tools/generate-configs.ts", "prebuild": "npm run clean", "build": "tsc -p tsconfig.build.json", "clean": "rimraf dist/", diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index 0d7c524d6fdd..a7c549802192 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -1,28 +1,21 @@ { - "parser": "@typescript-eslint/parser", - "parserOptions": { - "sourceType": "module" - }, - "plugins": ["@typescript-eslint"], + "extends": "./base.json", "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-ts-ignore": "error", + "@typescript-eslint/ban-ts-ignore": "warn", "@typescript-eslint/ban-types": "error", - "camelcase": "off", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/explicit-member-accessibility": "error", "@typescript-eslint/generic-type-naming": "warn", - "indent": "off", "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", "@typescript-eslint/member-naming": "warn", "@typescript-eslint/member-ordering": "warn", "@typescript-eslint/no-angle-bracket-type-assertion": "error", - "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "warn", @@ -34,13 +27,12 @@ "@typescript-eslint/no-non-null-assertion": "error", "@typescript-eslint/no-object-literal-type-assertion": "error", "@typescript-eslint/no-parameter-properties": "error", - "@typescript-eslint/no-require-imports": "error", + "@typescript-eslint/no-require-imports": "warn", "@typescript-eslint/no-this-alias": "warn", "@typescript-eslint/no-triple-slash-reference": "error", "@typescript-eslint/no-type-alias": "warn", "@typescript-eslint/no-unnecessary-qualifier": "warn", "@typescript-eslint/no-unnecessary-type-assertion": "warn", - "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-useless-constructor": "warn", @@ -48,8 +40,7 @@ "@typescript-eslint/prefer-function-type": "warn", "@typescript-eslint/prefer-interface": "error", "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/prefer-regexp-exec": "warn", - "@typescript-eslint/promise-function-async": "error", + "@typescript-eslint/promise-function-async": "warn", "@typescript-eslint/require-array-sort-compare": "warn", "@typescript-eslint/restrict-plus-operands": "warn", "@typescript-eslint/type-annotation-spacing": "error" diff --git a/packages/eslint-plugin/src/configs/base.json b/packages/eslint-plugin/src/configs/base.json new file mode 100644 index 000000000000..d5ffe78aa1da --- /dev/null +++ b/packages/eslint-plugin/src/configs/base.json @@ -0,0 +1,13 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "camelcase": "off", + "indent": "off", + "no-array-constructor": "off", + "no-unused-vars": "off" + } +} diff --git a/packages/eslint-plugin/src/configs/recommended.json b/packages/eslint-plugin/src/configs/recommended.json index 1032727f5765..3414f8fddde9 100644 --- a/packages/eslint-plugin/src/configs/recommended.json +++ b/packages/eslint-plugin/src/configs/recommended.json @@ -1,25 +1,17 @@ { - "parser": "@typescript-eslint/parser", - "parserOptions": { - "sourceType": "module" - }, - "plugins": ["@typescript-eslint"], + "extends": "./base.json", "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-types": "error", - "camelcase": "off", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/explicit-member-accessibility": "error", - "indent": "off", "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", "@typescript-eslint/no-angle-bracket-type-assertion": "error", - "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "warn", @@ -29,15 +21,12 @@ "@typescript-eslint/no-non-null-assertion": "error", "@typescript-eslint/no-object-literal-type-assertion": "error", "@typescript-eslint/no-parameter-properties": "error", - "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-triple-slash-reference": "error", - "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/prefer-interface": "error", "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/promise-function-async": "error", "@typescript-eslint/type-annotation-spacing": "error" } } diff --git a/packages/eslint-plugin/src/rules/ban-ts-ignore.ts b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts index bf83a29cf4e0..661031a03f79 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-ignore.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts @@ -8,7 +8,7 @@ export default util.createRule({ description: 'Bans “// @ts-ignore” comments from being used.', tslintRuleName: 'ban-ts-ignore', category: 'Best Practices', - recommended: 'error', + recommended: false, }, schema: [], messages: { diff --git a/packages/eslint-plugin/src/rules/no-require-imports.ts b/packages/eslint-plugin/src/rules/no-require-imports.ts index 98039a91b7a8..38f332a03879 100644 --- a/packages/eslint-plugin/src/rules/no-require-imports.ts +++ b/packages/eslint-plugin/src/rules/no-require-imports.ts @@ -9,7 +9,7 @@ export default util.createRule({ description: 'Disallows invocation of `require()`.', tslintName: 'no-require-imports', category: 'Best Practices', - recommended: 'error', + recommended: false, }, schema: [], messages: { diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 75d2ccdacc7e..18236b046cb6 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -21,7 +21,7 @@ export default util.createRule({ 'Requires any function or method that returns a Promise to be marked async.', tslintName: 'promise-function-async', category: 'Best Practices', - recommended: 'error', + recommended: false, }, messages: { missingAsync: 'Functions that return promises must be async.', diff --git a/packages/eslint-plugin/tools/create-config.ts b/packages/eslint-plugin/tools/generate-configs.ts similarity index 77% rename from packages/eslint-plugin/tools/create-config.ts rename to packages/eslint-plugin/tools/generate-configs.ts index 4f9d0cb83841..61fa1b4842fc 100644 --- a/packages/eslint-plugin/tools/create-config.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -7,25 +7,10 @@ import requireIndex from 'requireindex'; const MAX_RULE_NAME_LENGTH = 33 + 'typescript-eslint/'.length; const RULE_NAME_PREFIX = '@typescript-eslint'; -const all = Object.entries( +const allRules = Object.entries( requireIndex(path.resolve(__dirname, '../dist/rules')), ); -const baseConfig = { - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - }, - plugins: ['@typescript-eslint'], -}; - -const bannedRules = new Set([ - 'camelcase', - 'indent', - 'no-array-constructor', - 'no-unused-vars', -]); - /** * Helper function reduces records to key - value pairs. * @param config @@ -41,11 +26,6 @@ const reducer = ( const setting = value.default.meta.docs.recommended; const usedSetting = !setting ? 'warn' : setting; - // having this here is just for output niceness (the keys will be ordered) - if (bannedRules.has(key)) { - console.log(key.padEnd(MAX_RULE_NAME_LENGTH), '= off'); - config[key] = 'off'; - } console.log(ruleName.padEnd(MAX_RULE_NAME_LENGTH), '=', usedSetting); config[ruleName] = usedSetting; @@ -59,7 +39,7 @@ function checkValidSettings(): boolean { const validSettings = ['error', 'warn', false]; let result = true; - all.forEach(entry => { + allRules.forEach(entry => { const key = entry[0]; const value = entry[1]; const setting = value.default.meta.docs.recommended; @@ -77,7 +57,7 @@ function checkValidSettings(): boolean { * Helper function generates configuration. */ function generate(rules: Record, filePath: string): void { - const config = Object.assign({}, baseConfig, { rules }); + const config = Object.assign({ extends: './base.json' }, { rules }); fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); } @@ -85,14 +65,14 @@ function generate(rules: Record, filePath: string): void { if (checkValidSettings()) { console.log('------------------------- all.json -------------------------'); generate( - all.reduce(reducer, {}), + allRules.reduce(reducer, {}), path.resolve(__dirname, '../src/configs/all.json'), ); console.log('--------------------- recommended.json ---------------------'); const recommendedSettings = ['error', 'warn']; generate( - all + allRules .filter(entry => recommendedSettings.includes(entry[1].default.meta.docs.recommended), ) From 886b765295683e4f1cf216be05ab7811edb692d0 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:33:36 +0100 Subject: [PATCH 03/17] fix: export base.json and all.json --- packages/eslint-plugin/src/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index a69361543aaa..899925f02b0a 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -1,6 +1,8 @@ import requireIndex from 'requireindex'; import path from 'path'; +import all from './configs/all.json'; +import base from './configs/base.json'; import recommended from './configs/recommended.json'; const rules = requireIndex(path.join(__dirname, 'rules')); @@ -17,6 +19,8 @@ const rulesWithoutDefault = Object.keys(rules).reduce>( export = { rules: rulesWithoutDefault, configs: { + all, + base, recommended, }, }; From c51d4345a49bca984991d1473a5a7d192b3f52ec Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:40:21 +0100 Subject: [PATCH 04/17] fix: path to base.json --- packages/eslint-plugin/tools/generate-configs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index 61fa1b4842fc..f7834550469b 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -57,7 +57,7 @@ function checkValidSettings(): boolean { * Helper function generates configuration. */ function generate(rules: Record, filePath: string): void { - const config = Object.assign({ extends: './base.json' }, { rules }); + const config = Object.assign({ extends: './configs/base.json' }, { rules }); fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); } From c0eec0e84ab7d24fa18064683d57c9cbe8ad1726 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:47:04 +0100 Subject: [PATCH 05/17] fix: regenerate configs with fixed path --- packages/eslint-plugin/src/configs/all.json | 2 +- packages/eslint-plugin/src/configs/recommended.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index a7c549802192..5e2a34e68930 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -1,5 +1,5 @@ { - "extends": "./base.json", + "extends": "./configs/base.json", "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", diff --git a/packages/eslint-plugin/src/configs/recommended.json b/packages/eslint-plugin/src/configs/recommended.json index 3414f8fddde9..f3c9b911026d 100644 --- a/packages/eslint-plugin/src/configs/recommended.json +++ b/packages/eslint-plugin/src/configs/recommended.json @@ -1,5 +1,5 @@ { - "extends": "./base.json", + "extends": "./configs/base.json", "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", From e9a012c8a868797e54b40a35f5613fe8bc3446d9 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sat, 2 Mar 2019 12:44:09 +0100 Subject: [PATCH 06/17] feat(eslint-plugin): provide index.ts to collect rules --- .prettierignore | 1 - packages/eslint-plugin/package.json | 1 - packages/eslint-plugin/src/index.ts | 16 +--- packages/eslint-plugin/src/rules/index.ts | 89 +++++++++++++++++++ .../eslint-plugin/tools/generate-configs.ts | 60 ++++--------- .../eslint-plugin/typings/requireindex.d.ts | 9 -- yarn.lock | 5 -- 7 files changed, 107 insertions(+), 74 deletions(-) create mode 100644 packages/eslint-plugin/src/rules/index.ts delete mode 100644 packages/eslint-plugin/typings/requireindex.d.ts diff --git a/.prettierignore b/.prettierignore index b8623219a349..5775b89b030e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,6 @@ **/coverage **/shared-fixtures **/tests/integration/fixtures/**/* -**/lib/configs/recommended.json **/.vscode **/.nyc_output packages/eslint-plugin-tslint/tests/test-tslint-rules-directory/alwaysFailRule.js diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index cca99252c5d6..f9843577e35c 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -37,7 +37,6 @@ "dependencies": { "@typescript-eslint/parser": "1.4.2", "@typescript-eslint/typescript-estree": "1.4.2", - "requireindex": "^1.2.0", "tsutils": "^3.7.0" }, "devDependencies": { diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index 899925f02b0a..b48d46f27ca8 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -1,23 +1,11 @@ -import requireIndex from 'requireindex'; -import path from 'path'; +import rules from './rules'; import all from './configs/all.json'; import base from './configs/base.json'; import recommended from './configs/recommended.json'; -const rules = requireIndex(path.join(__dirname, 'rules')); -// eslint expects the rule to be on rules[name], not rules[name].default -const rulesWithoutDefault = Object.keys(rules).reduce>( - (acc, ruleName) => { - acc[ruleName] = rules[ruleName].default; - return acc; - }, - {}, -); - -// import all rules in lib/rules export = { - rules: rulesWithoutDefault, + rules: rules, configs: { all, base, diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts new file mode 100644 index 000000000000..04caf845fd3d --- /dev/null +++ b/packages/eslint-plugin/src/rules/index.ts @@ -0,0 +1,89 @@ +import adjacentOverloadSignatures from './adjacent-overload-signatures'; +import arrayType from './array-type'; +import banTsIgnore from './ban-ts-ignore'; +import banTypes from './ban-types'; +import camelcase from './camelcase'; +import classNameCasing from './class-name-casing'; +import explicitFunctionReturnType from './explicit-function-return-type'; +import explicitMemberAccessibility from './explicit-member-accessibility'; +import genericTypeNaming from './generic-type-naming'; +import indent from './indent'; +import interfaceNamePrefix from './interface-name-prefix'; +import memberDelimiterStyle from './member-delimiter-style'; +import memberNaming from './member-naming'; +import memberOrdering from './member-ordering'; +import noAngleBracketTypeAssertion from './no-angle-bracket-type-assertion'; +import noArrayConstructor from './no-array-constructor'; +import noEmptyInterface from './no-empty-interface'; +import noExplicitAny from './no-explicit-any'; +import noExtraneousClass from './no-extraneous-class'; +import noForInArray from './no-for-in-array'; +import noInferrableTypes from './no-inferrable-types'; +import noMisusedNew from './no-misused-new'; +import noNamespace from './no-namespace'; +import noNonNullAssertion from './no-non-null-assertion'; +import noObjectLiteralTypeAssertion from './no-object-literal-type-assertion'; +import noParameterProperties from './no-parameter-properties'; +import noRequireImports from './no-require-imports'; +import noThisAlias from './no-this-alias'; +import noTripleSlashReference from './no-triple-slash-reference'; +import noTypeAlias from './no-type-alias'; +import noUnnecessaryQualifier from './no-unnecessary-qualifier'; +import noUnnecessaryTypeAssertion from './no-unnecessary-type-assertion'; +import noUnusedVars from './no-unused-vars'; +import noUseBeforeDefine from './no-use-before-define'; +import noUselessConstructor from './no-useless-constructor'; +import noVarRequires from './no-var-requires'; +import preferFunctionType from './prefer-function-type'; +import preferInterface from './prefer-interface'; +import preferNamespaceKeyword from './prefer-namespace-keyword'; +import promiseFunctionAsync from './promise-function-async'; +import requireArraySortCompare from './require-array-sort-compare'; +import restrictPlusOperands from './restrict-plus-operands'; +import typeAnnotationSpacing from './type-annotation-spacing'; + +export default { + 'adjacent-overload-signatures': adjacentOverloadSignatures, + 'array-type': arrayType, + 'ban-ts-ignore': banTsIgnore, + 'ban-types': banTypes, + camelcase: camelcase, + 'class-name-casing': classNameCasing, + 'explicit-function-return-type': explicitFunctionReturnType, + 'explicit-member-accessibility': explicitMemberAccessibility, + 'generic-type-naming': genericTypeNaming, + indent: indent, + 'interface-name-prefix': interfaceNamePrefix, + 'member-delimiter-style': memberDelimiterStyle, + 'member-naming': memberNaming, + 'member-ordering': memberOrdering, + 'no-angle-bracket-type-assertion': noAngleBracketTypeAssertion, + 'no-array-constructor': noArrayConstructor, + 'no-empty-interface': noEmptyInterface, + 'no-explicit-any': noExplicitAny, + 'no-extraneous-class': noExtraneousClass, + 'no-for-in-array': noForInArray, + 'no-inferrable-types': noInferrableTypes, + 'no-misused-new': noMisusedNew, + 'no-namespace': noNamespace, + 'no-non-null-assertion': noNonNullAssertion, + 'no-object-literal-type-assertion': noObjectLiteralTypeAssertion, + 'no-parameter-properties': noParameterProperties, + 'no-require-imports': noRequireImports, + 'no-this-alias': noThisAlias, + 'no-triple-slash-reference': noTripleSlashReference, + 'no-type-alias': noTypeAlias, + 'no-unnecessary-qualifier': noUnnecessaryQualifier, + 'no-unnecessary-type-assertion': noUnnecessaryTypeAssertion, + 'no-unused-vars': noUnusedVars, + 'no-use-before-define': noUseBeforeDefine, + 'no-useless-constructor': noUselessConstructor, + 'no-var-requires': noVarRequires, + 'prefer-function-type': preferFunctionType, + 'prefer-interface': preferInterface, + 'prefer-namespace-keyword': preferNamespaceKeyword, + 'promise-function-async': promiseFunctionAsync, + 'require-array-sort-compare': requireArraySortCompare, + 'restrict-plus-operands': restrictPlusOperands, + 'type-annotation-spacing': typeAnnotationSpacing, +}; diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index f7834550469b..7d8facdb4f7a 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -2,14 +2,12 @@ import path from 'path'; import fs from 'fs'; -import requireIndex from 'requireindex'; +import rules from '../src/rules'; -const MAX_RULE_NAME_LENGTH = 33 + 'typescript-eslint/'.length; const RULE_NAME_PREFIX = '@typescript-eslint'; +const MAX_RULE_NAME_LENGTH = 33 + RULE_NAME_PREFIX.length; -const allRules = Object.entries( - requireIndex(path.resolve(__dirname, '../dist/rules')), -); +const allRules = Object.entries(rules); /** * Helper function reduces records to key - value pairs. @@ -23,7 +21,7 @@ const reducer = ( const key = entry[0]; const value = entry[1]; const ruleName = `${RULE_NAME_PREFIX}/${key}`; - const setting = value.default.meta.docs.recommended; + const setting = value.meta.docs.recommended; const usedSetting = !setting ? 'warn' : setting; console.log(ruleName.padEnd(MAX_RULE_NAME_LENGTH), '=', usedSetting); @@ -32,27 +30,6 @@ const reducer = ( return config; }; -/** - * Helper function to check for invalid recommended setting. - */ -function checkValidSettings(): boolean { - const validSettings = ['error', 'warn', false]; - let result = true; - - allRules.forEach(entry => { - const key = entry[0]; - const value = entry[1]; - const setting = value.default.meta.docs.recommended; - - if (!validSettings.includes(setting)) { - console.error(`ERR! Invalid level for rule ${key}: "${setting}"`); - result = false; - } - }); - - return result; -} - /** * Helper function generates configuration. */ @@ -62,21 +39,16 @@ function generate(rules: Record, filePath: string): void { fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); } -if (checkValidSettings()) { - console.log('------------------------- all.json -------------------------'); - generate( - allRules.reduce(reducer, {}), - path.resolve(__dirname, '../src/configs/all.json'), - ); +console.log('------------------------ all.json ------------------------'); +generate( + allRules.reduce(reducer, {} as Record), + path.resolve(__dirname, '../src/configs/all.json'), +); - console.log('--------------------- recommended.json ---------------------'); - const recommendedSettings = ['error', 'warn']; - generate( - allRules - .filter(entry => - recommendedSettings.includes(entry[1].default.meta.docs.recommended), - ) - .reduce(reducer, {}), - path.resolve(__dirname, '../src/configs/recommended.json'), - ); -} +console.log('-------------------- recommended.json --------------------'); +generate( + allRules + .filter(entry => !!entry[1].meta.docs.recommended) + .reduce(reducer, {}), + path.resolve(__dirname, '../src/configs/recommended.json'), +); diff --git a/packages/eslint-plugin/typings/requireindex.d.ts b/packages/eslint-plugin/typings/requireindex.d.ts deleted file mode 100644 index 03807931eeda..000000000000 --- a/packages/eslint-plugin/typings/requireindex.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module 'requireindex' { - type RequireIndex = ( - path: string, - basenames?: string[], - ) => Record; - - const fn: RequireIndex; - export = fn; -} diff --git a/yarn.lock b/yarn.lock index fe9efe6c836e..f6829fbf835f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6030,11 +6030,6 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= -requireindex@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" - integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" From fdd01d9c415b597a73423b4a67dc1e4ea136655c Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sat, 2 Mar 2019 16:30:10 +0100 Subject: [PATCH 07/17] test: add tests for ./src/rules/index.ts and ./src/.configs/all.json --- .../eslint-plugin/tests/configs/all.test.ts | 20 +++++++++++++++++++ .../eslint-plugin/tests/rules/index.test.ts | 14 +++++++++++++ .../eslint-plugin/tools/generate-configs.ts | 10 +++++----- 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 packages/eslint-plugin/tests/configs/all.test.ts create mode 100644 packages/eslint-plugin/tests/rules/index.test.ts diff --git a/packages/eslint-plugin/tests/configs/all.test.ts b/packages/eslint-plugin/tests/configs/all.test.ts new file mode 100644 index 000000000000..33c342d83309 --- /dev/null +++ b/packages/eslint-plugin/tests/configs/all.test.ts @@ -0,0 +1,20 @@ +import rules from '../../src/rules'; +import allConfig from '../../src/configs/all.json'; + +describe('all.json config', () => { + const ruleNames = Object.keys(rules).map( + name => `@typescript-eslint/${name}`, + ); + + it('contains all available rule modules', () => { + expect(ruleNames).toEqual( + expect.arrayContaining(Object.keys(allConfig.rules)), + ); + }); + + it('has all rules enabled either with "warn" or "error"', () => { + expect(['warn', 'error']).toEqual( + expect.arrayContaining(Object.values(allConfig.rules)), + ); + }); +}); diff --git a/packages/eslint-plugin/tests/rules/index.test.ts b/packages/eslint-plugin/tests/rules/index.test.ts new file mode 100644 index 000000000000..c9160c0522f6 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/index.test.ts @@ -0,0 +1,14 @@ +import fs from 'fs'; + +import rules from '../../src/rules'; + +describe('./src/rules/index.ts', () => { + const ruleNames = Object.keys(rules).map(name => `${name}.ts`); + const files = fs + .readdirSync('./src/rules') + .filter(file => file !== 'index.ts' && file.endsWith('.ts')); + + it('imports all available rule modules', () => { + expect(ruleNames).toEqual(expect.arrayContaining(files)); + }); +}); diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index 7d8facdb4f7a..e3c7f7183a1e 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -4,10 +4,10 @@ import path from 'path'; import fs from 'fs'; import rules from '../src/rules'; -const RULE_NAME_PREFIX = '@typescript-eslint'; +const RULE_NAME_PREFIX = '@typescript-eslint/'; const MAX_RULE_NAME_LENGTH = 33 + RULE_NAME_PREFIX.length; -const allRules = Object.entries(rules); +const ruleEntries = Object.entries(rules); /** * Helper function reduces records to key - value pairs. @@ -20,7 +20,7 @@ const reducer = ( ): Record => { const key = entry[0]; const value = entry[1]; - const ruleName = `${RULE_NAME_PREFIX}/${key}`; + const ruleName = `${RULE_NAME_PREFIX}${key}`; const setting = value.meta.docs.recommended; const usedSetting = !setting ? 'warn' : setting; @@ -41,13 +41,13 @@ function generate(rules: Record, filePath: string): void { console.log('------------------------ all.json ------------------------'); generate( - allRules.reduce(reducer, {} as Record), + ruleEntries.reduce(reducer, {}), path.resolve(__dirname, '../src/configs/all.json'), ); console.log('-------------------- recommended.json --------------------'); generate( - allRules + ruleEntries .filter(entry => !!entry[1].meta.docs.recommended) .reduce(reducer, {}), path.resolve(__dirname, '../src/configs/recommended.json'), From 507c14a25990b72099fb946c1f241b7ddcd89dab Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sat, 2 Mar 2019 17:40:07 +0100 Subject: [PATCH 08/17] fix: test for Node.js 6 --- packages/eslint-plugin/tests/configs/all.test.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/tests/configs/all.test.ts b/packages/eslint-plugin/tests/configs/all.test.ts index 33c342d83309..2867fc0daf33 100644 --- a/packages/eslint-plugin/tests/configs/all.test.ts +++ b/packages/eslint-plugin/tests/configs/all.test.ts @@ -5,6 +5,13 @@ describe('all.json config', () => { const ruleNames = Object.keys(rules).map( name => `@typescript-eslint/${name}`, ); + // with end of Node.js 6 support, we can use Object.values(allConfig.rules) here + const configRules: Record = allConfig.rules; + const configRuleValues = Object.keys(configRules).map( + key => configRules[key], + ); + + Object.values(allConfig.rules); it('contains all available rule modules', () => { expect(ruleNames).toEqual( @@ -13,8 +20,6 @@ describe('all.json config', () => { }); it('has all rules enabled either with "warn" or "error"', () => { - expect(['warn', 'error']).toEqual( - expect.arrayContaining(Object.values(allConfig.rules)), - ); + expect(['warn', 'error']).toEqual(expect.arrayContaining(configRuleValues)); }); }); From 876e70c4f7fe2075530d7d510096efebf29150e2 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sat, 2 Mar 2019 21:09:08 +0100 Subject: [PATCH 09/17] fix: remove left overs --- packages/eslint-plugin/tests/configs/all.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/eslint-plugin/tests/configs/all.test.ts b/packages/eslint-plugin/tests/configs/all.test.ts index 2867fc0daf33..30189eb73aea 100644 --- a/packages/eslint-plugin/tests/configs/all.test.ts +++ b/packages/eslint-plugin/tests/configs/all.test.ts @@ -11,8 +11,6 @@ describe('all.json config', () => { key => configRules[key], ); - Object.values(allConfig.rules); - it('contains all available rule modules', () => { expect(ruleNames).toEqual( expect.arrayContaining(Object.keys(allConfig.rules)), From 883fa471c13158c128e0b5f19454b5c06039936b Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Sun, 3 Mar 2019 12:42:08 +0100 Subject: [PATCH 10/17] test: improve coverage --- packages/eslint-plugin/src/index.ts | 2 +- packages/eslint-plugin/tests/index.test.ts | 24 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin/tests/index.test.ts diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index b48d46f27ca8..d799030f49e8 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -5,7 +5,7 @@ import base from './configs/base.json'; import recommended from './configs/recommended.json'; export = { - rules: rules, + rules, configs: { all, base, diff --git a/packages/eslint-plugin/tests/index.test.ts b/packages/eslint-plugin/tests/index.test.ts new file mode 100644 index 000000000000..e1ad6361e280 --- /dev/null +++ b/packages/eslint-plugin/tests/index.test.ts @@ -0,0 +1,24 @@ +import fs from 'fs'; + +import eslintPlugin from '../src'; +import rules from '../src/rules'; + +describe('eslint-plugin ("./src/index.ts")', () => { + const ruleKeys = Object.keys(rules); + const eslintPluginRuleKeys = Object.keys(eslintPlugin.rules); + + const configs = fs + .readdirSync('./src/configs') + .filter(file => file.endsWith('.json')); + const eslintPluginConfigKeys = Object.keys(eslintPlugin.configs).map( + key => `${key}.json`, + ); + + it('exports all available rules', () => { + expect(ruleKeys).toEqual(expect.arrayContaining(eslintPluginRuleKeys)); + }); + + it('exports all available configs', () => { + expect(configs).toEqual(expect.arrayContaining(eslintPluginConfigKeys)); + }); +}); From ec021d7f2a6ce76bbcaf24e29e51eee6f05627c4 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Tue, 5 Mar 2019 21:14:10 +0100 Subject: [PATCH 11/17] feat(eslint-plugin): disable eslints "no-useless-constructor" rule --- packages/eslint-plugin/src/configs/base.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/configs/base.json b/packages/eslint-plugin/src/configs/base.json index d5ffe78aa1da..2d251dbf4c5e 100644 --- a/packages/eslint-plugin/src/configs/base.json +++ b/packages/eslint-plugin/src/configs/base.json @@ -8,6 +8,7 @@ "camelcase": "off", "indent": "off", "no-array-constructor": "off", - "no-unused-vars": "off" + "no-unused-vars": "off", + "no-useless-constructor": "off" } } From 863654ee98b91ee06c322ae10cb3e0a33be56d2b Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Thu, 7 Mar 2019 15:07:19 +0100 Subject: [PATCH 12/17] feat(eslint-plugin): add base config to generated configs --- .../eslint-plugin/tools/generate-configs.ts | 66 ++++++++++++++----- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index e3c7f7183a1e..49b93a2fe923 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -3,21 +3,32 @@ import path from 'path'; import fs from 'fs'; import rules from '../src/rules'; +import RuleModule from 'ts-eslint'; +import { Linter } from 'eslint'; const RULE_NAME_PREFIX = '@typescript-eslint/'; -const MAX_RULE_NAME_LENGTH = 33 + RULE_NAME_PREFIX.length; +const MAX_RULE_NAME_LENGTH = 32 + RULE_NAME_PREFIX.length; const ruleEntries = Object.entries(rules); +interface LinterConfigRules { + [name: string]: Linter.RuleLevel; +} + +interface LinterConfig extends Linter.Config { + extends?: string | string[]; + plugins?: string[]; +} + /** * Helper function reduces records to key - value pairs. * @param config * @param entry */ -const reducer = ( - config: Record, - entry: Record, -): Record => { +const reducer = ( + config: LinterConfigRules, + entry: [string, RuleModule], +) => { const key = entry[0]; const value = entry[1]; const ruleName = `${RULE_NAME_PREFIX}${key}`; @@ -31,24 +42,43 @@ const reducer = ( }; /** - * Helper function generates configuration. + * Helper function writes configuration. */ -function generate(rules: Record, filePath: string): void { - const config = Object.assign({ extends: './configs/base.json' }, { rules }); - +function writeConfig(config: LinterConfig, filePath: string): void { fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); } -console.log('------------------------ all.json ------------------------'); -generate( - ruleEntries.reduce(reducer, {}), - path.resolve(__dirname, '../src/configs/all.json'), -); +const baseConfig: LinterConfig = { + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + }, + plugins: ['@typescript-eslint'], + rules: { + camelcase: 'off', + indent: 'off', + 'no-array-constructor': 'off', + 'no-unused-vars': 'off', + 'no-useless-constructor': 'off', + }, +}; +writeConfig(baseConfig, path.resolve(__dirname, '../src/configs/base.json')); -console.log('-------------------- recommended.json --------------------'); -generate( - ruleEntries +console.log('------------------------- all.json -------------------------'); +const allConfig: LinterConfig = { + extends: './configs/base.json', + rules: ruleEntries.reduce(reducer, {}) as LinterConfigRules, +}; +writeConfig(allConfig, path.resolve(__dirname, '../src/configs/all.json')); + +console.log('--------------------- recommended.json ---------------------'); +const recommendedConfig: LinterConfig = { + extends: './configs/base.json', + rules: ruleEntries .filter(entry => !!entry[1].meta.docs.recommended) - .reduce(reducer, {}), + .reduce(reducer, {}) as LinterConfigRules, +}; +writeConfig( + recommendedConfig, path.resolve(__dirname, '../src/configs/recommended.json'), ); From 6b7b4352c525374e94857a6d50bf8f649abb9fce Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Fri, 15 Mar 2019 16:34:59 +0100 Subject: [PATCH 13/17] fix: remove recommendation from docs for rules not in config --- packages/eslint-plugin/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 10268b006351..2b7980cc71bc 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -113,7 +113,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive (`adjacent-overload-signatures` from TSLint) | :heavy_check_mark: | | | [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays (`array-type` from TSLint) | :heavy_check_mark: | :wrench: | | [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Enforces that types will not to be used (`ban-types` from TSLint) | :heavy_check_mark: | :wrench: | -| [`@typescript-eslint/ban-ts-ignore`](./docs/rules/ban-ts-ignore.md) | Bans “// @ts-ignore” comments from being used (`ban-ts-ignore` from TSLint) | :heavy_check_mark: | | +| [`@typescript-eslint/ban-ts-ignore`](./docs/rules/ban-ts-ignore.md) | Bans “// @ts-ignore” comments from being used (`ban-ts-ignore` from TSLint) | | | | [`@typescript-eslint/camelcase`](./docs/rules/camelcase.md) | Enforce camelCase naming convention | :heavy_check_mark: | | | [`@typescript-eslint/class-name-casing`](./docs/rules/class-name-casing.md) | Require PascalCased class and interface names (`class-name` from TSLint) | :heavy_check_mark: | | | [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | :heavy_check_mark: | | @@ -136,7 +136,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator (`no-non-null-assertion` from TSLint) | :heavy_check_mark: | | | [`@typescript-eslint/no-object-literal-type-assertion`](./docs/rules/no-object-literal-type-assertion.md) | Forbids an object literal to appear in a type assertion expression (`no-object-literal-type-assertion` from TSLint) | :heavy_check_mark: | | | [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors. (`no-parameter-properties` from TSLint) | :heavy_check_mark: | | -| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` (`no-require-imports` from TSLint) | :heavy_check_mark: | | +| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` (`no-require-imports` from TSLint) | | | | [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` (`no-this-assignment` from TSLint) | | | | [`@typescript-eslint/no-triple-slash-reference`](./docs/rules/no-triple-slash-reference.md) | Disallow `/// ` comments (`no-reference` from TSLint) | :heavy_check_mark: | | | [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases (`interface-over-type-literal` from TSLint) | | | @@ -146,10 +146,10 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | | | [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | | | [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements (`no-var-requires` from TSLint) | :heavy_check_mark: | | -| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures (`callable-types` from TSLint) | | :wrench: | +| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures (`callable-types` from TSLint) | | :wrench: | | [`@typescript-eslint/prefer-interface`](./docs/rules/prefer-interface.md) | Prefer an interface declaration over a type literal (type T = { ... }) (`interface-over-type-literal` from TSLint) | :heavy_check_mark: | :wrench: | | [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) | :heavy_check_mark: | :wrench: | -| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async. (`promise-function-async` from TSLint) | :heavy_check_mark: | | +| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async. (`promise-function-async` from TSLint) | | | | [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string. (`restrict-plus-operands` from TSLint) | | | | [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | :heavy_check_mark: | :wrench: | From 66944f812e4975f2747f687caf7c8b3a82845067 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Fri, 26 Apr 2019 16:15:31 +0200 Subject: [PATCH 14/17] feat(eslint-plugin): set rules in all.json to 'error' --- packages/eslint-plugin/src/configs/all.json | 56 +++++++++---------- .../eslint-plugin/tests/configs/all.test.ts | 4 +- .../eslint-plugin/tools/generate-configs.ts | 18 ++++-- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index a8bea22e2dbf..c426b9497977 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -3,55 +3,55 @@ "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", - "@typescript-eslint/await-thenable": "warn", - "@typescript-eslint/ban-ts-ignore": "warn", + "@typescript-eslint/await-thenable": "error", + "@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-types": "error", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", - "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/explicit-function-return-type": "error", "@typescript-eslint/explicit-member-accessibility": "error", - "@typescript-eslint/func-call-spacing": "warn", - "@typescript-eslint/generic-type-naming": "warn", + "@typescript-eslint/func-call-spacing": "error", + "@typescript-eslint/generic-type-naming": "error", "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", - "@typescript-eslint/member-naming": "warn", - "@typescript-eslint/member-ordering": "warn", + "@typescript-eslint/member-naming": "error", + "@typescript-eslint/member-ordering": "error", "@typescript-eslint/no-angle-bracket-type-assertion": "error", "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-extra-parens": "warn", - "@typescript-eslint/no-extraneous-class": "warn", - "@typescript-eslint/no-for-in-array": "warn", + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-extra-parens": "error", + "@typescript-eslint/no-extraneous-class": "error", + "@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-assertion": "error", "@typescript-eslint/no-object-literal-type-assertion": "error", "@typescript-eslint/no-parameter-properties": "error", - "@typescript-eslint/no-require-imports": "warn", - "@typescript-eslint/no-this-alias": "warn", + "@typescript-eslint/no-require-imports": "error", + "@typescript-eslint/no-this-alias": "error", "@typescript-eslint/no-triple-slash-reference": "error", - "@typescript-eslint/no-type-alias": "warn", - "@typescript-eslint/no-unnecessary-qualifier": "warn", - "@typescript-eslint/no-unnecessary-type-assertion": "warn", - "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-type-alias": "error", + "@typescript-eslint/no-unnecessary-qualifier": "error", + "@typescript-eslint/no-unnecessary-type-assertion": "error", + "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-use-before-define": "error", - "@typescript-eslint/no-useless-constructor": "warn", + "@typescript-eslint/no-useless-constructor": "error", "@typescript-eslint/no-var-requires": "error", - "@typescript-eslint/prefer-for-of": "warn", - "@typescript-eslint/prefer-function-type": "warn", - "@typescript-eslint/prefer-includes": "warn", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", + "@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-interface": "error", "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/prefer-string-starts-ends-with": "warn", - "@typescript-eslint/promise-function-async": "warn", - "@typescript-eslint/require-array-sort-compare": "warn", - "@typescript-eslint/restrict-plus-operands": "warn", - "@typescript-eslint/semi": "warn", + "@typescript-eslint/prefer-string-starts-ends-with": "error", + "@typescript-eslint/promise-function-async": "error", + "@typescript-eslint/require-array-sort-compare": "error", + "@typescript-eslint/restrict-plus-operands": "error", + "@typescript-eslint/semi": "error", "@typescript-eslint/type-annotation-spacing": "error", - "@typescript-eslint/unbound-method": "warn", - "@typescript-eslint/unified-signatures": "warn" + "@typescript-eslint/unbound-method": "error", + "@typescript-eslint/unified-signatures": "error" } } diff --git a/packages/eslint-plugin/tests/configs/all.test.ts b/packages/eslint-plugin/tests/configs/all.test.ts index 30189eb73aea..252a8fd9bde1 100644 --- a/packages/eslint-plugin/tests/configs/all.test.ts +++ b/packages/eslint-plugin/tests/configs/all.test.ts @@ -17,7 +17,7 @@ describe('all.json config', () => { ); }); - it('has all rules enabled either with "warn" or "error"', () => { - expect(['warn', 'error']).toEqual(expect.arrayContaining(configRuleValues)); + it('has all rules enabled with "error"', () => { + expect(['error']).toEqual(expect.arrayContaining(configRuleValues)); }); }); diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index 49b93a2fe923..929c3cd69712 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -8,6 +8,7 @@ import { Linter } from 'eslint'; const RULE_NAME_PREFIX = '@typescript-eslint/'; const MAX_RULE_NAME_LENGTH = 32 + RULE_NAME_PREFIX.length; +const DEFAULT_RULE_SETTING = 'warn'; const ruleEntries = Object.entries(rules); @@ -28,12 +29,18 @@ interface LinterConfig extends Linter.Config { const reducer = ( config: LinterConfigRules, entry: [string, RuleModule], + setting?: 'error' | 'warn', ) => { const key = entry[0]; const value = entry[1]; const ruleName = `${RULE_NAME_PREFIX}${key}`; - const setting = value.meta.docs.recommended; - const usedSetting = !setting ? 'warn' : setting; + + const recommendation = value.meta.docs.recommended; + const usedSetting = setting + ? setting + : !recommendation + ? DEFAULT_RULE_SETTING + : recommendation; console.log(ruleName.padEnd(MAX_RULE_NAME_LENGTH), '=', usedSetting); config[ruleName] = usedSetting; @@ -67,7 +74,10 @@ writeConfig(baseConfig, path.resolve(__dirname, '../src/configs/base.json')); console.log('------------------------- all.json -------------------------'); const allConfig: LinterConfig = { extends: './configs/base.json', - rules: ruleEntries.reduce(reducer, {}) as LinterConfigRules, + rules: ruleEntries.reduce( + (config, entry) => reducer(config, entry, 'error'), + {}, + ) as LinterConfigRules, }; writeConfig(allConfig, path.resolve(__dirname, '../src/configs/all.json')); @@ -76,7 +86,7 @@ const recommendedConfig: LinterConfig = { extends: './configs/base.json', rules: ruleEntries .filter(entry => !!entry[1].meta.docs.recommended) - .reduce(reducer, {}) as LinterConfigRules, + .reduce((config, entry) => reducer(config, entry), {}) as LinterConfigRules, }; writeConfig( recommendedConfig, From 83562a85041e4cd22f29864fb25d2a50271041e6 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Fri, 10 May 2019 16:52:19 +0200 Subject: [PATCH 15/17] fix: for manual provided config --- packages/eslint-plugin/src/configs/all.json | 1 + packages/eslint-plugin/src/rules/index.ts | 2 ++ packages/eslint-plugin/tests/index.test.ts | 9 +++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index c426b9497977..00137b32b5d7 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -25,6 +25,7 @@ "@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/no-magic-numbers": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-assertion": "error", diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 0b7def2dd8b4..8322949e054d 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -22,6 +22,7 @@ import noExtraParens from './no-extra-parens'; import noExtraneousClass from './no-extraneous-class'; import noForInArray from './no-for-in-array'; import noInferrableTypes from './no-inferrable-types'; +import noMagicNumbers from './no-magic-numbers'; import noMisusedNew from './no-misused-new'; import noNamespace from './no-namespace'; import noNonNullAssertion from './no-non-null-assertion'; @@ -76,6 +77,7 @@ export default { 'no-extraneous-class': noExtraneousClass, 'no-for-in-array': noForInArray, 'no-inferrable-types': noInferrableTypes, + 'no-magic-numbers': noMagicNumbers, 'no-misused-new': noMisusedNew, 'no-namespace': noNamespace, 'no-non-null-assertion': noNonNullAssertion, diff --git a/packages/eslint-plugin/tests/index.test.ts b/packages/eslint-plugin/tests/index.test.ts index e1ad6361e280..f852f7151036 100644 --- a/packages/eslint-plugin/tests/index.test.ts +++ b/packages/eslint-plugin/tests/index.test.ts @@ -6,19 +6,20 @@ import rules from '../src/rules'; describe('eslint-plugin ("./src/index.ts")', () => { const ruleKeys = Object.keys(rules); const eslintPluginRuleKeys = Object.keys(eslintPlugin.rules); + const manualConfigs = ['eslintRecommended']; const configs = fs .readdirSync('./src/configs') .filter(file => file.endsWith('.json')); - const eslintPluginConfigKeys = Object.keys(eslintPlugin.configs).map( - key => `${key}.json`, - ); + const eslintPluginConfigKeys = Object.keys(eslintPlugin.configs) + .filter(key => !manualConfigs.includes(key)) + .map(key => `${key}.json`); it('exports all available rules', () => { expect(ruleKeys).toEqual(expect.arrayContaining(eslintPluginRuleKeys)); }); - it('exports all available configs', () => { + it('exports all available generated configs', () => { expect(configs).toEqual(expect.arrayContaining(eslintPluginConfigKeys)); }); }); From 846c74b214afabadb5139b9dd67145c2f691cd55 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Mon, 13 May 2019 21:27:51 +0200 Subject: [PATCH 16/17] fix: remove of unbound-method as recommended in docs again --- packages/eslint-plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 22afc3659ac6..24ada799b9a6 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -161,7 +161,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string. (`restrict-plus-operands` from TSLint) | | | :thought_balloon: | | [`@typescript-eslint/semi`](./docs/rules/semi.md) | Require or disallow semicolons instead of ASI | | :wrench: | | | [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | :heavy_check_mark: | :wrench: | | -| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope. (`no-unbound-method` from TSLint) | :heavy_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope. (`no-unbound-method` from TSLint) | | | :thought_balloon: | | [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce to use `RegExp#exec` over `String#match` | | | :thought_balloon: | | [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one. (`unified-signatures` from TSLint) | | | | From ca6eb21c0f6b5fdfa7635ab1ab5af7fc98b6639a Mon Sep 17 00:00:00 2001 From: Ricky Lippmann <3674067+ldrick@users.noreply.github.com> Date: Wed, 15 May 2019 23:55:41 +0200 Subject: [PATCH 17/17] fix: all reviewed things and added deprecated filter --- packages/eslint-plugin/src/configs/all.json | 5 ++ packages/eslint-plugin/src/configs/base.json | 9 +-- .../src/configs/recommended.json | 4 ++ .../eslint-plugin/tests/configs/all.test.ts | 45 +++++++++---- .../eslint-plugin/tools/generate-configs.ts | 65 ++++++++++++------- 5 files changed, 84 insertions(+), 44 deletions(-) diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index dc6f9648aa1e..fa36e3d876ce 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -6,18 +6,21 @@ "@typescript-eslint/await-thenable": "error", "@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-types": "error", + "camelcase": "off", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", "@typescript-eslint/explicit-function-return-type": "error", "@typescript-eslint/explicit-member-accessibility": "error", "@typescript-eslint/func-call-spacing": "error", "@typescript-eslint/generic-type-naming": "error", + "indent": "off", "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", "@typescript-eslint/member-naming": "error", "@typescript-eslint/member-ordering": "error", "@typescript-eslint/no-angle-bracket-type-assertion": "error", + "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "error", @@ -37,8 +40,10 @@ "@typescript-eslint/no-type-alias": "error", "@typescript-eslint/no-unnecessary-qualifier": "error", "@typescript-eslint/no-unnecessary-type-assertion": "error", + "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-use-before-define": "error", + "no-useless-constructor": "off", "@typescript-eslint/no-useless-constructor": "error", "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/prefer-for-of": "error", diff --git a/packages/eslint-plugin/src/configs/base.json b/packages/eslint-plugin/src/configs/base.json index 2d251dbf4c5e..9b6931ad616d 100644 --- a/packages/eslint-plugin/src/configs/base.json +++ b/packages/eslint-plugin/src/configs/base.json @@ -3,12 +3,5 @@ "parserOptions": { "sourceType": "module" }, - "plugins": ["@typescript-eslint"], - "rules": { - "camelcase": "off", - "indent": "off", - "no-array-constructor": "off", - "no-unused-vars": "off", - "no-useless-constructor": "off" - } + "plugins": ["@typescript-eslint"] } diff --git a/packages/eslint-plugin/src/configs/recommended.json b/packages/eslint-plugin/src/configs/recommended.json index f3c9b911026d..12edb521fe8f 100644 --- a/packages/eslint-plugin/src/configs/recommended.json +++ b/packages/eslint-plugin/src/configs/recommended.json @@ -4,14 +4,17 @@ "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", "@typescript-eslint/ban-types": "error", + "camelcase": "off", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/explicit-member-accessibility": "error", + "indent": "off", "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", "@typescript-eslint/no-angle-bracket-type-assertion": "error", + "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "warn", @@ -22,6 +25,7 @@ "@typescript-eslint/no-object-literal-type-assertion": "error", "@typescript-eslint/no-parameter-properties": "error", "@typescript-eslint/no-triple-slash-reference": "error", + "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-var-requires": "error", diff --git a/packages/eslint-plugin/tests/configs/all.test.ts b/packages/eslint-plugin/tests/configs/all.test.ts index 252a8fd9bde1..425e3a1426a4 100644 --- a/packages/eslint-plugin/tests/configs/all.test.ts +++ b/packages/eslint-plugin/tests/configs/all.test.ts @@ -1,23 +1,46 @@ import rules from '../../src/rules'; import allConfig from '../../src/configs/all.json'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + +interface IndexRules { + [name: string]: TSESLint.RuleModule; +} +interface JsonRules { + [name: string]: string; +} describe('all.json config', () => { - const ruleNames = Object.keys(rules).map( - name => `@typescript-eslint/${name}`, + const RULE_NAME_PREFIX = '@typescript-eslint/'; + + const typedRules: IndexRules = rules; + const notDeprecatedRuleNames = Object.keys(typedRules).reduce( + (collection, name) => { + if (!typedRules[name].meta.deprecated) { + collection.push(`${RULE_NAME_PREFIX}${name}`); + } + return collection; + }, + [], ); - // with end of Node.js 6 support, we can use Object.values(allConfig.rules) here - const configRules: Record = allConfig.rules; - const configRuleValues = Object.keys(configRules).map( - key => configRules[key], + + // with end of Node.js 6 support, we can use Object.entries(allConfig.rules) here + const configRules: JsonRules = allConfig.rules; + const typescriptEslintConfigRules = Object.keys(configRules).filter(name => + name.startsWith(RULE_NAME_PREFIX), + ); + const typescriptEslintConfigRuleValues = typescriptEslintConfigRules.map( + name => configRules[name], ); - it('contains all available rule modules', () => { - expect(ruleNames).toEqual( - expect.arrayContaining(Object.keys(allConfig.rules)), + it('contains all @typescript-eslint/eslint-plugin rule modules, except the deprecated ones', () => { + expect(notDeprecatedRuleNames).toEqual( + expect.arrayContaining(typescriptEslintConfigRules), ); }); - it('has all rules enabled with "error"', () => { - expect(['error']).toEqual(expect.arrayContaining(configRuleValues)); + it('has all containing @typescript-eslint/eslint-plugin rules enabled with "error"', () => { + expect(['error']).toEqual( + expect.arrayContaining(typescriptEslintConfigRuleValues), + ); }); }); diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index e5d9a1d11c27..4c29753a048d 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -1,19 +1,13 @@ /* eslint-disable no-console */ -import path from 'path'; +import { Linter } from 'eslint'; import fs from 'fs'; -import rules from '../src/rules'; +import path from 'path'; import { TSESLint } from '@typescript-eslint/experimental-utils'; -import { Linter } from 'eslint'; - -const RULE_NAME_PREFIX = '@typescript-eslint/'; -const MAX_RULE_NAME_LENGTH = 32 + RULE_NAME_PREFIX.length; -const DEFAULT_RULE_SETTING = 'warn'; - -const ruleEntries = Object.entries(rules); +import rules from '../src/rules'; interface LinterConfigRules { - [name: string]: Linter.RuleLevel; + [name: string]: Linter.RuleLevel | Linter.RuleLevelAndOptions; } interface LinterConfig extends Linter.Config { @@ -21,6 +15,19 @@ interface LinterConfig extends Linter.Config { plugins?: string[]; } +const RULE_NAME_PREFIX = '@typescript-eslint/'; +const MAX_RULE_NAME_LENGTH = 32 + RULE_NAME_PREFIX.length; +const DEFAULT_RULE_SETTING = 'warn'; +const BASE_RULES_TO_BE_OVERRIDDEN = new Set([ + 'camelcase', + 'indent', + 'no-array-constructor', + 'no-unused-vars', + 'no-useless-constructor', +]); + +const ruleEntries = Object.entries(rules); + /** * Helper function reduces records to key - value pairs. * @param config @@ -29,19 +36,30 @@ interface LinterConfig extends Linter.Config { const reducer = ( config: LinterConfigRules, entry: [string, TSESLint.RuleModule], - setting?: 'error' | 'warn', + settings: { + errorLevel?: 'error' | 'warn'; + filterDeprecated: boolean; + }, ) => { const key = entry[0]; const value = entry[1]; - const ruleName = `${RULE_NAME_PREFIX}${key}`; + if (settings.filterDeprecated && value.meta.deprecated) { + return config; + } + + const ruleName = `${RULE_NAME_PREFIX}${key}`; const recommendation = value.meta.docs.recommended; - const usedSetting = setting - ? setting + const usedSetting = settings.errorLevel + ? settings.errorLevel : !recommendation ? DEFAULT_RULE_SETTING : recommendation; + if (BASE_RULES_TO_BE_OVERRIDDEN.has(key)) { + console.log(key.padEnd(MAX_RULE_NAME_LENGTH), '=', 'off'); + config[key] = 'off'; + } console.log(ruleName.padEnd(MAX_RULE_NAME_LENGTH), '=', usedSetting); config[ruleName] = usedSetting; @@ -61,23 +79,17 @@ const baseConfig: LinterConfig = { sourceType: 'module', }, plugins: ['@typescript-eslint'], - rules: { - camelcase: 'off', - indent: 'off', - 'no-array-constructor': 'off', - 'no-unused-vars': 'off', - 'no-useless-constructor': 'off', - }, }; writeConfig(baseConfig, path.resolve(__dirname, '../src/configs/base.json')); console.log('------------------------- all.json -------------------------'); const allConfig: LinterConfig = { extends: './configs/base.json', - rules: ruleEntries.reduce( - (config, entry) => reducer(config, entry, 'error'), + rules: ruleEntries.reduce( + (config, entry) => + reducer(config, entry, { errorLevel: 'error', filterDeprecated: true }), {}, - ) as LinterConfigRules, + ), }; writeConfig(allConfig, path.resolve(__dirname, '../src/configs/all.json')); @@ -86,7 +98,10 @@ const recommendedConfig: LinterConfig = { extends: './configs/base.json', rules: ruleEntries .filter(entry => !!entry[1].meta.docs.recommended) - .reduce((config, entry) => reducer(config, entry), {}) as LinterConfigRules, + .reduce( + (config, entry) => reducer(config, entry, { filterDeprecated: true }), + {}, + ), }; writeConfig( recommendedConfig,