From 37d0d51fdad0bdd27c7e27e364c6dc2c18f1c377 Mon Sep 17 00:00:00 2001 From: moulikcipherX Date: Wed, 12 Jun 2019 01:22:18 +0530 Subject: [PATCH 1/7] Added Fix for no-explicit-any --- packages/eslint-plugin/src/rules/no-explicit-any.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 541b0acb1df1..432d1d1e47c7 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -9,6 +9,7 @@ export default util.createRule({ category: 'Best Practices', recommended: 'warn', }, + fixable: "code", messages: { unexpectedAny: 'Unexpected any. Specify a different type.', }, @@ -21,6 +22,9 @@ export default util.createRule({ context.report({ node, messageId: 'unexpectedAny', + fix(fixer) { + return fixer.replaceText(node,"unknown"); + } }); }, }; From 9c18c398603924d4d9a68341a1d0432aea8c4611 Mon Sep 17 00:00:00 2001 From: moulikcipherX Date: Thu, 13 Jun 2019 01:23:07 +0530 Subject: [PATCH 2/7] Formatted code --- packages/eslint-plugin/src/rules/no-explicit-any.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 432d1d1e47c7..16d95051b4ce 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -9,7 +9,7 @@ export default util.createRule({ category: 'Best Practices', recommended: 'warn', }, - fixable: "code", + fixable: 'code', messages: { unexpectedAny: 'Unexpected any. Specify a different type.', }, @@ -23,8 +23,8 @@ export default util.createRule({ node, messageId: 'unexpectedAny', fix(fixer) { - return fixer.replaceText(node,"unknown"); - } + return fixer.replaceText(node, 'unknown'); + }, }); }, }; From b985c7a5b3135a4b316b5917e0b49a16f6c6d083 Mon Sep 17 00:00:00 2001 From: moulikcipherX Date: Sat, 15 Jun 2019 11:39:58 +0530 Subject: [PATCH 3/7] Added fixToUnknown as ruleFix --- .../src/rules/no-explicit-any.ts | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 16d95051b4ce..00a629dfe834 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -1,6 +1,14 @@ import * as util from '../util'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; -export default util.createRule({ +type Options = [ + { + fixToUnknown: boolean; + } +]; +type MessageIds = 'unexpectedAny'; + +export default util.createRule({ name: 'no-explicit-any', meta: { type: 'suggestion', @@ -13,18 +21,36 @@ export default util.createRule({ messages: { unexpectedAny: 'Unexpected any. Specify a different type.', }, - schema: [], + schema: [ + { + type: 'object', + properties: { + fixToUnknown: { + type: 'boolean', + }, + }, + }, + ], }, - defaultOptions: [], - create(context) { + defaultOptions: [ + { + fixToUnknown: false, + }, + ], + + create(context, [option]) { return { TSAnyKeyword(node) { + let fix: TSESLint.ReportFixFunction | null = null; + + if (option.fixToUnknown) { + fix = fixer => fixer.replaceText(node, 'unknown'); + } + context.report({ node, messageId: 'unexpectedAny', - fix(fixer) { - return fixer.replaceText(node, 'unknown'); - }, + fix, }); }, }; From 0cd69ac47e005c45d86160549bf62c869901f65c Mon Sep 17 00:00:00 2001 From: moulikcipherX Date: Sat, 15 Jun 2019 15:11:02 +0530 Subject: [PATCH 4/7] Updated Docs --- packages/eslint-plugin/README.md | 2 +- .../eslint-plugin/docs/rules/no-explicit-any.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index ff6a11b3726e..eb2955b5f2bb 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -143,7 +143,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/no-angle-bracket-type-assertion`](./docs/rules/no-angle-bracket-type-assertion.md) | Enforces the use of `as Type` assertions instead of `` assertions | :heavy_check_mark: | | | | [`@typescript-eslint/no-array-constructor`](./docs/rules/no-array-constructor.md) | Disallow generic `Array` constructors | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :heavy_check_mark: | | | -| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :heavy_check_mark: | | | +| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-extra-parens`](./docs/rules/no-extra-parens.md) | Disallow unnecessary parentheses | | :wrench: | | | [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | | [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately. | | | :thought_balloon: | diff --git a/packages/eslint-plugin/docs/rules/no-explicit-any.md b/packages/eslint-plugin/docs/rules/no-explicit-any.md index 2439f43c2f3f..e62483cbddee 100644 --- a/packages/eslint-plugin/docs/rules/no-explicit-any.md +++ b/packages/eslint-plugin/docs/rules/no-explicit-any.md @@ -87,6 +87,21 @@ function greet(param: Array): string {} function greet(param: Array): Array {} ``` +## Options + +The rule accepts an options object with the following properties: + +```ts +type Options = { + // if true, only when fix any to unknown + fixToUnknown: boolean; +}; + +const defaults = { + fixToUnknwon: false, +}; +``` + ## When Not To Use It If an unknown type or a library without typings is used From 6df937d43bd4dd8cefe6dedcdc29dcecf89aedbb Mon Sep 17 00:00:00 2001 From: moulikcipherX Date: Fri, 21 Jun 2019 03:16:22 +0530 Subject: [PATCH 5/7] Fix Typos --- packages/eslint-plugin/docs/rules/no-explicit-any.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-explicit-any.md b/packages/eslint-plugin/docs/rules/no-explicit-any.md index e62483cbddee..35ff13165532 100644 --- a/packages/eslint-plugin/docs/rules/no-explicit-any.md +++ b/packages/eslint-plugin/docs/rules/no-explicit-any.md @@ -93,12 +93,12 @@ The rule accepts an options object with the following properties: ```ts type Options = { - // if true, only when fix any to unknown + // if true, auto-fixing will be made available in which the "any" type is converted to an "unknown" type fixToUnknown: boolean; }; const defaults = { - fixToUnknwon: false, + fixToUnknown: false, }; ``` From 78e96b6fe1d034b2a8a68c620b686dff23a94cca Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Thu, 20 Jun 2019 16:33:36 -0700 Subject: [PATCH 6/7] fix missing type --- packages/eslint-plugin/src/rules/no-explicit-any.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 6637285b6260..ebc980a8b03f 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -8,6 +8,7 @@ import { TSESLint } from '@typescript-eslint/experimental-utils'; type Options = [ { fixToUnknown: boolean; + ignoreRestArgs: boolean; } ]; type MessageIds = 'unexpectedAny'; From 0e57f7beca697a82ce8a1676fe3c3daf5961d806 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Thu, 27 Jun 2019 21:35:25 -0700 Subject: [PATCH 7/7] reuse invalid tests to test fixer --- .../src/rules/no-explicit-any.ts | 4 +-- .../tests/rules/no-explicit-any.test.ts | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 363f7fb841cd..f5a555933615 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -5,13 +5,13 @@ import { import * as util from '../util'; import { TSESLint } from '@typescript-eslint/experimental-utils'; -type Options = [ +export type Options = [ { fixToUnknown?: boolean; ignoreRestArgs?: boolean; } ]; -type MessageIds = 'unexpectedAny'; +export type MessageIds = 'unexpectedAny'; export default util.createRule({ name: 'no-explicit-any', diff --git a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts index cf596ffecbc3..b27cc8111bc0 100644 --- a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts +++ b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts @@ -1,5 +1,8 @@ -import rule from '../../src/rules/no-explicit-any'; +import rule, { MessageIds, Options } from '../../src/rules/no-explicit-any'; import { RuleTester } from '../RuleTester'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + +type InvalidTestCase = TSESLint.InvalidTestCase; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -187,7 +190,7 @@ type obj = { options: [{ ignoreRestArgs: true }], }, ], - invalid: [ + invalid: ([ { code: 'const number: any = 1', errors: [ @@ -784,5 +787,23 @@ type obj = { }, ], }, - ], + ] as InvalidTestCase[]).reduce((acc, testCase) => { + acc.push(testCase); + const options = testCase.options || []; + const code = `// fixToUnknown: true\n${testCase.code}`; + acc.push({ + code, + output: code.replace(/any/g, 'unknown'), + options: [{ ...options[0], fixToUnknown: true }], + errors: testCase.errors.map(err => { + if (err.line === undefined) { + return err; + } + + return { ...err, line: err.line + 1 }; + }), + }); + + return acc; + }, []), });