Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat(eslint-plugin): add rule
ban-tslint-comment
(#2140)
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
- Loading branch information
1 parent
9b51c44
commit 43ee226
Showing
6 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Bans `// tslint:<rule-flag>` comments from being used (`ban-tslint-comment`) | ||
|
||
Useful when migrating from TSLint to ESLint. Once TSLint has been removed, this rule helps locate TSLint annotations (e.g. `// tslint:disable`). | ||
|
||
## Rule Details | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
All TSLint [rule flags](https://palantir.github.io/tslint/usage/rule-flags/) | ||
|
||
```js | ||
/* tslint:disable */ | ||
/* tslint:enable */ | ||
/* tslint:disable:rule1 rule2 rule3... */ | ||
/* tslint:enable:rule1 rule2 rule3... */ | ||
// tslint:disable-next-line | ||
someCode(); // tslint:disable-line | ||
// tslint:disable-next-line:rule1 rule2 rule3... | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
// This is a comment that just happens to mention tslint | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
If you are still using TSLint. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { AST_TOKEN_TYPES } from '@typescript-eslint/experimental-utils'; | ||
import * as util from '../util'; | ||
|
||
// tslint regex | ||
// https://github.com/palantir/tslint/blob/95d9d958833fd9dc0002d18cbe34db20d0fbf437/src/enableDisableRules.ts#L32 | ||
const ENABLE_DISABLE_REGEX = /^\s*tslint:(enable|disable)(?:-(line|next-line))?(:|\s|$)/; | ||
|
||
const toText = ( | ||
text: string, | ||
type: AST_TOKEN_TYPES.Line | AST_TOKEN_TYPES.Block, | ||
): string => | ||
type === AST_TOKEN_TYPES.Line | ||
? ['//', text.trim()].join(' ') | ||
: ['/*', text.trim(), '*/'].join(' '); | ||
|
||
export default util.createRule({ | ||
name: 'ban-tslint-comment', | ||
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: 'Bans `// tslint:<rule-flag>` comments from being used', | ||
category: 'Stylistic Issues', | ||
recommended: false, | ||
}, | ||
messages: { | ||
commentDetected: 'tslint comment detected: "{{ text }}"', | ||
}, | ||
schema: [], | ||
fixable: 'code', | ||
}, | ||
defaultOptions: [], | ||
create: context => { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
Program(): void { | ||
const comments = sourceCode.getAllComments(); | ||
comments.forEach(c => { | ||
if (ENABLE_DISABLE_REGEX.test(c.value)) { | ||
context.report({ | ||
data: { text: toText(c.value, c.type) }, | ||
node: c, | ||
messageId: 'commentDetected', | ||
fix(fixer) { | ||
const rangeStart = sourceCode.getIndexFromLoc({ | ||
column: c.loc.start.column > 0 ? c.loc.start.column - 1 : 0, | ||
line: c.loc.start.line, | ||
}); | ||
const rangeEnd = sourceCode.getIndexFromLoc({ | ||
column: c.loc.end.column, | ||
line: c.loc.end.line, | ||
}); | ||
return fixer.removeRange([rangeStart, rangeEnd + 1]); | ||
}, | ||
}); | ||
} | ||
}); | ||
}, | ||
}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
packages/eslint-plugin/tests/rules/ban-tslint-comment.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import rule from '../../src/rules/ban-tslint-comment'; | ||
import { RuleTester } from '../RuleTester'; | ||
|
||
interface Testable { | ||
code: string; | ||
text?: string; | ||
column?: number; | ||
line?: number; | ||
output?: string; | ||
} | ||
|
||
const PALANTIR_EXAMPLES: Testable[] = [ | ||
{ code: '/* tslint:disable */' }, // Disable all rules for the rest of the file | ||
{ code: '/* tslint:enable */' }, // Enable all rules for the rest of the file | ||
{ | ||
code: '/* tslint:disable:rule1 rule2 rule3... */', | ||
}, // Disable the listed rules for the rest of the file | ||
{ | ||
code: '/* tslint:enable:rule1 rule2 rule3... */', | ||
}, // Enable the listed rules for the rest of the file | ||
{ code: '// tslint:disable-next-line' }, // Disables all rules for the following line | ||
{ | ||
code: 'someCode(); // tslint:disable-line', | ||
text: '// tslint:disable-line', | ||
column: 13, | ||
output: 'someCode();', | ||
}, // Disables all rules for the current line | ||
{ | ||
code: '// tslint:disable-next-line:rule1 rule2 rule3...', | ||
}, // Disables the listed rules for the next line | ||
]; | ||
|
||
// prettier-ignore | ||
const MORE_EXAMPLES: Testable[] = [ | ||
{ | ||
code: `const woah = doSomeStuff(); | ||
// tslint:disable-line | ||
console.log(woah); | ||
`, | ||
output: `const woah = doSomeStuff(); | ||
console.log(woah); | ||
`, | ||
text: '// tslint:disable-line', | ||
line: 2, | ||
}, | ||
] | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: '@typescript-eslint/parser', | ||
}); | ||
|
||
ruleTester.run('ban-tslint-comment', rule, { | ||
valid: [ | ||
{ | ||
code: 'let a: readonly any[] = [];', | ||
}, | ||
{ | ||
code: 'let a = new Array();', | ||
}, | ||
{ | ||
code: '// some other comment', | ||
}, | ||
{ | ||
code: '// TODO: this is a comment that mentions tslint', | ||
}, | ||
{ | ||
code: '/* another comment that mentions tslint */', | ||
}, | ||
], | ||
invalid: [...PALANTIR_EXAMPLES, ...MORE_EXAMPLES].map( | ||
({ code, column, line, output, text }) => ({ | ||
code, | ||
output: output ?? '', | ||
errors: [ | ||
{ | ||
column: column ?? 1, | ||
line: line ?? 1, | ||
data: { text: text ?? code }, | ||
messageId: 'commentDetected' as const, | ||
}, | ||
], | ||
}), | ||
), | ||
}); |