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