From 0fe781edd4e803eba7c566c48fa6607c4d400090 Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Thu, 14 Feb 2019 16:31:52 +0100 Subject: [PATCH 1/2] feat(eslint-plugin): add ban-ts-ignore rule --- packages/eslint-plugin/README.md | 1 + packages/eslint-plugin/ROADMAP.md | 3 +- .../eslint-plugin/docs/rules/ban-ts-ignore.md | 37 +++++++++++++ .../eslint-plugin/src/rules/ban-ts-ignore.ts | 47 ++++++++++++++++ .../tests/rules/ban-ts-ignore.test.ts | 53 +++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin/docs/rules/ban-ts-ignore.md create mode 100644 packages/eslint-plugin/src/rules/ban-ts-ignore.ts create mode 100644 packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 79fdeb0fb969..10268b006351 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -113,6 +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/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: | | diff --git a/packages/eslint-plugin/ROADMAP.md b/packages/eslint-plugin/ROADMAP.md index 59a1c037f7d1..ed02d8b50c38 100644 --- a/packages/eslint-plugin/ROADMAP.md +++ b/packages/eslint-plugin/ROADMAP.md @@ -13,7 +13,7 @@ | TSLint rule | | ESLint rule | | --------------------------------- | :-: | ---------------------------------------------------- | | [`adjacent-overload-signatures`] | ✅ | [`@typescript-eslint/adjacent-overload-signatures`] | -| [`ban-ts-ignore`] | 🛑 | N/A | +| [`ban-ts-ignore`] | ✅ | [`@typescript-eslint/ban-ts-ignore`] | | [`ban-types`] | ✅ | [`@typescript-eslint/ban-types`] | | [`member-access`] | ✅ | [`@typescript-eslint/explicit-member-accessibility`] | | [`member-ordering`] | ✅ | [`@typescript-eslint/member-ordering`] | @@ -575,6 +575,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [`@typescript-eslint/adjacent-overload-signatures`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md [`@typescript-eslint/ban-types`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md +[`@typescript-eslint/ban-ts-ignore`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-ignore.md [`@typescript-eslint/explicit-member-accessibility`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md [`@typescript-eslint/member-ordering`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-ordering.md [`@typescript-eslint/no-explicit-any`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md diff --git a/packages/eslint-plugin/docs/rules/ban-ts-ignore.md b/packages/eslint-plugin/docs/rules/ban-ts-ignore.md new file mode 100644 index 000000000000..7480d044d950 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/ban-ts-ignore.md @@ -0,0 +1,37 @@ +# Bans “// @ts-ignore” comments from being used (ban-ts-ignore) + +Suppressing Typescript Compiler Errors can be hard to discover. + +## Rule Details + +Does not allow the use of `// @ts-ignore` comments. + +The following patterns are considered warnings: + +```ts +if (false) { + // @ts-ignore: Unreachable code error + console.log('hello'); +} +``` + +The following patterns are not warnings: + +```ts +if (false) { + // Compiler warns about unreachable code error + console.log('hello'); +} +``` + +## When Not To Use It + +If you are sure, compiler errors won't affect functionality and you need to disable them. + +## Further Reading + +- TypeScript [Type Checking JavaScript Files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html) + +## Compatibility + +- TSLint: [ban-ts-ignore](https://palantir.github.io/tslint/rules/ban-ts-ignore/) diff --git a/packages/eslint-plugin/src/rules/ban-ts-ignore.ts b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts new file mode 100644 index 000000000000..4dc9b032ba68 --- /dev/null +++ b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts @@ -0,0 +1,47 @@ +/** + * @fileoverview Bans “// @ts-ignore” comments from being used. + * @author Ricky Lippmann + */ + +import * as util from '../util'; + +export default util.createRule({ + name: 'ban-ts-ignore', + meta: { + type: 'problem', + docs: { + description: 'Bans “// @ts-ignore” comments from being used.', + tslintRuleName: 'ban-ts-ignore', + category: 'Best Practices', + recommended: 'error' + }, + schema: [], + messages: { + tsIgnoreComment: + 'Do not use "// @ts-ignore" comments because they suppress compilation errors.' + } + }, + defaultOptions: [], + create(context) { + const tsIgnoreRegExp = /^\/*\s*@ts-ignore/; + const sourceCode = context.getSourceCode(); + + return { + Program(): void { + const comments = sourceCode.getAllComments(); + + comments.forEach(comment => { + if (comment.type !== 'Line') { + return; + } + if (tsIgnoreRegExp.test(comment.value)) { + context.report({ + node: comment, + messageId: 'tsIgnoreComment' + }); + } + }); + } + }; + } +}); diff --git a/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts b/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts new file mode 100644 index 000000000000..896c195d8ac9 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts @@ -0,0 +1,53 @@ +import rule from '../../src/rules/ban-ts-ignore'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser' +}); + +ruleTester.run('ban-ts-ignore', rule, { + valid: [ + `// just a comment containing @ts-ignore somewhere`, + `/* +// @ts-ignore in a block +*/` + ], + invalid: [ + { + code: '// @ts-ignore: Suppress next line', + errors: [ + { + messageId: 'tsIgnoreComment', + line: 1, + column: 1 + } + ] + }, + { + code: '/////@ts-ignore: Suppress next line', + errors: [ + { + messageId: 'tsIgnoreComment', + line: 1, + column: 1 + } + ] + }, + { + code: ` +if (false) { + // @ts-ignore: Unreachable code error + console.log("hello"); +} + `, + parser: '@typescript-eslint/parser', + errors: [ + { + messageId: 'tsIgnoreComment', + line: 3, + column: 3 + } + ] + } + ] +}); From 3c814e6dac460d8ebaa7a20560cd2f55ea232a5c Mon Sep 17 00:00:00 2001 From: Ricky Lippmann Date: Thu, 14 Feb 2019 17:19:33 +0100 Subject: [PATCH 2/2] test(eslint-plugin): add more tests --- .../eslint-plugin/tests/rules/ban-ts-ignore.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts b/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts index 896c195d8ac9..807d1ee017dc 100644 --- a/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts +++ b/packages/eslint-plugin/tests/rules/ban-ts-ignore.test.ts @@ -8,11 +8,23 @@ const ruleTester = new RuleTester({ ruleTester.run('ban-ts-ignore', rule, { valid: [ `// just a comment containing @ts-ignore somewhere`, + `/* @ts-ignore */`, + `/** @ts-ignore */`, `/* // @ts-ignore in a block */` ], invalid: [ + { + code: '// @ts-ignore', + errors: [ + { + messageId: 'tsIgnoreComment', + line: 1, + column: 1 + } + ] + }, { code: '// @ts-ignore: Suppress next line', errors: [