Skip to content

Commit e325b72

Browse files
golopotbradzacher
authored andcommitted
feat(eslint-plugin): [ban-types] Support namespaced type (typescript-eslint#616)
1 parent 606fc70 commit e325b72

File tree

2 files changed

+119
-36
lines changed

2 files changed

+119
-36
lines changed

packages/eslint-plugin/src/rules/ban-types.ts

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
TSESLint,
3-
TSESTree,
4-
AST_NODE_TYPES,
5-
} from '@typescript-eslint/experimental-utils';
1+
import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
62
import * as util from '../util';
73

84
type Options = [
@@ -20,6 +16,31 @@ type Options = [
2016
];
2117
type MessageIds = 'bannedTypeMessage';
2218

19+
function stringifyTypeName(
20+
node: TSESTree.EntityName,
21+
sourceCode: TSESLint.SourceCode,
22+
): string {
23+
return sourceCode.getText(node).replace(/ /g, '');
24+
}
25+
26+
function getCustomMessage(
27+
bannedType: null | string | { message?: string; fixWith?: string },
28+
) {
29+
if (bannedType === null) {
30+
return '';
31+
}
32+
33+
if (typeof bannedType === 'string') {
34+
return ` ${bannedType}`;
35+
}
36+
37+
if (bannedType.message) {
38+
return ` ${bannedType.message}`;
39+
}
40+
41+
return '';
42+
}
43+
2344
export default util.createRule<Options, MessageIds>({
2445
name: 'ban-types',
2546
meta: {
@@ -87,39 +108,23 @@ export default util.createRule<Options, MessageIds>({
87108
],
88109
create(context, [{ types: bannedTypes }]) {
89110
return {
90-
'TSTypeReference Identifier'(node: TSESTree.Identifier) {
91-
if (
92-
node.parent &&
93-
node.parent.type !== AST_NODE_TYPES.TSQualifiedName
94-
) {
95-
if (node.name in bannedTypes) {
96-
let customMessage = '';
97-
const bannedCfgValue = bannedTypes[node.name];
111+
TSTypeReference({ typeName }) {
112+
const name = stringifyTypeName(typeName, context.getSourceCode());
98113

99-
let fix: TSESLint.ReportFixFunction | null = null;
114+
if (name in bannedTypes) {
115+
const bannedType = bannedTypes[name];
116+
const customMessage = getCustomMessage(bannedType);
117+
const fixWith = bannedType && (bannedType as any).fixWith;
100118

101-
if (typeof bannedCfgValue === 'string') {
102-
customMessage += ` ${bannedCfgValue}`;
103-
} else if (bannedCfgValue !== null) {
104-
if (bannedCfgValue.message) {
105-
customMessage += ` ${bannedCfgValue.message}`;
106-
}
107-
if (bannedCfgValue.fixWith) {
108-
const fixWith = bannedCfgValue.fixWith;
109-
fix = fixer => fixer.replaceText(node, fixWith);
110-
}
111-
}
112-
113-
context.report({
114-
node,
115-
messageId: 'bannedTypeMessage',
116-
data: {
117-
name: node.name,
118-
customMessage,
119-
},
120-
fix,
121-
});
122-
}
119+
context.report({
120+
node: typeName,
121+
messageId: 'bannedTypeMessage',
122+
data: {
123+
name: name,
124+
customMessage,
125+
},
126+
fix: fixWith ? fixer => fixer.replaceText(typeName, fixWith) : null,
127+
});
123128
}
124129
},
125130
};

packages/eslint-plugin/tests/rules/ban-types.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ const options: InferOptionsTypeFromRule<typeof rule> = [
1616
Object: "Use '{}' instead.",
1717
Array: null,
1818
F: null,
19+
'NS.Bad': {
20+
message: 'Use NS.Good instead.',
21+
fixWith: 'NS.Good',
22+
},
1923
},
2024
},
2125
];
@@ -39,6 +43,14 @@ ruleTester.run('ban-types', rule, {
3943
code: 'let e: foo.String;',
4044
options,
4145
},
46+
{
47+
code: 'let a: _.NS.Bad',
48+
options,
49+
},
50+
{
51+
code: 'let a: NS.Bad._',
52+
options,
53+
},
4254
],
4355
invalid: [
4456
{
@@ -56,6 +68,25 @@ ruleTester.run('ban-types', rule, {
5668
],
5769
options,
5870
},
71+
{
72+
code: 'let aa: Foo;',
73+
errors: [
74+
{
75+
messageId: 'bannedTypeMessage',
76+
data: {
77+
name: 'Foo',
78+
customMessage: '',
79+
},
80+
},
81+
],
82+
options: [
83+
{
84+
types: {
85+
Foo: { message: '' },
86+
},
87+
},
88+
],
89+
},
5990
{
6091
code: 'let b: {c: String};',
6192
output: 'let b: {c: string};',
@@ -217,5 +248,52 @@ class Foo<F = string> extends Bar<string> implements Baz<Object> {
217248
],
218249
options,
219250
},
251+
{
252+
code: 'let a: NS.Bad;',
253+
output: 'let a: NS.Good;',
254+
errors: [
255+
{
256+
messageId: 'bannedTypeMessage',
257+
data: {
258+
name: 'NS.Bad',
259+
customMessage: ' Use NS.Good instead.',
260+
},
261+
line: 1,
262+
column: 8,
263+
},
264+
],
265+
options,
266+
},
267+
{
268+
code: `
269+
let a: NS.Bad<Foo>;
270+
let b: Foo<NS.Bad>;
271+
`,
272+
output: `
273+
let a: NS.Good<Foo>;
274+
let b: Foo<NS.Good>;
275+
`,
276+
errors: [
277+
{
278+
messageId: 'bannedTypeMessage',
279+
data: {
280+
name: 'NS.Bad',
281+
customMessage: ' Use NS.Good instead.',
282+
},
283+
line: 2,
284+
column: 8,
285+
},
286+
{
287+
messageId: 'bannedTypeMessage',
288+
data: {
289+
name: 'NS.Bad',
290+
customMessage: ' Use NS.Good instead.',
291+
},
292+
line: 3,
293+
column: 12,
294+
},
295+
],
296+
options,
297+
},
220298
],
221299
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy