@so1ve/eslint-plugin 0.56.1 → 0.58.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.mjs CHANGED
@@ -1,354 +1,10 @@
1
- import { ESLintUtils, AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils';
2
- import { ref, computed } from '@vue/reactivity';
3
- import * as util from '@typescript-eslint/utils/dist/ast-utils';
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
4
2
 
5
3
  const createEslintRule = ESLintUtils.RuleCreator((ruleName) => ruleName);
6
4
 
7
- const RULE_NAME$8 = "array-bracket-spacing";
8
- const arrayBracketSpacing = createEslintRule({
9
- name: RULE_NAME$8,
10
- meta: {
11
- type: "layout",
12
- docs: {
13
- description: "Array bracket spacing",
14
- recommended: "error"
15
- },
16
- fixable: "whitespace",
17
- schema: [],
18
- messages: {
19
- arrayBracketSpacing: "Array bracket spacing mismatch"
20
- }
21
- },
22
- defaultOptions: [],
23
- create: (context) => {
24
- const sourceCode = context.getSourceCode();
25
- const text = sourceCode.getText();
26
- const checkNode = (node) => {
27
- const elements = node.type === AST_NODE_TYPES.TSTupleType ? node.elementTypes : node.elements;
28
- const firstElement = elements[0];
29
- const lastElement = elements[elements.length - 1];
30
- if (!firstElement) {
31
- return;
32
- }
33
- const leftToken = sourceCode.getTokenBefore(firstElement);
34
- const rightToken = ref(sourceCode.getTokenAfter(lastElement));
35
- if (rightToken.value.value === ",") {
36
- rightToken.value = sourceCode.getTokenAfter(rightToken.value);
37
- }
38
- const textBetweenFirstAndToken = computed(() => text.slice(leftToken.range[1], firstElement.range[0]));
39
- const isNewline = computed(() => textBetweenFirstAndToken.value.includes("\n"));
40
- const textBetweenLastAndToken = computed(() => text.slice(lastElement.range[1], rightToken.value.range[0]));
41
- const hasNewlineAfter = computed(() => textBetweenLastAndToken.value.includes("\n"));
42
- if (sourceCode.isSpaceBetween(leftToken, firstElement) && !isNewline.value) {
43
- context.report({
44
- node,
45
- messageId: "arrayBracketSpacing",
46
- *fix(fixer) {
47
- yield fixer.removeRange([leftToken.range[1], firstElement.range[0]]);
48
- }
49
- });
50
- }
51
- if (sourceCode.isSpaceBetween(lastElement, rightToken.value)) {
52
- if (!isNewline.value) {
53
- context.report({
54
- node,
55
- messageId: "arrayBracketSpacing",
56
- *fix(fixer) {
57
- yield fixer.removeRange([lastElement.range[1], rightToken.value.range[0]]);
58
- }
59
- });
60
- }
61
- }
62
- if (isNewline.value && !hasNewlineAfter.value) {
63
- context.report({
64
- node,
65
- messageId: "arrayBracketSpacing",
66
- *fix(fixer) {
67
- yield fixer.replaceTextRange([lastElement.range[1], rightToken.value.range[0]], "\n");
68
- }
69
- });
70
- }
71
- };
72
- return {
73
- TSTupleType: checkNode,
74
- ArrayExpression: checkNode
75
- };
76
- }
77
- });
78
-
79
- const RULE_NAME$7 = "generic-spacing";
80
- const genericSpacing = createEslintRule({
81
- name: RULE_NAME$7,
82
- meta: {
83
- type: "layout",
84
- docs: {
85
- description: "Spaces around generic type parameters",
86
- recommended: "error"
87
- },
88
- fixable: "whitespace",
89
- schema: [],
90
- messages: {
91
- genericSpacingMismatch: "Generic spaces mismatch"
92
- }
93
- },
94
- defaultOptions: [],
95
- create: (context) => {
96
- const sourceCode = context.getSourceCode();
97
- const text = sourceCode.getText();
98
- return {
99
- TSTypeParameterDeclaration: (node) => {
100
- const params = node.params;
101
- for (const param of params) {
102
- const leftToken = sourceCode.getTokenBefore(param);
103
- const rightToken = sourceCode.getTokenAfter(param);
104
- const hasSpacingBeforeParam = sourceCode.isSpaceBetween(leftToken, param);
105
- const hasSpacingAfterParam = sourceCode.isSpaceBetween(param, rightToken);
106
- if (hasSpacingBeforeParam && param.loc.start.line === node.loc.start.line && leftToken.value === "<") {
107
- context.report({
108
- node,
109
- loc: {
110
- start: {
111
- line: leftToken.loc.end.line,
112
- column: leftToken.loc.end.column
113
- },
114
- end: {
115
- line: param.loc.start.line,
116
- column: param.loc.start.column - 1
117
- }
118
- },
119
- messageId: "genericSpacingMismatch",
120
- *fix(fixer) {
121
- yield fixer.removeRange([leftToken.range[1], param.range[0]]);
122
- }
123
- });
124
- }
125
- if (hasSpacingAfterParam && param.loc.end.line === node.loc.end.line) {
126
- context.report({
127
- loc: {
128
- start: {
129
- line: param.loc.end.line,
130
- column: param.loc.end.column
131
- },
132
- end: {
133
- line: rightToken.loc.start.line,
134
- column: rightToken.loc.start.column
135
- }
136
- },
137
- node,
138
- messageId: "genericSpacingMismatch",
139
- *fix(fixer) {
140
- yield fixer.removeRange([param.range[1], rightToken.range[0]]);
141
- }
142
- });
143
- }
144
- if (!hasSpacingBeforeParam && util.isCommaToken(leftToken)) {
145
- context.report({
146
- node,
147
- loc: {
148
- start: {
149
- line: leftToken.loc.end.line,
150
- column: leftToken.loc.end.column
151
- },
152
- end: {
153
- line: param.loc.start.line,
154
- column: param.loc.start.column - 1
155
- }
156
- },
157
- messageId: "genericSpacingMismatch",
158
- *fix(fixer) {
159
- yield fixer.replaceTextRange([leftToken.range[1], param.range[0]], " ");
160
- }
161
- });
162
- }
163
- }
164
- if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression"].includes(node.parent.type)) {
165
- const leftToken = sourceCode.getTokenBefore(node);
166
- const hasSpacingBeforeNode = sourceCode.isSpaceBetween(leftToken, node);
167
- const lastParam = params[params.length - 1];
168
- const endBracket = sourceCode.getTokenAfter(lastParam);
169
- const rightToken = sourceCode.getTokenAfter(endBracket, util.isOpeningParenToken);
170
- if (!rightToken) {
171
- return;
172
- }
173
- const hasSpacingAfterParam = sourceCode.isSpaceBetween(endBracket, rightToken);
174
- if (hasSpacingBeforeNode && node.parent.type !== AST_NODE_TYPES.TSFunctionType) {
175
- context.report({
176
- node,
177
- loc: {
178
- start: {
179
- line: leftToken.loc.end.line,
180
- column: leftToken.loc.end.column
181
- },
182
- end: {
183
- line: node.loc.start.line,
184
- column: node.loc.start.column
185
- }
186
- },
187
- messageId: "genericSpacingMismatch",
188
- *fix(fixer) {
189
- yield fixer.removeRange([leftToken.range[1], node.range[0]]);
190
- }
191
- });
192
- }
193
- if (hasSpacingAfterParam && [AST_NODE_TYPES.TSFunctionType, AST_NODE_TYPES.FunctionDeclaration, AST_NODE_TYPES.FunctionExpression].includes(node.parent.type)) {
194
- context.report({
195
- node,
196
- loc: {
197
- start: {
198
- line: endBracket.loc.end.line,
199
- column: endBracket.loc.end.column
200
- },
201
- end: {
202
- line: rightToken.loc.start.line,
203
- column: rightToken.loc.start.column
204
- }
205
- },
206
- messageId: "genericSpacingMismatch",
207
- *fix(fixer) {
208
- yield fixer.removeRange([endBracket.range[1], rightToken.range[0]]);
209
- }
210
- });
211
- }
212
- }
213
- },
214
- // add space around = in type Foo<T = true>
215
- TSTypeParameter: (node) => {
216
- if (!node.default) {
217
- return;
218
- }
219
- const endNode = node.constraint ?? node.name;
220
- const from = endNode.range[1];
221
- const to = node.default.range[0];
222
- const spaceAndEqual = sourceCode.text.slice(from, to);
223
- if (spaceAndEqual !== " = ") {
224
- const preSpace = spaceAndEqual.match(/^(\s*)/)?.[0];
225
- const postSpace = spaceAndEqual.match(/(\s*)$/)?.[0];
226
- if (preSpace.length !== 1) {
227
- context.report({
228
- *fix(fixer) {
229
- yield fixer.replaceTextRange([from, from + preSpace.length], " ");
230
- },
231
- loc: {
232
- start: {
233
- line: node.loc.start.line,
234
- column: node.loc.start.column + 1
235
- },
236
- end: {
237
- line: node.loc.end.line,
238
- column: node.loc.end.column - 2 - postSpace.length
239
- }
240
- },
241
- node,
242
- messageId: "genericSpacingMismatch"
243
- });
244
- }
245
- if (postSpace.length !== 1) {
246
- context.report({
247
- *fix(fixer) {
248
- yield fixer.replaceTextRange([to - postSpace.length, to], " ");
249
- },
250
- loc: {
251
- start: {
252
- line: node.loc.start.line,
253
- column: node.loc.start.column + 2 + preSpace.length
254
- },
255
- end: {
256
- line: node.loc.end.line,
257
- column: node.loc.end.column - 1
258
- }
259
- },
260
- messageId: "genericSpacingMismatch"
261
- });
262
- }
263
- }
264
- },
265
- // type T = Generic< any >
266
- TSTypeParameterInstantiation: (node) => {
267
- const params = node.params;
268
- for (const param of params) {
269
- const leftToken = sourceCode.getTokenBefore(param);
270
- const rightToken = sourceCode.getTokenAfter(param);
271
- const hasSpacingBeforeParam = leftToken.value === "<" ? sourceCode.isSpaceBetween(leftToken, param) : false;
272
- const hasSpacingAfterParam = rightToken.value === ">" ? sourceCode.isSpaceBetween(param, rightToken) : false;
273
- if (hasSpacingBeforeParam && leftToken.loc.end.line === param.loc.start.line) {
274
- context.report({
275
- node,
276
- loc: {
277
- start: {
278
- line: leftToken.loc.end.line,
279
- column: leftToken.loc.end.column
280
- },
281
- end: {
282
- line: param.loc.start.line,
283
- column: param.loc.start.column
284
- }
285
- },
286
- messageId: "genericSpacingMismatch",
287
- *fix(fixer) {
288
- yield fixer.removeRange([leftToken.range[1], param.range[0]]);
289
- }
290
- });
291
- }
292
- if (hasSpacingAfterParam && param.loc.end.line === rightToken.loc.start.line) {
293
- context.report({
294
- node,
295
- loc: {
296
- start: {
297
- line: param.loc.end.line,
298
- column: param.loc.end.column
299
- },
300
- end: {
301
- line: rightToken.loc.start.line,
302
- column: rightToken.loc.start.column
303
- }
304
- },
305
- messageId: "genericSpacingMismatch",
306
- *fix(fixer) {
307
- yield fixer.removeRange([param.range[1], rightToken.range[0]]);
308
- }
309
- });
310
- }
311
- }
312
- },
313
- // Add spaces before extends
314
- // interface a {}
315
- // interface A<B extends 1>extends a {}
316
- // Fix to: interface A<B extends 1> extends a {}
317
- TSInterfaceDeclaration: (node) => {
318
- if (!node.extends || !node.typeParameters) {
319
- return;
320
- }
321
- const { typeParameters } = node;
322
- const extendsKeywordStart = typeParameters.range[1];
323
- const extendsKeywordEnd = node.extends[0].range[0];
324
- const extendsText = text.slice(extendsKeywordStart, extendsKeywordEnd);
325
- if (!/^\s+/.test(extendsText)) {
326
- context.report({
327
- loc: {
328
- start: {
329
- line: typeParameters.loc.end.line,
330
- column: typeParameters.loc.end.column
331
- },
332
- end: {
333
- line: typeParameters.loc.end.line,
334
- column: typeParameters.loc.end.column + 7
335
- }
336
- },
337
- node,
338
- messageId: "genericSpacingMismatch",
339
- *fix(fixer) {
340
- yield fixer.replaceTextRange([extendsKeywordStart, extendsKeywordEnd - 8], " ");
341
- }
342
- });
343
- }
344
- }
345
- };
346
- }
347
- });
348
-
349
- const RULE_NAME$6 = "import-dedupe";
5
+ const RULE_NAME$2 = "import-dedupe";
350
6
  const importDedupe = createEslintRule({
351
- name: RULE_NAME$6,
7
+ name: RULE_NAME$2,
352
8
  meta: {
353
9
  type: "problem",
354
10
  docs: {
@@ -396,9 +52,9 @@ const importDedupe = createEslintRule({
396
52
  }
397
53
  });
398
54
 
399
- const RULE_NAME$5 = "no-inline-type-import";
55
+ const RULE_NAME$1 = "no-inline-type-import";
400
56
  const noInlineTypeImport = createEslintRule({
401
- name: RULE_NAME$5,
57
+ name: RULE_NAME$1,
402
58
  meta: {
403
59
  type: "layout",
404
60
  docs: {
@@ -448,450 +104,34 @@ import { ${valueSpecifiersText} } from "${node.source.value}";`
448
104
  }
449
105
  });
450
106
 
451
- const RULE_NAME$4 = "no-space-before-paren";
452
- const noSpaceBeforeParen = createEslintRule({
453
- name: RULE_NAME$4,
454
- meta: {
455
- type: "layout",
456
- docs: {
457
- description: "Space before paren",
458
- recommended: "error"
459
- },
460
- fixable: "whitespace",
461
- schema: [],
462
- messages: {
463
- noSpaceBeforeParen: "Expected no space before paren"
464
- }
465
- },
466
- defaultOptions: [],
467
- create: (context) => {
468
- const sourceCode = context.getSourceCode();
469
- const text = sourceCode.getText();
470
- return {
471
- ImportExpression(node) {
472
- const sourceRange = node.source.range;
473
- const parenStart = sourceRange[0] - 1;
474
- const importEnd = node.range[0] + 6;
475
- const textBetweenImportAndParenRange = [importEnd, parenStart];
476
- const textBetweenImportAndParen = text.slice(...textBetweenImportAndParenRange);
477
- if (textBetweenImportAndParen.length > 0) {
478
- context.report({
479
- node,
480
- messageId: "noSpaceBeforeParen",
481
- *fix(fixer) {
482
- yield fixer.removeRange(textBetweenImportAndParenRange);
483
- }
484
- });
485
- }
486
- },
487
- CallExpression(node) {
488
- let caller = "property" in node.callee ? node.callee.property : node.callee;
489
- if (caller.type === AST_NODE_TYPES.TSInstantiationExpression && "property" in caller.expression) {
490
- caller = caller.expression.property;
491
- }
492
- const callerEnd = ref(caller.range[1]);
493
- const textAfterCaller = computed(() => text.slice(callerEnd.value));
494
- const parenStart = ref(callerEnd.value + textAfterCaller.value.indexOf("("));
495
- const textBetweenFunctionNameAndParenRange = computed(
496
- () => [callerEnd.value, parenStart.value]
497
- );
498
- const textBetweenFunctionNameAndParen = computed(
499
- () => text.slice(...textBetweenFunctionNameAndParenRange.value)
500
- );
501
- const hasGenerics = computed(() => /^\s*</.test(textBetweenFunctionNameAndParen.value));
502
- const hasIndex = computed(() => textBetweenFunctionNameAndParen.value.startsWith("]"));
503
- if (hasIndex.value) {
504
- callerEnd.value += 1;
505
- }
506
- if (node.optional) {
507
- parenStart.value = callerEnd.value + textAfterCaller.value.indexOf("(");
508
- }
509
- const spaces = /(\s*)$/.exec(textBetweenFunctionNameAndParen.value)[1];
510
- if (!hasGenerics.value) {
511
- if (spaces.length > 0 && textBetweenFunctionNameAndParen.value !== "?.") {
512
- const textBeforeSpaces = textBetweenFunctionNameAndParen.value.slice(
513
- 0,
514
- textBetweenFunctionNameAndParen.value.length - spaces.length
515
- );
516
- context.report({
517
- node,
518
- messageId: "noSpaceBeforeParen",
519
- *fix(fixer) {
520
- yield fixer.replaceTextRange(
521
- textBetweenFunctionNameAndParenRange.value,
522
- textBeforeSpaces + (node.optional ? "?." : "")
523
- );
524
- }
525
- });
526
- }
527
- } else {
528
- const preSpaces = /^(\s*)/.exec(textBetweenFunctionNameAndParen.value)[1];
529
- const postSpaces = /(\s*)$/.exec(textBetweenFunctionNameAndParen.value)[1];
530
- const spacesBeforeOptionalMark = /(\s*)\?\./.exec(textBetweenFunctionNameAndParen.value)?.[1] ?? "";
531
- if (preSpaces.length > 0) {
532
- context.report({
533
- node,
534
- messageId: "noSpaceBeforeParen",
535
- *fix(fixer) {
536
- yield fixer.removeRange([callerEnd.value, callerEnd.value + preSpaces.length]);
537
- }
538
- });
539
- }
540
- if (postSpaces.length > 0) {
541
- context.report({
542
- node,
543
- messageId: "noSpaceBeforeParen",
544
- *fix(fixer) {
545
- yield fixer.removeRange([parenStart.value - postSpaces.length, parenStart.value]);
546
- }
547
- });
548
- }
549
- if (spacesBeforeOptionalMark.length > 0 && !textBetweenFunctionNameAndParen.value.endsWith(" ")) {
550
- context.report({
551
- node,
552
- messageId: "noSpaceBeforeParen",
553
- *fix(fixer) {
554
- yield fixer.removeRange([parenStart.value - spacesBeforeOptionalMark.length - 2, parenStart.value - 2]);
555
- }
556
- });
557
- }
558
- }
559
- },
560
- NewExpression(node) {
561
- const calleeEnd = node.callee.range[1];
562
- const textAfterCallee = text.slice(calleeEnd);
563
- const parenStart = calleeEnd + textAfterCallee.indexOf("(");
564
- const textBetweenCalleeAndParenRange = [calleeEnd, parenStart];
565
- const textBetweenCalleeAndParen = text.slice(...textBetweenCalleeAndParenRange);
566
- const hasGenerics = /^\s*</.test(textBetweenCalleeAndParen);
567
- if (!hasGenerics && textBetweenCalleeAndParen.length > 0) {
568
- context.report({
569
- node,
570
- messageId: "noSpaceBeforeParen",
571
- *fix(fixer) {
572
- yield fixer.removeRange(textBetweenCalleeAndParenRange);
573
- }
574
- });
575
- } else if (hasGenerics) {
576
- const preSpaces = /^(\s*)/.exec(textBetweenCalleeAndParen)[1];
577
- const postSpaces = /(\s*)$/.exec(textBetweenCalleeAndParen)[1];
578
- if (preSpaces.length > 0) {
579
- context.report({
580
- node,
581
- messageId: "noSpaceBeforeParen",
582
- *fix(fixer) {
583
- yield fixer.removeRange([calleeEnd, calleeEnd + preSpaces.length]);
584
- }
585
- });
586
- }
587
- if (postSpaces.length > 0) {
588
- context.report({
589
- node,
590
- messageId: "noSpaceBeforeParen",
591
- *fix(fixer) {
592
- yield fixer.removeRange([parenStart - postSpaces.length, parenStart]);
593
- }
594
- });
595
- }
596
- }
597
- }
598
- };
599
- }
600
- });
601
-
602
- const RULE_NAME$3 = "semi-spacing";
603
- const semiSpacing = createEslintRule({
604
- name: RULE_NAME$3,
605
- meta: {
606
- type: "layout",
607
- docs: {
608
- description: "Semicolon spacing in types",
609
- recommended: "error"
610
- },
611
- fixable: "whitespace",
612
- schema: [],
613
- messages: {
614
- noSpaceBeforeSemi: "Expected no space before semicolon"
615
- }
616
- },
617
- defaultOptions: [],
618
- create: (context) => {
619
- const sourceCode = context.getSourceCode();
620
- return {
621
- TSTypeAliasDeclaration(node) {
622
- const leftToken = node.typeAnnotation;
623
- const rightToken = sourceCode.getTokenAfter(node.typeAnnotation);
624
- if (!rightToken || rightToken.type !== AST_TOKEN_TYPES.Punctuator || rightToken.value !== ";") {
625
- return;
626
- }
627
- const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
628
- if (hasSpacing) {
629
- context.report({
630
- loc: {
631
- start: {
632
- line: leftToken.loc.end.line,
633
- column: leftToken.loc.end.column
634
- },
635
- end: {
636
- line: rightToken.loc.start.line,
637
- column: rightToken.loc.start.column
638
- }
639
- },
640
- node,
641
- messageId: "noSpaceBeforeSemi",
642
- *fix(fixer) {
643
- yield fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
644
- }
645
- });
646
- }
647
- }
648
- };
649
- }
650
- });
651
-
652
- const RULE_NAME$2 = "space-before-function-paren";
653
- const spaceBeforeFunctionParen = createEslintRule({
654
- name: RULE_NAME$2,
655
- meta: {
656
- type: "layout",
657
- docs: {
658
- description: "Enforce consistent spacing before function parenthesis",
659
- recommended: false,
660
- extendsBaseRule: true
661
- },
662
- fixable: "whitespace",
663
- schema: [
664
- {
665
- oneOf: [
666
- {
667
- enum: ["always", "never"]
668
- },
669
- {
670
- type: "object",
671
- properties: {
672
- anonymous: {
673
- enum: ["always", "never", "ignore"]
674
- },
675
- named: {
676
- enum: ["always", "never", "ignore"]
677
- },
678
- asyncArrow: {
679
- enum: ["always", "never", "ignore"]
680
- }
681
- },
682
- additionalProperties: false
683
- }
684
- ]
685
- }
686
- ],
687
- messages: {
688
- unexpected: "Unexpected space before function parentheses.",
689
- missing: "Missing space before function parentheses."
690
- }
691
- },
692
- defaultOptions: ["always"],
693
- create(context, [firstOption]) {
694
- const sourceCode = context.getSourceCode();
695
- const baseConfig = typeof firstOption === "string" ? firstOption : "always";
696
- const overrideConfig = typeof firstOption === "object" ? firstOption : {};
697
- function isNamedFunction(node) {
698
- if (node.id != null) {
699
- return true;
700
- }
701
- const parent = node.parent;
702
- return parent.type === AST_NODE_TYPES.MethodDefinition || parent.type === AST_NODE_TYPES.TSAbstractMethodDefinition || parent.type === AST_NODE_TYPES.Property && (parent.kind === "get" || parent.kind === "set" || parent.method);
703
- }
704
- function getConfigForFunction(node) {
705
- if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
706
- if (node.async && util.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) {
707
- return overrideConfig.asyncArrow ?? baseConfig;
708
- }
709
- } else if (isNamedFunction(node)) {
710
- return overrideConfig.named ?? baseConfig;
711
- } else if (!node.generator) {
712
- return overrideConfig.anonymous ?? baseConfig;
713
- }
714
- return "ignore";
715
- }
716
- function checkFunction(node) {
717
- const functionConfig = getConfigForFunction(node);
718
- if (functionConfig === "ignore") {
719
- return;
720
- }
721
- let leftToken, rightToken;
722
- if (node.typeParameters) {
723
- leftToken = sourceCode.getLastToken(node.typeParameters);
724
- rightToken = sourceCode.getTokenAfter(leftToken);
725
- } else {
726
- rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken);
727
- leftToken = sourceCode.getTokenBefore(rightToken);
728
- }
729
- const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
730
- if (hasSpacing && functionConfig === "never") {
731
- context.report({
732
- node,
733
- loc: {
734
- start: leftToken.loc.end,
735
- end: rightToken.loc.start
736
- },
737
- messageId: "unexpected",
738
- fix: (fixer) => fixer.removeRange([leftToken.range[1], rightToken.range[0]])
739
- });
740
- } else if (!hasSpacing && functionConfig === "always" && !node.typeParameters) {
741
- context.report({
742
- node,
743
- loc: rightToken.loc,
744
- messageId: "missing",
745
- fix: (fixer) => fixer.insertTextAfter(leftToken, " ")
746
- });
747
- }
748
- }
749
- return {
750
- ArrowFunctionExpression: checkFunction,
751
- FunctionDeclaration: checkFunction,
752
- FunctionExpression: checkFunction,
753
- TSEmptyBodyFunctionExpression: checkFunction,
754
- TSDeclareFunction: checkFunction
755
- };
756
- }
757
- });
758
-
759
- const operatorOrAnyBracketOrKeywordRE = /^(\||&|\*|\+|\-|\/|%|<|>|<=|>=|==|!=|===|!==|\[|\(|\{|as|extends|implements|keyof|new|readonly|typeof|unique|unknown)/;
760
- const RULE_NAME$1 = "space-between-generic-and-paren";
761
- const spaceBetweenGenericAndParen = createEslintRule({
762
- name: RULE_NAME$1,
763
- meta: {
764
- type: "layout",
765
- docs: {
766
- description: "Spaces between generic type parameters and paren",
767
- recommended: "error"
768
- },
769
- fixable: "whitespace",
770
- schema: [],
771
- messages: {
772
- noSpaceBetweenGenericAndParen: "Expected no space between generic type parameters and paren"
773
- }
774
- },
775
- defaultOptions: [],
776
- create: (context) => {
777
- const sourceCode = context.getSourceCode();
778
- const text = sourceCode.text;
779
- return {
780
- TSTypeParameter: (node) => {
781
- const spaceStartRange = node.range[1] + 1;
782
- const post = text.slice(spaceStartRange);
783
- const postSpace = post.match(/^(\s*)/)?.[0];
784
- const postEqual = post.slice(postSpace.length).match(/^(=)/)?.[0];
785
- const postComma = text.slice(node.range[1]).match(/^(,)/)?.[0];
786
- const postQuestionMark = text.slice(spaceStartRange + postSpace.length).match(/^(\?)/)?.[0];
787
- const postOperatorOrAnyBracketOrKeyword = text.slice(spaceStartRange + postSpace.length).match(operatorOrAnyBracketOrKeywordRE)?.[0];
788
- if (postSpace?.length && !postEqual && !postComma && !postQuestionMark && !postOperatorOrAnyBracketOrKeyword && node.parent.type !== AST_NODE_TYPES.TSInferType) {
789
- context.report({
790
- loc: {
791
- start: {
792
- line: node.loc.end.line,
793
- column: node.loc.end.column + 1
794
- },
795
- end: {
796
- line: node.loc.end.line,
797
- column: node.loc.end.column + 1 + postSpace.length
798
- }
799
- },
800
- node,
801
- messageId: "noSpaceBetweenGenericAndParen",
802
- *fix(fixer) {
803
- yield fixer.replaceTextRange([spaceStartRange, spaceStartRange + postSpace.length], "");
804
- }
805
- });
806
- }
807
- if (node.parent?.parent.type === AST_NODE_TYPES.FunctionDeclaration) {
808
- const spaceEndRange = node.range[0] - 1;
809
- const pre = sourceCode.text.slice(0, spaceEndRange);
810
- const preSpace = pre.match(/(\s+)$/)?.[0];
811
- if (preSpace?.length) {
812
- context.report({
813
- loc: {
814
- start: {
815
- line: node.loc.start.line,
816
- column: node.loc.start.column - preSpace.length
817
- },
818
- end: {
819
- line: node.loc.start.line,
820
- column: node.loc.start.column - 1
821
- }
822
- },
823
- node,
824
- messageId: "noSpaceBetweenGenericAndParen",
825
- *fix(fixer) {
826
- yield fixer.replaceTextRange([spaceEndRange - preSpace.length, spaceEndRange], "");
827
- }
828
- });
829
- }
830
- }
831
- }
832
- };
833
- }
834
- });
835
-
836
- const RULE_NAME = "space-in-empty-block";
837
- const spaceInEmptyBlock = createEslintRule({
107
+ const RULE_NAME = "no-useless-template-string";
108
+ const noUselessTemplateString = createEslintRule({
838
109
  name: RULE_NAME,
839
110
  meta: {
840
- type: "layout",
111
+ type: "problem",
841
112
  docs: {
842
- description: "Disallow spaces in empty block",
113
+ description: "No useless template string",
843
114
  recommended: "error"
844
115
  },
845
- fixable: "whitespace",
116
+ fixable: "code",
846
117
  schema: [],
847
118
  messages: {
848
- noSpaceInEmptyBlock: "Expected no space in empty block"
119
+ noUselessTemplateString: "No useless template string"
849
120
  }
850
121
  },
851
122
  defaultOptions: [],
852
123
  create: (context) => {
853
- const sourceCode = context.getSourceCode();
854
124
  return {
855
- BlockStatement: (node) => {
856
- if (node.body.length || sourceCode.getCommentsInside(node).length) {
857
- return;
858
- }
859
- const spaceStartRange = node.range[1] - 2;
860
- const post = sourceCode.text.slice(spaceStartRange);
861
- const postSpace = post.match(/^(\s*)/)?.[0];
862
- if (postSpace?.length) {
125
+ TemplateLiteral(node) {
126
+ const hasNewline = node.quasis.some((n) => n.value.raw.includes("\n"));
127
+ if (node.expressions.length === 0 && !hasNewline) {
863
128
  context.report({
864
- loc: {
865
- start: node.loc.start,
866
- end: {
867
- line: node.loc.end.line,
868
- column: node.loc.end.column - 1 + postSpace.length
869
- }
870
- },
871
- messageId: "noSpaceInEmptyBlock",
872
- *fix(fixer) {
873
- yield fixer.replaceTextRange([node.range[0] + 1, spaceStartRange + postSpace.length], "");
874
- }
875
- });
876
- }
877
- const spaceEndRange = node.range[0] + 1;
878
- const pre = sourceCode.text.slice(0, spaceEndRange);
879
- const preSpace = pre.match(/(\s+)$/)?.[0];
880
- if (preSpace?.length) {
881
- context.report({
882
- loc: {
883
- start: {
884
- line: node.loc.start.line,
885
- column: node.loc.start.column - preSpace.length
886
- },
887
- end: {
888
- line: node.loc.start.line,
889
- column: node.loc.start.column
890
- }
891
- },
892
- messageId: "noSpaceInEmptyBlock",
893
- *fix(fixer) {
894
- yield fixer.replaceTextRange([spaceEndRange - preSpace.length, spaceEndRange], "");
129
+ node,
130
+ messageId: "noUselessTemplateString",
131
+ fix(fixer) {
132
+ const s = node.range[0];
133
+ const e = node.range[1];
134
+ return fixer.replaceTextRange([s, e], `"${node.quasis[0].value.raw}"`);
895
135
  }
896
136
  });
897
137
  }
@@ -903,14 +143,8 @@ const spaceInEmptyBlock = createEslintRule({
903
143
  const index = {
904
144
  rules: {
905
145
  "import-dedupe": importDedupe,
906
- "generic-spacing": genericSpacing,
907
- "space-between-generic-and-paren": spaceBetweenGenericAndParen,
908
- "space-in-empty-block": spaceInEmptyBlock,
909
- "semi-spacing": semiSpacing,
910
146
  "no-inline-type-import": noInlineTypeImport,
911
- "no-space-before-paren": noSpaceBeforeParen,
912
- "space-before-function-paren": spaceBeforeFunctionParen,
913
- "array-bracket-spacing": arrayBracketSpacing
147
+ "no-useless-template-string": noUselessTemplateString
914
148
  }
915
149
  };
916
150