generated from rdlabo/typescript-template-eslint-plugin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdeny-constructor-di.ts
125 lines (115 loc) · 3.88 KB
/
deny-constructor-di.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { TSESLint } from '@typescript-eslint/utils';
import { AST } from 'eslint';
import Token = AST.Token;
const rule: TSESLint.RuleModule<'denyConstructorDI', []> = {
meta: {
docs: {
description:
'This plugin disallows Dependency Injection within the constructor.',
url: '',
},
fixable: 'code',
messages: {
denyConstructorDI:
'Dependency Injection within the constructor is not allowed.',
},
schema: [],
type: 'problem',
},
defaultOptions: [],
create: (context) => ({
Program(node) {
if (node.tokens) {
const decorator = node.tokens.find((token, index) => {
return (
token.type === 'Punctuator' &&
token.value === '@' &&
node.tokens![index + 1].type === 'Identifier' &&
['Component', 'Injectable', 'Directive', 'Pipe'].includes(
node.tokens![index + 1].value
)
);
});
if (!decorator) {
return;
}
const constructor = node.tokens.find(
(token) => token.value === 'constructor'
);
if (constructor) {
const startLine = constructor.loc.start.line;
const openToken = node.tokens
.filter((token) => token.loc.start.line >= startLine)
.find((token) => token.value === '(');
const closeToken = node.tokens
.filter((token) => token.loc.start.line >= startLine)
.find((token) => token.value === ')');
const openIndex = node.tokens.findIndex(
(token) => token === openToken
);
const closeIndex = node.tokens.findIndex(
(token) => token === closeToken
);
if (openToken && closeToken) {
const diToken = node.tokens.filter(
(token, index) =>
index > openIndex &&
index < closeIndex &&
(['Identifier', 'Keyword'].includes(token.type) ||
['<', '>'].includes(token.value))
);
if (diToken && diToken.length > 0) {
const codes: string[] = [];
let temporaryToken: Token[] = [];
let continueFlg = true;
for (let i = 0; i < diToken.length; i++) {
if (diToken[i]?.value === '<') {
continueFlg = false;
}
if (diToken[i - 1]?.value === '>') {
continueFlg = true;
}
if (!continueFlg) {
continue;
}
temporaryToken.push(diToken[i] as Token);
if (
temporaryToken.filter(
(d) => d.type === 'Identifier' && d.value !== 'readonly'
).length === 2
) {
const token: string[] = temporaryToken.map((d) => {
if (
temporaryToken.filter(
(di) =>
di.type === 'Identifier' && di.value !== 'readonly'
)[1].value === d.value
) {
return `= inject(${d.value});`;
}
return d.value;
});
codes.push(token.join(' '));
temporaryToken = [];
}
}
codes.push('');
codes.push('constructor(');
context.report({
node: constructor,
messageId: 'denyConstructorDI',
fix: (fixer) => {
return fixer.replaceTextRange(
[constructor.range[0], closeToken.range[0]],
codes.join('\n' + ' '.repeat(constructor.loc.start.column))
);
},
});
}
}
}
}
},
}),
};
export = rule;