@so1ve/eslint-plugin 0.77.0 → 0.78.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +159 -112
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +159 -112
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,132 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const utils = require('@typescript-eslint/utils');
|
|
4
3
|
const types = require('@typescript-eslint/types');
|
|
4
|
+
const utils = require('@typescript-eslint/utils');
|
|
5
5
|
|
|
6
6
|
const createEslintRule = utils.ESLintUtils.RuleCreator((ruleName) => ruleName);
|
|
7
7
|
|
|
8
|
+
const RULE_NAME$4 = "function-style";
|
|
9
|
+
const START_RETURN = /^return /;
|
|
10
|
+
const END_SEMICOLON = /;$/;
|
|
11
|
+
const functionStyle = createEslintRule({
|
|
12
|
+
name: RULE_NAME$4,
|
|
13
|
+
meta: {
|
|
14
|
+
type: "problem",
|
|
15
|
+
docs: {
|
|
16
|
+
description: "Enforce function style.",
|
|
17
|
+
recommended: "error"
|
|
18
|
+
},
|
|
19
|
+
fixable: "code",
|
|
20
|
+
schema: [],
|
|
21
|
+
messages: {
|
|
22
|
+
arrow: "Expected an arrow function shorthand.",
|
|
23
|
+
declaration: "Expected a function declaration."
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
defaultOptions: [],
|
|
27
|
+
create: (context) => {
|
|
28
|
+
const sourceCode = context.getSourceCode();
|
|
29
|
+
const text = sourceCode.getText();
|
|
30
|
+
const getStatementRaw = (statement) => `(${text.slice(statement.range[0], statement.range[1]).replace(START_RETURN, "").replace(END_SEMICOLON, "")})`;
|
|
31
|
+
function getLoneReturnStatement(node) {
|
|
32
|
+
const { body } = node;
|
|
33
|
+
if (body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
34
|
+
const { body: blockBody } = body;
|
|
35
|
+
if (blockBody.length === 1) {
|
|
36
|
+
const [statement] = blockBody;
|
|
37
|
+
if (statement?.type === types.AST_NODE_TYPES.ReturnStatement) {
|
|
38
|
+
return statement;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function generateFunction(type, name, node, rawStatement, asVariable = true) {
|
|
44
|
+
const async = node.async ? "async " : "";
|
|
45
|
+
const generics = node.typeParameters ? sourceCode.getText(node.typeParameters) : "";
|
|
46
|
+
const params = node.params.map((param) => sourceCode.getText(param)).join(", ");
|
|
47
|
+
const returnType = node.returnType ? sourceCode.getText(node.returnType) : "";
|
|
48
|
+
const body = sourceCode.getText(node.body);
|
|
49
|
+
const variableDeclaration = asVariable ? `const ${name} = ` : "";
|
|
50
|
+
return type === "arrow" ? `${variableDeclaration}${async}${generics}(${params})${returnType} => ${rawStatement};` : `${async}function ${name}${generics}(${params})${returnType} ${body}`;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
FunctionExpression(node) {
|
|
54
|
+
if (node.parent?.id?.typeAnnotation || node.parent?.type !== types.AST_NODE_TYPES.VariableDeclarator) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const name = node.parent.id.name;
|
|
58
|
+
context.report({
|
|
59
|
+
node,
|
|
60
|
+
messageId: "declaration",
|
|
61
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
62
|
+
node.parent.parent.range,
|
|
63
|
+
generateFunction("declaration", name, node)
|
|
64
|
+
)
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
"FunctionDeclaration:not(TSDeclareFunction + FunctionDeclaration)"(node) {
|
|
68
|
+
const statement = getLoneReturnStatement(node);
|
|
69
|
+
if (!statement || !node.id?.name || node.generator) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const asVariable = node.parent?.type !== types.AST_NODE_TYPES.ExportDefaultDeclaration;
|
|
73
|
+
context.report({
|
|
74
|
+
node,
|
|
75
|
+
messageId: "arrow",
|
|
76
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
77
|
+
node.range,
|
|
78
|
+
generateFunction(
|
|
79
|
+
"arrow",
|
|
80
|
+
node.id.name,
|
|
81
|
+
node,
|
|
82
|
+
getStatementRaw(statement),
|
|
83
|
+
asVariable
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
ArrowFunctionExpression(node) {
|
|
89
|
+
const { body, parent } = node;
|
|
90
|
+
const statement = getLoneReturnStatement(node);
|
|
91
|
+
if (statement) {
|
|
92
|
+
context.report({
|
|
93
|
+
node,
|
|
94
|
+
messageId: "arrow",
|
|
95
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
96
|
+
node.body.range,
|
|
97
|
+
getStatementRaw(statement)
|
|
98
|
+
)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (parent?.id?.typeAnnotation) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
105
|
+
const { body: blockBody } = body;
|
|
106
|
+
if (blockBody.length > 1 && node.parent?.parent?.type === types.AST_NODE_TYPES.VariableDeclaration) {
|
|
107
|
+
const { parent: parent2 } = node.parent;
|
|
108
|
+
context.report({
|
|
109
|
+
node: parent2,
|
|
110
|
+
messageId: "declaration",
|
|
111
|
+
fix: (fixer) => {
|
|
112
|
+
const [start, end] = parent2.range;
|
|
113
|
+
return fixer.replaceTextRange(
|
|
114
|
+
[start, end],
|
|
115
|
+
generateFunction(
|
|
116
|
+
"declaration",
|
|
117
|
+
node.parent.id.name,
|
|
118
|
+
node
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
8
130
|
const RULE_NAME$3 = "import-dedupe";
|
|
9
131
|
const importDedupe = createEslintRule({
|
|
10
132
|
name: RULE_NAME$3,
|
|
@@ -73,7 +195,7 @@ const noInlineTypeImport = createEslintRule({
|
|
|
73
195
|
const sourceCode = context.getSourceCode();
|
|
74
196
|
return {
|
|
75
197
|
ImportDeclaration: (node) => {
|
|
76
|
-
const specifiers = node
|
|
198
|
+
const { specifiers } = node;
|
|
77
199
|
const typeSpecifiers = specifiers.filter(
|
|
78
200
|
(s) => s.type === types.AST_NODE_TYPES.ImportSpecifier && s.importKind === "type"
|
|
79
201
|
);
|
|
@@ -93,10 +215,10 @@ const noInlineTypeImport = createEslintRule({
|
|
|
93
215
|
const defaultImportSpecifierText = sourceCode.getText(
|
|
94
216
|
defaultImportSpecifier
|
|
95
217
|
);
|
|
96
|
-
const
|
|
218
|
+
const defaultAndvalueSpecifiersText = defaultImportSpecifier ? `import ${defaultImportSpecifierText}, { ${valueSpecifiersText} } from "${node.source.value}";` : `import { ${valueSpecifiersText} } from "${node.source.value}";`;
|
|
97
219
|
const texts = [
|
|
98
220
|
`import type { ${typeSpecifiersText} } from "${node.source.value}";`,
|
|
99
|
-
|
|
221
|
+
defaultAndvalueSpecifiersText
|
|
100
222
|
];
|
|
101
223
|
yield fixer.replaceText(node, texts.join("\n"));
|
|
102
224
|
}
|
|
@@ -119,36 +241,38 @@ const noInlineTypeImport = createEslintRule({
|
|
|
119
241
|
}
|
|
120
242
|
});
|
|
121
243
|
|
|
122
|
-
const RULE_NAME$1 = "no-
|
|
123
|
-
const
|
|
244
|
+
const RULE_NAME$1 = "no-negated-equal";
|
|
245
|
+
const noNegatedEqual = createEslintRule({
|
|
124
246
|
name: RULE_NAME$1,
|
|
125
247
|
meta: {
|
|
126
248
|
type: "problem",
|
|
127
249
|
docs: {
|
|
128
|
-
description: "
|
|
250
|
+
description: "Disallow negated equal sign.",
|
|
129
251
|
recommended: "error"
|
|
130
252
|
},
|
|
131
253
|
fixable: "code",
|
|
132
254
|
schema: [],
|
|
133
255
|
messages: {
|
|
134
|
-
|
|
256
|
+
noNegatedEqual: "Expect no negated equal sign."
|
|
135
257
|
}
|
|
136
258
|
},
|
|
137
259
|
defaultOptions: [],
|
|
138
260
|
create: (context) => ({
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
261
|
+
BinaryExpression(node) {
|
|
262
|
+
const { parent, left, right, operator } = node;
|
|
263
|
+
if (!parent) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (["==", "==="].includes(node.operator) && parent.type === types.AST_NODE_TYPES.UnaryExpression && // Is this necessary?
|
|
267
|
+
parent.operator === "!") {
|
|
142
268
|
context.report({
|
|
143
269
|
node,
|
|
144
|
-
messageId: "
|
|
145
|
-
fix(fixer) {
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`"${node.quasis[0].value.raw}"`
|
|
151
|
-
);
|
|
270
|
+
messageId: "noNegatedEqual",
|
|
271
|
+
*fix(fixer) {
|
|
272
|
+
const operatorRange = [left.range[1], right.range[0]];
|
|
273
|
+
const fixedOperator = operator === "==" ? "!=" : "!==";
|
|
274
|
+
yield fixer.replaceTextRange(operatorRange, fixedOperator);
|
|
275
|
+
yield fixer.removeRange([parent.range[0], parent.range[0] + 1]);
|
|
152
276
|
}
|
|
153
277
|
});
|
|
154
278
|
}
|
|
@@ -156,125 +280,48 @@ const noUselessTemplateString = createEslintRule({
|
|
|
156
280
|
})
|
|
157
281
|
});
|
|
158
282
|
|
|
159
|
-
const RULE_NAME = "
|
|
160
|
-
const
|
|
161
|
-
const END_SEMICOLON = /;$/;
|
|
162
|
-
function getBeforeNode(node) {
|
|
163
|
-
const { parent } = node;
|
|
164
|
-
if (!parent)
|
|
165
|
-
return;
|
|
166
|
-
const { body } = parent;
|
|
167
|
-
if (!body)
|
|
168
|
-
return;
|
|
169
|
-
const index = body.indexOf(node);
|
|
170
|
-
if (index === 0)
|
|
171
|
-
return;
|
|
172
|
-
return body[index - 1];
|
|
173
|
-
}
|
|
174
|
-
const functionStyle = createEslintRule({
|
|
283
|
+
const RULE_NAME = "no-useless-template-string";
|
|
284
|
+
const noUselessTemplateString = createEslintRule({
|
|
175
285
|
name: RULE_NAME,
|
|
176
286
|
meta: {
|
|
177
287
|
type: "problem",
|
|
178
288
|
docs: {
|
|
179
|
-
description: "
|
|
289
|
+
description: "No useless template string.",
|
|
180
290
|
recommended: "error"
|
|
181
291
|
},
|
|
182
292
|
fixable: "code",
|
|
183
293
|
schema: [],
|
|
184
294
|
messages: {
|
|
185
|
-
|
|
186
|
-
arrowShorthand: "Expected an arrow function shorthand.",
|
|
187
|
-
declaration: "Expected a function declaration."
|
|
295
|
+
noUselessTemplateString: "No useless template string."
|
|
188
296
|
}
|
|
189
297
|
},
|
|
190
298
|
defaultOptions: [],
|
|
191
|
-
create: (context) => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
function getLonelyReturnStatement(node) {
|
|
196
|
-
const { body } = node;
|
|
197
|
-
if (body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
198
|
-
const { body: blockBody } = body;
|
|
199
|
-
if (blockBody.length === 1) {
|
|
200
|
-
const [statement] = blockBody;
|
|
201
|
-
if (statement?.type === types.AST_NODE_TYPES.ReturnStatement) {
|
|
202
|
-
return statement;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function generateFunction(node, type) {
|
|
208
|
-
const async = node.async ? "async " : "";
|
|
209
|
-
const params = node.params.map((param) => sourceCode.getText(param)).join(", ");
|
|
210
|
-
const generics = node.typeParameters ? sourceCode.getText(node.typeParameters) : "";
|
|
211
|
-
const body = sourceCode.getText(node.body);
|
|
212
|
-
return type === "arrow" ? `const ${node.id.name} = ${async}${generics}(${params}) => ${body};` : `${async}function ${node.parent.id.name}${generics}(${params}) ${body}`;
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
FunctionDeclaration(node) {
|
|
216
|
-
if (!node.id?.name)
|
|
217
|
-
return;
|
|
218
|
-
const statement = getLonelyReturnStatement(node);
|
|
219
|
-
if (!statement || node.generator || getBeforeNode(node)?.type === types.AST_NODE_TYPES.TSDeclareFunction)
|
|
220
|
-
return;
|
|
299
|
+
create: (context) => ({
|
|
300
|
+
"TemplateLiteral:not(TaggedTemplateExpression > TemplateLiteral)"(node) {
|
|
301
|
+
const hasNewline = node.quasis.some((n) => n.value.raw.includes("\n"));
|
|
302
|
+
if (node.expressions.length === 0 && !hasNewline) {
|
|
221
303
|
context.report({
|
|
222
304
|
node,
|
|
223
|
-
messageId: "
|
|
224
|
-
fix
|
|
225
|
-
const [start, end] = node.range;
|
|
305
|
+
messageId: "noUselessTemplateString",
|
|
306
|
+
fix(fixer) {
|
|
226
307
|
return fixer.replaceTextRange(
|
|
227
|
-
|
|
228
|
-
|
|
308
|
+
node.range,
|
|
309
|
+
`"${node.quasis[0].value.raw}"`
|
|
229
310
|
);
|
|
230
311
|
}
|
|
231
312
|
});
|
|
232
|
-
},
|
|
233
|
-
ArrowFunctionExpression(node) {
|
|
234
|
-
const { body, parent } = node;
|
|
235
|
-
if (parent?.id?.typeAnnotation)
|
|
236
|
-
return;
|
|
237
|
-
if (body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
238
|
-
const { body: blockBody } = body;
|
|
239
|
-
if (blockBody.length > 1 && node.parent?.parent?.type === types.AST_NODE_TYPES.VariableDeclaration) {
|
|
240
|
-
const parent2 = node.parent.parent;
|
|
241
|
-
context.report({
|
|
242
|
-
node: parent2,
|
|
243
|
-
messageId: "declaration",
|
|
244
|
-
fix: (fixer) => {
|
|
245
|
-
const [start, end] = parent2.range;
|
|
246
|
-
return fixer.replaceTextRange(
|
|
247
|
-
[start, end],
|
|
248
|
-
generateFunction(node, "declaration")
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
const statement = getLonelyReturnStatement(node);
|
|
255
|
-
if (statement)
|
|
256
|
-
context.report({
|
|
257
|
-
node,
|
|
258
|
-
messageId: "arrowShorthand",
|
|
259
|
-
fix: (fixer) => {
|
|
260
|
-
const [start, end] = node.body.range;
|
|
261
|
-
return fixer.replaceTextRange(
|
|
262
|
-
[start, end],
|
|
263
|
-
getStatementRaw(statement)
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
313
|
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
314
|
+
}
|
|
315
|
+
})
|
|
270
316
|
});
|
|
271
317
|
|
|
272
318
|
const index = {
|
|
273
319
|
rules: {
|
|
320
|
+
"function-style": functionStyle,
|
|
274
321
|
"import-dedupe": importDedupe,
|
|
275
322
|
"no-inline-type-import": noInlineTypeImport,
|
|
276
323
|
"no-useless-template-string": noUselessTemplateString,
|
|
277
|
-
"
|
|
324
|
+
"no-negated-equal": noNegatedEqual
|
|
278
325
|
}
|
|
279
326
|
};
|
|
280
327
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as _typescript_eslint_utils_dist_ts_eslint_Rule from '@typescript-eslint/utils/dist/ts-eslint/Rule';
|
|
2
2
|
|
|
3
|
-
type MessageIds = "arrow" | "
|
|
3
|
+
type MessageIds = "arrow" | "declaration";
|
|
4
4
|
|
|
5
5
|
declare const _default: {
|
|
6
6
|
rules: {
|
|
7
|
+
"function-style": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<MessageIds, [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
|
|
7
8
|
"import-dedupe": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"importDedupe", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
|
|
8
9
|
"no-inline-type-import": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noInlineTypeImport", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
|
|
9
10
|
"no-useless-template-string": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noUselessTemplateString", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
|
|
10
|
-
"
|
|
11
|
+
"no-negated-equal": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noNegatedEqual", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
|
|
11
12
|
};
|
|
12
13
|
};
|
|
13
14
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,130 @@
|
|
|
1
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
1
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
2
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
3
3
|
|
|
4
4
|
const createEslintRule = ESLintUtils.RuleCreator((ruleName) => ruleName);
|
|
5
5
|
|
|
6
|
+
const RULE_NAME$4 = "function-style";
|
|
7
|
+
const START_RETURN = /^return /;
|
|
8
|
+
const END_SEMICOLON = /;$/;
|
|
9
|
+
const functionStyle = createEslintRule({
|
|
10
|
+
name: RULE_NAME$4,
|
|
11
|
+
meta: {
|
|
12
|
+
type: "problem",
|
|
13
|
+
docs: {
|
|
14
|
+
description: "Enforce function style.",
|
|
15
|
+
recommended: "error"
|
|
16
|
+
},
|
|
17
|
+
fixable: "code",
|
|
18
|
+
schema: [],
|
|
19
|
+
messages: {
|
|
20
|
+
arrow: "Expected an arrow function shorthand.",
|
|
21
|
+
declaration: "Expected a function declaration."
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultOptions: [],
|
|
25
|
+
create: (context) => {
|
|
26
|
+
const sourceCode = context.getSourceCode();
|
|
27
|
+
const text = sourceCode.getText();
|
|
28
|
+
const getStatementRaw = (statement) => `(${text.slice(statement.range[0], statement.range[1]).replace(START_RETURN, "").replace(END_SEMICOLON, "")})`;
|
|
29
|
+
function getLoneReturnStatement(node) {
|
|
30
|
+
const { body } = node;
|
|
31
|
+
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
32
|
+
const { body: blockBody } = body;
|
|
33
|
+
if (blockBody.length === 1) {
|
|
34
|
+
const [statement] = blockBody;
|
|
35
|
+
if (statement?.type === AST_NODE_TYPES.ReturnStatement) {
|
|
36
|
+
return statement;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function generateFunction(type, name, node, rawStatement, asVariable = true) {
|
|
42
|
+
const async = node.async ? "async " : "";
|
|
43
|
+
const generics = node.typeParameters ? sourceCode.getText(node.typeParameters) : "";
|
|
44
|
+
const params = node.params.map((param) => sourceCode.getText(param)).join(", ");
|
|
45
|
+
const returnType = node.returnType ? sourceCode.getText(node.returnType) : "";
|
|
46
|
+
const body = sourceCode.getText(node.body);
|
|
47
|
+
const variableDeclaration = asVariable ? `const ${name} = ` : "";
|
|
48
|
+
return type === "arrow" ? `${variableDeclaration}${async}${generics}(${params})${returnType} => ${rawStatement};` : `${async}function ${name}${generics}(${params})${returnType} ${body}`;
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
FunctionExpression(node) {
|
|
52
|
+
if (node.parent?.id?.typeAnnotation || node.parent?.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const name = node.parent.id.name;
|
|
56
|
+
context.report({
|
|
57
|
+
node,
|
|
58
|
+
messageId: "declaration",
|
|
59
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
60
|
+
node.parent.parent.range,
|
|
61
|
+
generateFunction("declaration", name, node)
|
|
62
|
+
)
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
"FunctionDeclaration:not(TSDeclareFunction + FunctionDeclaration)"(node) {
|
|
66
|
+
const statement = getLoneReturnStatement(node);
|
|
67
|
+
if (!statement || !node.id?.name || node.generator) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const asVariable = node.parent?.type !== AST_NODE_TYPES.ExportDefaultDeclaration;
|
|
71
|
+
context.report({
|
|
72
|
+
node,
|
|
73
|
+
messageId: "arrow",
|
|
74
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
75
|
+
node.range,
|
|
76
|
+
generateFunction(
|
|
77
|
+
"arrow",
|
|
78
|
+
node.id.name,
|
|
79
|
+
node,
|
|
80
|
+
getStatementRaw(statement),
|
|
81
|
+
asVariable
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
ArrowFunctionExpression(node) {
|
|
87
|
+
const { body, parent } = node;
|
|
88
|
+
const statement = getLoneReturnStatement(node);
|
|
89
|
+
if (statement) {
|
|
90
|
+
context.report({
|
|
91
|
+
node,
|
|
92
|
+
messageId: "arrow",
|
|
93
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
94
|
+
node.body.range,
|
|
95
|
+
getStatementRaw(statement)
|
|
96
|
+
)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (parent?.id?.typeAnnotation) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
103
|
+
const { body: blockBody } = body;
|
|
104
|
+
if (blockBody.length > 1 && node.parent?.parent?.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
105
|
+
const { parent: parent2 } = node.parent;
|
|
106
|
+
context.report({
|
|
107
|
+
node: parent2,
|
|
108
|
+
messageId: "declaration",
|
|
109
|
+
fix: (fixer) => {
|
|
110
|
+
const [start, end] = parent2.range;
|
|
111
|
+
return fixer.replaceTextRange(
|
|
112
|
+
[start, end],
|
|
113
|
+
generateFunction(
|
|
114
|
+
"declaration",
|
|
115
|
+
node.parent.id.name,
|
|
116
|
+
node
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
6
128
|
const RULE_NAME$3 = "import-dedupe";
|
|
7
129
|
const importDedupe = createEslintRule({
|
|
8
130
|
name: RULE_NAME$3,
|
|
@@ -71,7 +193,7 @@ const noInlineTypeImport = createEslintRule({
|
|
|
71
193
|
const sourceCode = context.getSourceCode();
|
|
72
194
|
return {
|
|
73
195
|
ImportDeclaration: (node) => {
|
|
74
|
-
const specifiers = node
|
|
196
|
+
const { specifiers } = node;
|
|
75
197
|
const typeSpecifiers = specifiers.filter(
|
|
76
198
|
(s) => s.type === AST_NODE_TYPES.ImportSpecifier && s.importKind === "type"
|
|
77
199
|
);
|
|
@@ -91,10 +213,10 @@ const noInlineTypeImport = createEslintRule({
|
|
|
91
213
|
const defaultImportSpecifierText = sourceCode.getText(
|
|
92
214
|
defaultImportSpecifier
|
|
93
215
|
);
|
|
94
|
-
const
|
|
216
|
+
const defaultAndvalueSpecifiersText = defaultImportSpecifier ? `import ${defaultImportSpecifierText}, { ${valueSpecifiersText} } from "${node.source.value}";` : `import { ${valueSpecifiersText} } from "${node.source.value}";`;
|
|
95
217
|
const texts = [
|
|
96
218
|
`import type { ${typeSpecifiersText} } from "${node.source.value}";`,
|
|
97
|
-
|
|
219
|
+
defaultAndvalueSpecifiersText
|
|
98
220
|
];
|
|
99
221
|
yield fixer.replaceText(node, texts.join("\n"));
|
|
100
222
|
}
|
|
@@ -117,36 +239,38 @@ const noInlineTypeImport = createEslintRule({
|
|
|
117
239
|
}
|
|
118
240
|
});
|
|
119
241
|
|
|
120
|
-
const RULE_NAME$1 = "no-
|
|
121
|
-
const
|
|
242
|
+
const RULE_NAME$1 = "no-negated-equal";
|
|
243
|
+
const noNegatedEqual = createEslintRule({
|
|
122
244
|
name: RULE_NAME$1,
|
|
123
245
|
meta: {
|
|
124
246
|
type: "problem",
|
|
125
247
|
docs: {
|
|
126
|
-
description: "
|
|
248
|
+
description: "Disallow negated equal sign.",
|
|
127
249
|
recommended: "error"
|
|
128
250
|
},
|
|
129
251
|
fixable: "code",
|
|
130
252
|
schema: [],
|
|
131
253
|
messages: {
|
|
132
|
-
|
|
254
|
+
noNegatedEqual: "Expect no negated equal sign."
|
|
133
255
|
}
|
|
134
256
|
},
|
|
135
257
|
defaultOptions: [],
|
|
136
258
|
create: (context) => ({
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
259
|
+
BinaryExpression(node) {
|
|
260
|
+
const { parent, left, right, operator } = node;
|
|
261
|
+
if (!parent) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (["==", "==="].includes(node.operator) && parent.type === AST_NODE_TYPES.UnaryExpression && // Is this necessary?
|
|
265
|
+
parent.operator === "!") {
|
|
140
266
|
context.report({
|
|
141
267
|
node,
|
|
142
|
-
messageId: "
|
|
143
|
-
fix(fixer) {
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`"${node.quasis[0].value.raw}"`
|
|
149
|
-
);
|
|
268
|
+
messageId: "noNegatedEqual",
|
|
269
|
+
*fix(fixer) {
|
|
270
|
+
const operatorRange = [left.range[1], right.range[0]];
|
|
271
|
+
const fixedOperator = operator === "==" ? "!=" : "!==";
|
|
272
|
+
yield fixer.replaceTextRange(operatorRange, fixedOperator);
|
|
273
|
+
yield fixer.removeRange([parent.range[0], parent.range[0] + 1]);
|
|
150
274
|
}
|
|
151
275
|
});
|
|
152
276
|
}
|
|
@@ -154,125 +278,48 @@ const noUselessTemplateString = createEslintRule({
|
|
|
154
278
|
})
|
|
155
279
|
});
|
|
156
280
|
|
|
157
|
-
const RULE_NAME = "
|
|
158
|
-
const
|
|
159
|
-
const END_SEMICOLON = /;$/;
|
|
160
|
-
function getBeforeNode(node) {
|
|
161
|
-
const { parent } = node;
|
|
162
|
-
if (!parent)
|
|
163
|
-
return;
|
|
164
|
-
const { body } = parent;
|
|
165
|
-
if (!body)
|
|
166
|
-
return;
|
|
167
|
-
const index = body.indexOf(node);
|
|
168
|
-
if (index === 0)
|
|
169
|
-
return;
|
|
170
|
-
return body[index - 1];
|
|
171
|
-
}
|
|
172
|
-
const functionStyle = createEslintRule({
|
|
281
|
+
const RULE_NAME = "no-useless-template-string";
|
|
282
|
+
const noUselessTemplateString = createEslintRule({
|
|
173
283
|
name: RULE_NAME,
|
|
174
284
|
meta: {
|
|
175
285
|
type: "problem",
|
|
176
286
|
docs: {
|
|
177
|
-
description: "
|
|
287
|
+
description: "No useless template string.",
|
|
178
288
|
recommended: "error"
|
|
179
289
|
},
|
|
180
290
|
fixable: "code",
|
|
181
291
|
schema: [],
|
|
182
292
|
messages: {
|
|
183
|
-
|
|
184
|
-
arrowShorthand: "Expected an arrow function shorthand.",
|
|
185
|
-
declaration: "Expected a function declaration."
|
|
293
|
+
noUselessTemplateString: "No useless template string."
|
|
186
294
|
}
|
|
187
295
|
},
|
|
188
296
|
defaultOptions: [],
|
|
189
|
-
create: (context) => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
function getLonelyReturnStatement(node) {
|
|
194
|
-
const { body } = node;
|
|
195
|
-
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
196
|
-
const { body: blockBody } = body;
|
|
197
|
-
if (blockBody.length === 1) {
|
|
198
|
-
const [statement] = blockBody;
|
|
199
|
-
if (statement?.type === AST_NODE_TYPES.ReturnStatement) {
|
|
200
|
-
return statement;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
function generateFunction(node, type) {
|
|
206
|
-
const async = node.async ? "async " : "";
|
|
207
|
-
const params = node.params.map((param) => sourceCode.getText(param)).join(", ");
|
|
208
|
-
const generics = node.typeParameters ? sourceCode.getText(node.typeParameters) : "";
|
|
209
|
-
const body = sourceCode.getText(node.body);
|
|
210
|
-
return type === "arrow" ? `const ${node.id.name} = ${async}${generics}(${params}) => ${body};` : `${async}function ${node.parent.id.name}${generics}(${params}) ${body}`;
|
|
211
|
-
}
|
|
212
|
-
return {
|
|
213
|
-
FunctionDeclaration(node) {
|
|
214
|
-
if (!node.id?.name)
|
|
215
|
-
return;
|
|
216
|
-
const statement = getLonelyReturnStatement(node);
|
|
217
|
-
if (!statement || node.generator || getBeforeNode(node)?.type === AST_NODE_TYPES.TSDeclareFunction)
|
|
218
|
-
return;
|
|
297
|
+
create: (context) => ({
|
|
298
|
+
"TemplateLiteral:not(TaggedTemplateExpression > TemplateLiteral)"(node) {
|
|
299
|
+
const hasNewline = node.quasis.some((n) => n.value.raw.includes("\n"));
|
|
300
|
+
if (node.expressions.length === 0 && !hasNewline) {
|
|
219
301
|
context.report({
|
|
220
302
|
node,
|
|
221
|
-
messageId: "
|
|
222
|
-
fix
|
|
223
|
-
const [start, end] = node.range;
|
|
303
|
+
messageId: "noUselessTemplateString",
|
|
304
|
+
fix(fixer) {
|
|
224
305
|
return fixer.replaceTextRange(
|
|
225
|
-
|
|
226
|
-
|
|
306
|
+
node.range,
|
|
307
|
+
`"${node.quasis[0].value.raw}"`
|
|
227
308
|
);
|
|
228
309
|
}
|
|
229
310
|
});
|
|
230
|
-
},
|
|
231
|
-
ArrowFunctionExpression(node) {
|
|
232
|
-
const { body, parent } = node;
|
|
233
|
-
if (parent?.id?.typeAnnotation)
|
|
234
|
-
return;
|
|
235
|
-
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
236
|
-
const { body: blockBody } = body;
|
|
237
|
-
if (blockBody.length > 1 && node.parent?.parent?.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
238
|
-
const parent2 = node.parent.parent;
|
|
239
|
-
context.report({
|
|
240
|
-
node: parent2,
|
|
241
|
-
messageId: "declaration",
|
|
242
|
-
fix: (fixer) => {
|
|
243
|
-
const [start, end] = parent2.range;
|
|
244
|
-
return fixer.replaceTextRange(
|
|
245
|
-
[start, end],
|
|
246
|
-
generateFunction(node, "declaration")
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
const statement = getLonelyReturnStatement(node);
|
|
253
|
-
if (statement)
|
|
254
|
-
context.report({
|
|
255
|
-
node,
|
|
256
|
-
messageId: "arrowShorthand",
|
|
257
|
-
fix: (fixer) => {
|
|
258
|
-
const [start, end] = node.body.range;
|
|
259
|
-
return fixer.replaceTextRange(
|
|
260
|
-
[start, end],
|
|
261
|
-
getStatementRaw(statement)
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
311
|
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
312
|
+
}
|
|
313
|
+
})
|
|
268
314
|
});
|
|
269
315
|
|
|
270
316
|
const index = {
|
|
271
317
|
rules: {
|
|
318
|
+
"function-style": functionStyle,
|
|
272
319
|
"import-dedupe": importDedupe,
|
|
273
320
|
"no-inline-type-import": noInlineTypeImport,
|
|
274
321
|
"no-useless-template-string": noUselessTemplateString,
|
|
275
|
-
"
|
|
322
|
+
"no-negated-equal": noNegatedEqual
|
|
276
323
|
}
|
|
277
324
|
};
|
|
278
325
|
|