@so1ve/eslint-plugin 0.44.0 → 0.45.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const utils = require('@typescript-eslint/utils');
4
- const reactivity = require('@vue/reactivity');
5
4
  const util = require('@typescript-eslint/utils/dist/ast-utils');
5
+ const reactivity = require('@vue/reactivity');
6
6
 
7
7
  function _interopNamespaceDefault(e) {
8
8
  const n = Object.create(null);
@@ -19,9 +19,9 @@ const util__namespace = /*#__PURE__*/_interopNamespaceDefault(util);
19
19
 
20
20
  const createEslintRule = utils.ESLintUtils.RuleCreator((ruleName) => ruleName);
21
21
 
22
- const RULE_NAME$7 = "generic-spacing";
22
+ const RULE_NAME$9 = "generic-spacing";
23
23
  const genericSpacing = createEslintRule({
24
- name: RULE_NAME$7,
24
+ name: RULE_NAME$9,
25
25
  meta: {
26
26
  type: "layout",
27
27
  docs: {
@@ -43,18 +43,17 @@ const genericSpacing = createEslintRule({
43
43
  const params = node.params;
44
44
  for (let i = 0; i < params.length; i++) {
45
45
  const param = params[i];
46
- const pre = sourceCode.text.slice(0, param.range[0]);
47
- const preSpace = pre.match(/(\s+)$/)?.[0];
48
- const preComma = pre.match(/(,)\s+$/)?.[0];
49
- const post = sourceCode.text.slice(param.range[1]);
50
- const postSpace = post.match(/^(\s*)/)?.[0];
51
- if (preSpace && preSpace.length && !preComma && param.loc.start.line === node.loc.start.line) {
46
+ const leftToken = sourceCode.getTokenBefore(param);
47
+ const rightToken = sourceCode.getTokenAfter(param);
48
+ const hasSpacingBeforeParam = sourceCode.isSpaceBetween(leftToken, param);
49
+ const hasSpacingAfterParam = sourceCode.isSpaceBetween(param, rightToken);
50
+ if (hasSpacingBeforeParam && param.loc.start.line === node.loc.start.line && leftToken.value === "<") {
52
51
  context.report({
53
52
  node,
54
53
  loc: {
55
54
  start: {
56
- line: param.loc.start.line,
57
- column: param.loc.start.column + 1 - preSpace.length
55
+ line: leftToken.loc.end.line,
56
+ column: leftToken.loc.end.column
58
57
  },
59
58
  end: {
60
59
  line: param.loc.start.line,
@@ -63,11 +62,11 @@ const genericSpacing = createEslintRule({
63
62
  },
64
63
  messageId: "genericSpacingMismatch",
65
64
  *fix(fixer) {
66
- yield fixer.removeRange([param.range[0] - preSpace.length, param.range[0]]);
65
+ yield fixer.removeRange([leftToken.range[1], param.range[0]]);
67
66
  }
68
67
  });
69
68
  }
70
- if (postSpace && postSpace.length && param.loc.end.line === node.loc.end.line) {
69
+ if (hasSpacingAfterParam && param.loc.end.line === node.loc.end.line) {
71
70
  context.report({
72
71
  loc: {
73
72
  start: {
@@ -75,59 +74,80 @@ const genericSpacing = createEslintRule({
75
74
  column: param.loc.end.column
76
75
  },
77
76
  end: {
78
- line: param.loc.end.line,
79
- column: param.loc.end.column + postSpace.length
77
+ line: rightToken.loc.start.line,
78
+ column: rightToken.loc.start.column
80
79
  }
81
80
  },
82
81
  node,
83
82
  messageId: "genericSpacingMismatch",
84
83
  *fix(fixer) {
85
- yield fixer.replaceTextRange([param.range[1], param.range[1] + postSpace.length], "");
84
+ yield fixer.removeRange([param.range[1], rightToken.range[0]]);
86
85
  }
87
86
  });
88
87
  }
89
- }
90
- if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression"].includes(node.parent.type)) {
91
- const pre = sourceCode.text.slice(0, node.range[0]);
92
- const preSpace = pre.match(/(\s+)$/)?.[0];
93
- const post = sourceCode.text.slice(node.range[1]);
94
- const postBracket = post.match(/^(\s*)\(/)?.[0];
95
- if (preSpace && preSpace.length && !postBracket) {
88
+ if (!hasSpacingBeforeParam && util__namespace.isCommaToken(leftToken)) {
96
89
  context.report({
97
90
  node,
91
+ loc: {
92
+ start: {
93
+ line: leftToken.loc.end.line,
94
+ column: leftToken.loc.end.column
95
+ },
96
+ end: {
97
+ line: param.loc.start.line,
98
+ column: param.loc.start.column - 1
99
+ }
100
+ },
98
101
  messageId: "genericSpacingMismatch",
99
102
  *fix(fixer) {
100
- yield fixer.removeRange([node.range[0] - preSpace.length, node.range[0]]);
103
+ yield fixer.replaceTextRange([leftToken.range[1], param.range[0]], " ");
101
104
  }
102
105
  });
103
106
  }
104
- if (postBracket && postBracket.length > 1) {
107
+ }
108
+ if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression"].includes(node.parent.type)) {
109
+ const leftToken = sourceCode.getTokenBefore(node);
110
+ const hasSpacingBeforeNode = sourceCode.isSpaceBetween(leftToken, node);
111
+ const lastParam = params[params.length - 1];
112
+ const endBracket = sourceCode.getTokenAfter(lastParam);
113
+ const rightToken = sourceCode.getTokenAfter(endBracket, util__namespace.isOpeningParenToken);
114
+ const hasSpacingAfterParam = sourceCode.isSpaceBetween(endBracket, rightToken);
115
+ if (hasSpacingBeforeNode && node.parent.type !== utils.AST_NODE_TYPES.TSFunctionType) {
105
116
  context.report({
106
117
  node,
118
+ loc: {
119
+ start: {
120
+ line: leftToken.loc.end.line,
121
+ column: leftToken.loc.end.column
122
+ },
123
+ end: {
124
+ line: node.loc.start.line,
125
+ column: node.loc.start.column
126
+ }
127
+ },
107
128
  messageId: "genericSpacingMismatch",
108
129
  *fix(fixer) {
109
- yield fixer.removeRange([node.range[1], node.range[1] + postBracket.length - 1]);
130
+ yield fixer.removeRange([leftToken.range[1], node.range[0]]);
110
131
  }
111
132
  });
112
133
  }
113
- }
114
- for (let i = 1; i < params.length; i++) {
115
- const prev = params[i - 1];
116
- const current = params[i];
117
- const from = prev.range[1];
118
- const to = current.range[0];
119
- const span = sourceCode.text.slice(from, to);
120
- if (span !== ", " && !span.match(/,\n/)) {
134
+ if (hasSpacingAfterParam && [utils.AST_NODE_TYPES.TSFunctionType, utils.AST_NODE_TYPES.FunctionDeclaration, utils.AST_NODE_TYPES.FunctionExpression].includes(node.parent.type)) {
121
135
  context.report({
122
- *fix(fixer) {
123
- yield fixer.replaceTextRange([from, to], ", ");
124
- },
136
+ node,
125
137
  loc: {
126
- start: prev.loc.end,
127
- end: current.loc.start
138
+ start: {
139
+ line: endBracket.loc.end.line,
140
+ column: endBracket.loc.end.column
141
+ },
142
+ end: {
143
+ line: rightToken.loc.start.line,
144
+ column: rightToken.loc.start.column
145
+ }
128
146
  },
129
147
  messageId: "genericSpacingMismatch",
130
- node
148
+ *fix(fixer) {
149
+ yield fixer.removeRange([endBracket.range[1], rightToken.range[0]]);
150
+ }
131
151
  });
132
152
  }
133
153
  }
@@ -188,46 +208,45 @@ const genericSpacing = createEslintRule({
188
208
  const params = node.params;
189
209
  for (let i = 0; i < params.length; i++) {
190
210
  const param = params[i];
191
- const pre = sourceCode.text.slice(0, param.range[0]);
192
- const preSpace = pre.match(/(\s+)$/)?.[0];
193
- const preComma = pre.match(/(,)\s+$/)?.[0];
194
- const post = sourceCode.text.slice(param.range[1]);
195
- const postSpace = post.match(/^(\s*)/)?.[0];
196
- if (preSpace && preSpace.length && !preComma && param.loc.start.line === node.loc.start.line) {
211
+ const leftToken = sourceCode.getTokenBefore(param);
212
+ const rightToken = sourceCode.getTokenAfter(param);
213
+ const hasSpacingBeforeParam = leftToken.value === "<" ? sourceCode.isSpaceBetween(leftToken, param) : false;
214
+ const hasSpacingAfterParam = rightToken.value === ">" ? sourceCode.isSpaceBetween(param, rightToken) : false;
215
+ if (hasSpacingBeforeParam && leftToken.loc.end.line === param.loc.start.line) {
197
216
  context.report({
198
217
  node,
199
218
  loc: {
200
219
  start: {
201
- line: param.loc.start.line,
202
- column: param.loc.start.column + 1 - preSpace.length
220
+ line: leftToken.loc.end.line,
221
+ column: leftToken.loc.end.column
203
222
  },
204
223
  end: {
205
224
  line: param.loc.start.line,
206
- column: param.loc.start.column - 1
225
+ column: param.loc.start.column
207
226
  }
208
227
  },
209
228
  messageId: "genericSpacingMismatch",
210
229
  *fix(fixer) {
211
- yield fixer.replaceTextRange([param.range[0] - preSpace.length, param.range[0]], "");
230
+ yield fixer.removeRange([leftToken.range[1], param.range[0]]);
212
231
  }
213
232
  });
214
233
  }
215
- if (postSpace && postSpace.length && param.loc.end.line === node.loc.end.line) {
234
+ if (hasSpacingAfterParam && param.loc.end.line === rightToken.loc.start.line) {
216
235
  context.report({
236
+ node,
217
237
  loc: {
218
238
  start: {
219
239
  line: param.loc.end.line,
220
240
  column: param.loc.end.column
221
241
  },
222
242
  end: {
223
- line: param.loc.end.line,
224
- column: param.loc.end.column + postSpace.length
243
+ line: rightToken.loc.start.line,
244
+ column: rightToken.loc.start.column
225
245
  }
226
246
  },
227
- node,
228
247
  messageId: "genericSpacingMismatch",
229
248
  *fix(fixer) {
230
- yield fixer.replaceTextRange([param.range[1], param.range[1] + postSpace.length], "");
249
+ yield fixer.removeRange([param.range[1], rightToken.range[0]]);
231
250
  }
232
251
  });
233
252
  }
@@ -269,9 +288,9 @@ const genericSpacing = createEslintRule({
269
288
  }
270
289
  });
271
290
 
272
- const RULE_NAME$6 = "import-dedupe";
291
+ const RULE_NAME$8 = "import-dedupe";
273
292
  const importDedupe = createEslintRule({
274
- name: RULE_NAME$6,
293
+ name: RULE_NAME$8,
275
294
  meta: {
276
295
  type: "problem",
277
296
  docs: {
@@ -320,9 +339,9 @@ const importDedupe = createEslintRule({
320
339
  });
321
340
 
322
341
  const operatorOrAnyBracketOrKeywordRE = /^(\||&|\*|\+|\-|\/|%|<|>|<=|>=|==|!=|===|!==|\[|\(|\{|as|extends|implements|keyof|new|readonly|typeof|unique|unknown)/;
323
- const RULE_NAME$5 = "space-between-generic-and-paren";
342
+ const RULE_NAME$7 = "space-between-generic-and-paren";
324
343
  const spaceBetweenGenericAndParen = createEslintRule({
325
- name: RULE_NAME$5,
344
+ name: RULE_NAME$7,
326
345
  meta: {
327
346
  type: "layout",
328
347
  docs: {
@@ -348,7 +367,7 @@ const spaceBetweenGenericAndParen = createEslintRule({
348
367
  const postComma = text.slice(node.range[1]).match(/^(,)/)?.[0];
349
368
  const postQuestionMark = text.slice(spaceStartRange + postSpace.length).match(/^(\?)/)?.[0];
350
369
  const postOperatorOrAnyBracketOrKeyword = text.slice(spaceStartRange + postSpace.length).match(operatorOrAnyBracketOrKeywordRE)?.[0];
351
- if (postSpace && postSpace.length && !postEqual && !postComma && !postQuestionMark && !postOperatorOrAnyBracketOrKeyword && node.parent.type !== "TSInferType") {
370
+ if (postSpace && postSpace.length && !postEqual && !postComma && !postQuestionMark && !postOperatorOrAnyBracketOrKeyword && node.parent.type !== utils.AST_NODE_TYPES.TSInferType) {
352
371
  context.report({
353
372
  loc: {
354
373
  start: {
@@ -367,7 +386,7 @@ const spaceBetweenGenericAndParen = createEslintRule({
367
386
  }
368
387
  });
369
388
  }
370
- if (node.parent?.parent.type === "FunctionDeclaration") {
389
+ if (node.parent?.parent.type === utils.AST_NODE_TYPES.FunctionDeclaration) {
371
390
  const spaceEndRange = node.range[0] - 1;
372
391
  const pre = sourceCode.text.slice(0, spaceEndRange);
373
392
  const preSpace = pre.match(/(\s+)$/)?.[0];
@@ -396,19 +415,19 @@ const spaceBetweenGenericAndParen = createEslintRule({
396
415
  }
397
416
  });
398
417
 
399
- const RULE_NAME$4 = "no-spaces-before-paren";
400
- const noSpacesBeforeParen = createEslintRule({
401
- name: RULE_NAME$4,
418
+ const RULE_NAME$6 = "no-space-before-paren";
419
+ const noSpaceBeforeParen = createEslintRule({
420
+ name: RULE_NAME$6,
402
421
  meta: {
403
422
  type: "layout",
404
423
  docs: {
405
- description: "Spaces before paren",
424
+ description: "Space before paren",
406
425
  recommended: "error"
407
426
  },
408
427
  fixable: "whitespace",
409
428
  schema: [],
410
429
  messages: {
411
- noSpacesBeforeParen: "Expected no space before paren"
430
+ noSpaceBeforeParen: "Expected no space before paren"
412
431
  }
413
432
  },
414
433
  defaultOptions: [],
@@ -425,7 +444,7 @@ const noSpacesBeforeParen = createEslintRule({
425
444
  if (textBetweenImportAndParen.length > 0) {
426
445
  context.report({
427
446
  node,
428
- messageId: "noSpacesBeforeParen",
447
+ messageId: "noSpaceBeforeParen",
429
448
  *fix(fixer) {
430
449
  yield fixer.removeRange(textBetweenImportAndParenRange);
431
450
  }
@@ -434,7 +453,7 @@ const noSpacesBeforeParen = createEslintRule({
434
453
  },
435
454
  CallExpression(node) {
436
455
  let caller = "property" in node.callee ? node.callee.property : node.callee;
437
- if (caller.type === "TSInstantiationExpression" && "property" in caller.expression) {
456
+ if (caller.type === utils.AST_NODE_TYPES.TSInstantiationExpression && "property" in caller.expression) {
438
457
  caller = caller.expression.property;
439
458
  }
440
459
  const callerEnd = reactivity.ref(caller.range[1]);
@@ -454,7 +473,7 @@ const noSpacesBeforeParen = createEslintRule({
454
473
  if (textBetweenFunctionNameAndParen.value.length > 0 && textBetweenFunctionNameAndParen.value !== "?.") {
455
474
  context.report({
456
475
  node,
457
- messageId: "noSpacesBeforeParen",
476
+ messageId: "noSpaceBeforeParen",
458
477
  *fix(fixer) {
459
478
  yield fixer.replaceTextRange(textBetweenFunctionNameAndParenRange.value, node.optional ? "?." : "");
460
479
  }
@@ -467,7 +486,7 @@ const noSpacesBeforeParen = createEslintRule({
467
486
  if (preSpaces.length > 0) {
468
487
  context.report({
469
488
  node,
470
- messageId: "noSpacesBeforeParen",
489
+ messageId: "noSpaceBeforeParen",
471
490
  *fix(fixer) {
472
491
  yield fixer.removeRange([callerEnd.value, callerEnd.value + preSpaces.length]);
473
492
  }
@@ -476,7 +495,7 @@ const noSpacesBeforeParen = createEslintRule({
476
495
  if (postSpaces.length > 0) {
477
496
  context.report({
478
497
  node,
479
- messageId: "noSpacesBeforeParen",
498
+ messageId: "noSpaceBeforeParen",
480
499
  *fix(fixer) {
481
500
  yield fixer.removeRange([parenStart.value - postSpaces.length, parenStart.value]);
482
501
  }
@@ -485,7 +504,7 @@ const noSpacesBeforeParen = createEslintRule({
485
504
  if (spacesBeforeOptionalMark.length > 0 && !textBetweenFunctionNameAndParen.value.endsWith(" ")) {
486
505
  context.report({
487
506
  node,
488
- messageId: "noSpacesBeforeParen",
507
+ messageId: "noSpaceBeforeParen",
489
508
  *fix(fixer) {
490
509
  yield fixer.removeRange([parenStart.value - spacesBeforeOptionalMark.length - 2, parenStart.value - 2]);
491
510
  }
@@ -497,9 +516,9 @@ const noSpacesBeforeParen = createEslintRule({
497
516
  }
498
517
  });
499
518
 
500
- const RULE_NAME$3 = "space-in-empty-block";
519
+ const RULE_NAME$5 = "space-in-empty-block";
501
520
  const spaceInEmptyBlock = createEslintRule({
502
- name: RULE_NAME$3,
521
+ name: RULE_NAME$5,
503
522
  meta: {
504
523
  type: "layout",
505
524
  docs: {
@@ -564,9 +583,9 @@ const spaceInEmptyBlock = createEslintRule({
564
583
  }
565
584
  });
566
585
 
567
- const RULE_NAME$2 = "space-before-function-paren";
586
+ const RULE_NAME$4 = "space-before-function-paren";
568
587
  const spaceBeforeFunctionParen = createEslintRule({
569
- name: RULE_NAME$2,
588
+ name: RULE_NAME$4,
570
589
  meta: {
571
590
  type: "layout",
572
591
  docs: {
@@ -641,7 +660,7 @@ const spaceBeforeFunctionParen = createEslintRule({
641
660
  rightToken = sourceCode.getFirstToken(node, util__namespace.isOpeningParenToken);
642
661
  leftToken = sourceCode.getTokenBefore(rightToken);
643
662
  }
644
- const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken);
663
+ const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
645
664
  if (hasSpacing && functionConfig === "never") {
646
665
  context.report({
647
666
  node,
@@ -671,13 +690,13 @@ const spaceBeforeFunctionParen = createEslintRule({
671
690
  }
672
691
  });
673
692
 
674
- const RULE_NAME$1 = "semi-spacing";
693
+ const RULE_NAME$3 = "semi-spacing";
675
694
  const semiSpacing = createEslintRule({
676
- name: RULE_NAME$1,
695
+ name: RULE_NAME$3,
677
696
  meta: {
678
697
  type: "layout",
679
698
  docs: {
680
- description: "Semicolon spacing",
699
+ description: "Semicolon spacing in types",
681
700
  recommended: "error"
682
701
  },
683
702
  fixable: "whitespace",
@@ -689,29 +708,30 @@ const semiSpacing = createEslintRule({
689
708
  defaultOptions: [],
690
709
  create: (context) => {
691
710
  const sourceCode = context.getSourceCode();
692
- const text = sourceCode.text;
693
711
  return {
694
712
  TSTypeAliasDeclaration(node) {
695
- const sourceLine = text.slice(node.range[0], node.range[1]);
696
- const preSemiSpace = sourceLine.match(/(\s+);$/)?.[0];
697
- if (preSemiSpace) {
698
- const spaceStart = node.range[0] + sourceLine.length - preSemiSpace.length;
699
- const spaceEnd = node.range[0] + sourceLine.length - 1;
713
+ const leftToken = node.typeAnnotation;
714
+ const rightToken = sourceCode.getTokenAfter(node.typeAnnotation);
715
+ if (rightToken.type !== utils.AST_TOKEN_TYPES.Punctuator || rightToken.value !== ";") {
716
+ return;
717
+ }
718
+ const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
719
+ if (hasSpacing) {
700
720
  context.report({
701
721
  loc: {
702
722
  start: {
703
- line: node.loc.start.line,
704
- column: node.loc.start.column + sourceLine.length - preSemiSpace.length
723
+ line: leftToken.loc.end.line,
724
+ column: leftToken.loc.end.column
705
725
  },
706
726
  end: {
707
- line: node.loc.start.line,
708
- column: node.loc.start.column + sourceLine.length - 1
727
+ line: rightToken.loc.start.line,
728
+ column: rightToken.loc.start.column
709
729
  }
710
730
  },
711
731
  node,
712
732
  messageId: "noSpaceBeforeSemi",
713
733
  *fix(fixer) {
714
- yield fixer.removeRange([spaceStart, spaceEnd]);
734
+ yield fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
715
735
  }
716
736
  });
717
737
  }
@@ -720,9 +740,9 @@ const semiSpacing = createEslintRule({
720
740
  }
721
741
  });
722
742
 
723
- const RULE_NAME = "no-inline-type-import";
743
+ const RULE_NAME$2 = "no-inline-type-import";
724
744
  const noInlineTypeImport = createEslintRule({
725
- name: RULE_NAME,
745
+ name: RULE_NAME$2,
726
746
  meta: {
727
747
  type: "layout",
728
748
  docs: {
@@ -769,6 +789,120 @@ import { ${valueSpecifiersText} } from "${node.source.value}";`);
769
789
  }
770
790
  });
771
791
 
792
+ const RULE_NAME$1 = "no-beginning-newline";
793
+ const noBeginningNewline = createEslintRule({
794
+ name: RULE_NAME$1,
795
+ meta: {
796
+ type: "layout",
797
+ docs: {
798
+ description: "No beginning newline",
799
+ recommended: "error"
800
+ },
801
+ fixable: "whitespace",
802
+ schema: [],
803
+ messages: {
804
+ noBeginningNewline: "No beginning newline"
805
+ }
806
+ },
807
+ defaultOptions: [],
808
+ create: (context) => {
809
+ const text = context.getSourceCode().text;
810
+ return {
811
+ Program: (node) => {
812
+ const newlines = text.match(/([\n]*)/)[1];
813
+ if (newlines.length > 0) {
814
+ context.report({
815
+ node,
816
+ loc: {
817
+ start: {
818
+ line: 0,
819
+ column: 0
820
+ },
821
+ end: node.loc.start
822
+ },
823
+ messageId: "noBeginningNewline",
824
+ *fix(fixer) {
825
+ yield fixer.removeRange([0, node.range[0]]);
826
+ }
827
+ });
828
+ }
829
+ }
830
+ };
831
+ }
832
+ });
833
+
834
+ const RULE_NAME = "array-bracket-spacing";
835
+ const arrayBracketSpacing = createEslintRule({
836
+ name: RULE_NAME,
837
+ meta: {
838
+ type: "layout",
839
+ docs: {
840
+ description: "Array bracket spacing",
841
+ recommended: "error"
842
+ },
843
+ fixable: "whitespace",
844
+ schema: [],
845
+ messages: {
846
+ arrayBracketSpacing: "Array bracket spacing mismatch"
847
+ }
848
+ },
849
+ defaultOptions: [],
850
+ create: (context) => {
851
+ const sourceCode = context.getSourceCode();
852
+ const text = sourceCode.getText();
853
+ const checkNode = (node) => {
854
+ const elements = node.type === utils.AST_NODE_TYPES.TSTupleType ? node.elementTypes : node.elements;
855
+ const firstElement = elements[0];
856
+ const lastElement = elements[elements.length - 1];
857
+ if (!firstElement) {
858
+ return;
859
+ }
860
+ const leftToken = sourceCode.getTokenBefore(firstElement);
861
+ const rightToken = reactivity.ref(sourceCode.getTokenAfter(lastElement));
862
+ if (rightToken.value.value === ",") {
863
+ rightToken.value = sourceCode.getTokenAfter(rightToken.value);
864
+ }
865
+ const textBetweenFirstAndToken = reactivity.computed(() => text.slice(leftToken.range[1], firstElement.range[0]));
866
+ const isNewline = reactivity.computed(() => textBetweenFirstAndToken.value.includes("\n"));
867
+ const textBetweenLastAndToken = reactivity.computed(() => text.slice(lastElement.range[1], rightToken.value.range[0]));
868
+ const hasNewlineAfter = reactivity.computed(() => textBetweenLastAndToken.value.includes("\n"));
869
+ if (sourceCode.isSpaceBetween(leftToken, firstElement) && !isNewline.value) {
870
+ context.report({
871
+ node,
872
+ messageId: "arrayBracketSpacing",
873
+ *fix(fixer) {
874
+ yield fixer.removeRange([leftToken.range[1], firstElement.range[0]]);
875
+ }
876
+ });
877
+ }
878
+ if (sourceCode.isSpaceBetween(lastElement, rightToken.value)) {
879
+ if (!isNewline.value) {
880
+ context.report({
881
+ node,
882
+ messageId: "arrayBracketSpacing",
883
+ *fix(fixer) {
884
+ yield fixer.removeRange([lastElement.range[1], rightToken.value.range[0]]);
885
+ }
886
+ });
887
+ }
888
+ }
889
+ if (isNewline.value && !hasNewlineAfter.value) {
890
+ context.report({
891
+ node,
892
+ messageId: "arrayBracketSpacing",
893
+ *fix(fixer) {
894
+ yield fixer.replaceTextRange([lastElement.range[1], rightToken.value.range[0]], "\n");
895
+ }
896
+ });
897
+ }
898
+ };
899
+ return {
900
+ TSTupleType: checkNode,
901
+ ArrayExpression: checkNode
902
+ };
903
+ }
904
+ });
905
+
772
906
  const index = {
773
907
  rules: {
774
908
  "import-dedupe": importDedupe,
@@ -777,8 +911,10 @@ const index = {
777
911
  "space-in-empty-block": spaceInEmptyBlock,
778
912
  "semi-spacing": semiSpacing,
779
913
  "no-inline-type-import": noInlineTypeImport,
780
- "no-spaces-before-paren": noSpacesBeforeParen,
781
- "space-before-function-paren": spaceBeforeFunctionParen
914
+ "no-space-before-paren": noSpaceBeforeParen,
915
+ "space-before-function-paren": spaceBeforeFunctionParen,
916
+ "no-beginning-newline": noBeginningNewline,
917
+ "array-bracket-spacing": arrayBracketSpacing
782
918
  }
783
919
  };
784
920
 
package/dist/index.d.ts CHANGED
@@ -19,8 +19,10 @@ declare const _default: {
19
19
  "space-in-empty-block": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noSpaceInEmptyBlock", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
20
20
  "semi-spacing": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noSpaceBeforeSemi", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
21
21
  "no-inline-type-import": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noInlineTypeImport", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
22
- "no-spaces-before-paren": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noSpacesBeforeParen", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
22
+ "no-space-before-paren": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noSpaceBeforeParen", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
23
23
  "space-before-function-paren": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<MessageIds, Options, _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
24
+ "no-beginning-newline": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"noBeginningNewline", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
25
+ "array-bracket-spacing": _typescript_eslint_utils_dist_ts_eslint_Rule.RuleModule<"arrayBracketSpacing", [], _typescript_eslint_utils_dist_ts_eslint_Rule.RuleListener>;
24
26
  };
25
27
  };
26
28
 
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
2
- import { ref, computed } from '@vue/reactivity';
1
+ import { ESLintUtils, AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils';
3
2
  import * as util from '@typescript-eslint/utils/dist/ast-utils';
3
+ import { ref, computed } from '@vue/reactivity';
4
4
 
5
5
  const createEslintRule = ESLintUtils.RuleCreator((ruleName) => ruleName);
6
6
 
7
- const RULE_NAME$7 = "generic-spacing";
7
+ const RULE_NAME$9 = "generic-spacing";
8
8
  const genericSpacing = createEslintRule({
9
- name: RULE_NAME$7,
9
+ name: RULE_NAME$9,
10
10
  meta: {
11
11
  type: "layout",
12
12
  docs: {
@@ -28,18 +28,17 @@ const genericSpacing = createEslintRule({
28
28
  const params = node.params;
29
29
  for (let i = 0; i < params.length; i++) {
30
30
  const param = params[i];
31
- const pre = sourceCode.text.slice(0, param.range[0]);
32
- const preSpace = pre.match(/(\s+)$/)?.[0];
33
- const preComma = pre.match(/(,)\s+$/)?.[0];
34
- const post = sourceCode.text.slice(param.range[1]);
35
- const postSpace = post.match(/^(\s*)/)?.[0];
36
- if (preSpace && preSpace.length && !preComma && param.loc.start.line === node.loc.start.line) {
31
+ const leftToken = sourceCode.getTokenBefore(param);
32
+ const rightToken = sourceCode.getTokenAfter(param);
33
+ const hasSpacingBeforeParam = sourceCode.isSpaceBetween(leftToken, param);
34
+ const hasSpacingAfterParam = sourceCode.isSpaceBetween(param, rightToken);
35
+ if (hasSpacingBeforeParam && param.loc.start.line === node.loc.start.line && leftToken.value === "<") {
37
36
  context.report({
38
37
  node,
39
38
  loc: {
40
39
  start: {
41
- line: param.loc.start.line,
42
- column: param.loc.start.column + 1 - preSpace.length
40
+ line: leftToken.loc.end.line,
41
+ column: leftToken.loc.end.column
43
42
  },
44
43
  end: {
45
44
  line: param.loc.start.line,
@@ -48,11 +47,11 @@ const genericSpacing = createEslintRule({
48
47
  },
49
48
  messageId: "genericSpacingMismatch",
50
49
  *fix(fixer) {
51
- yield fixer.removeRange([param.range[0] - preSpace.length, param.range[0]]);
50
+ yield fixer.removeRange([leftToken.range[1], param.range[0]]);
52
51
  }
53
52
  });
54
53
  }
55
- if (postSpace && postSpace.length && param.loc.end.line === node.loc.end.line) {
54
+ if (hasSpacingAfterParam && param.loc.end.line === node.loc.end.line) {
56
55
  context.report({
57
56
  loc: {
58
57
  start: {
@@ -60,59 +59,80 @@ const genericSpacing = createEslintRule({
60
59
  column: param.loc.end.column
61
60
  },
62
61
  end: {
63
- line: param.loc.end.line,
64
- column: param.loc.end.column + postSpace.length
62
+ line: rightToken.loc.start.line,
63
+ column: rightToken.loc.start.column
65
64
  }
66
65
  },
67
66
  node,
68
67
  messageId: "genericSpacingMismatch",
69
68
  *fix(fixer) {
70
- yield fixer.replaceTextRange([param.range[1], param.range[1] + postSpace.length], "");
69
+ yield fixer.removeRange([param.range[1], rightToken.range[0]]);
71
70
  }
72
71
  });
73
72
  }
74
- }
75
- if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression"].includes(node.parent.type)) {
76
- const pre = sourceCode.text.slice(0, node.range[0]);
77
- const preSpace = pre.match(/(\s+)$/)?.[0];
78
- const post = sourceCode.text.slice(node.range[1]);
79
- const postBracket = post.match(/^(\s*)\(/)?.[0];
80
- if (preSpace && preSpace.length && !postBracket) {
73
+ if (!hasSpacingBeforeParam && util.isCommaToken(leftToken)) {
81
74
  context.report({
82
75
  node,
76
+ loc: {
77
+ start: {
78
+ line: leftToken.loc.end.line,
79
+ column: leftToken.loc.end.column
80
+ },
81
+ end: {
82
+ line: param.loc.start.line,
83
+ column: param.loc.start.column - 1
84
+ }
85
+ },
83
86
  messageId: "genericSpacingMismatch",
84
87
  *fix(fixer) {
85
- yield fixer.removeRange([node.range[0] - preSpace.length, node.range[0]]);
88
+ yield fixer.replaceTextRange([leftToken.range[1], param.range[0]], " ");
86
89
  }
87
90
  });
88
91
  }
89
- if (postBracket && postBracket.length > 1) {
92
+ }
93
+ if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression"].includes(node.parent.type)) {
94
+ const leftToken = sourceCode.getTokenBefore(node);
95
+ const hasSpacingBeforeNode = sourceCode.isSpaceBetween(leftToken, node);
96
+ const lastParam = params[params.length - 1];
97
+ const endBracket = sourceCode.getTokenAfter(lastParam);
98
+ const rightToken = sourceCode.getTokenAfter(endBracket, util.isOpeningParenToken);
99
+ const hasSpacingAfterParam = sourceCode.isSpaceBetween(endBracket, rightToken);
100
+ if (hasSpacingBeforeNode && node.parent.type !== AST_NODE_TYPES.TSFunctionType) {
90
101
  context.report({
91
102
  node,
103
+ loc: {
104
+ start: {
105
+ line: leftToken.loc.end.line,
106
+ column: leftToken.loc.end.column
107
+ },
108
+ end: {
109
+ line: node.loc.start.line,
110
+ column: node.loc.start.column
111
+ }
112
+ },
92
113
  messageId: "genericSpacingMismatch",
93
114
  *fix(fixer) {
94
- yield fixer.removeRange([node.range[1], node.range[1] + postBracket.length - 1]);
115
+ yield fixer.removeRange([leftToken.range[1], node.range[0]]);
95
116
  }
96
117
  });
97
118
  }
98
- }
99
- for (let i = 1; i < params.length; i++) {
100
- const prev = params[i - 1];
101
- const current = params[i];
102
- const from = prev.range[1];
103
- const to = current.range[0];
104
- const span = sourceCode.text.slice(from, to);
105
- if (span !== ", " && !span.match(/,\n/)) {
119
+ if (hasSpacingAfterParam && [AST_NODE_TYPES.TSFunctionType, AST_NODE_TYPES.FunctionDeclaration, AST_NODE_TYPES.FunctionExpression].includes(node.parent.type)) {
106
120
  context.report({
107
- *fix(fixer) {
108
- yield fixer.replaceTextRange([from, to], ", ");
109
- },
121
+ node,
110
122
  loc: {
111
- start: prev.loc.end,
112
- end: current.loc.start
123
+ start: {
124
+ line: endBracket.loc.end.line,
125
+ column: endBracket.loc.end.column
126
+ },
127
+ end: {
128
+ line: rightToken.loc.start.line,
129
+ column: rightToken.loc.start.column
130
+ }
113
131
  },
114
132
  messageId: "genericSpacingMismatch",
115
- node
133
+ *fix(fixer) {
134
+ yield fixer.removeRange([endBracket.range[1], rightToken.range[0]]);
135
+ }
116
136
  });
117
137
  }
118
138
  }
@@ -173,46 +193,45 @@ const genericSpacing = createEslintRule({
173
193
  const params = node.params;
174
194
  for (let i = 0; i < params.length; i++) {
175
195
  const param = params[i];
176
- const pre = sourceCode.text.slice(0, param.range[0]);
177
- const preSpace = pre.match(/(\s+)$/)?.[0];
178
- const preComma = pre.match(/(,)\s+$/)?.[0];
179
- const post = sourceCode.text.slice(param.range[1]);
180
- const postSpace = post.match(/^(\s*)/)?.[0];
181
- if (preSpace && preSpace.length && !preComma && param.loc.start.line === node.loc.start.line) {
196
+ const leftToken = sourceCode.getTokenBefore(param);
197
+ const rightToken = sourceCode.getTokenAfter(param);
198
+ const hasSpacingBeforeParam = leftToken.value === "<" ? sourceCode.isSpaceBetween(leftToken, param) : false;
199
+ const hasSpacingAfterParam = rightToken.value === ">" ? sourceCode.isSpaceBetween(param, rightToken) : false;
200
+ if (hasSpacingBeforeParam && leftToken.loc.end.line === param.loc.start.line) {
182
201
  context.report({
183
202
  node,
184
203
  loc: {
185
204
  start: {
186
- line: param.loc.start.line,
187
- column: param.loc.start.column + 1 - preSpace.length
205
+ line: leftToken.loc.end.line,
206
+ column: leftToken.loc.end.column
188
207
  },
189
208
  end: {
190
209
  line: param.loc.start.line,
191
- column: param.loc.start.column - 1
210
+ column: param.loc.start.column
192
211
  }
193
212
  },
194
213
  messageId: "genericSpacingMismatch",
195
214
  *fix(fixer) {
196
- yield fixer.replaceTextRange([param.range[0] - preSpace.length, param.range[0]], "");
215
+ yield fixer.removeRange([leftToken.range[1], param.range[0]]);
197
216
  }
198
217
  });
199
218
  }
200
- if (postSpace && postSpace.length && param.loc.end.line === node.loc.end.line) {
219
+ if (hasSpacingAfterParam && param.loc.end.line === rightToken.loc.start.line) {
201
220
  context.report({
221
+ node,
202
222
  loc: {
203
223
  start: {
204
224
  line: param.loc.end.line,
205
225
  column: param.loc.end.column
206
226
  },
207
227
  end: {
208
- line: param.loc.end.line,
209
- column: param.loc.end.column + postSpace.length
228
+ line: rightToken.loc.start.line,
229
+ column: rightToken.loc.start.column
210
230
  }
211
231
  },
212
- node,
213
232
  messageId: "genericSpacingMismatch",
214
233
  *fix(fixer) {
215
- yield fixer.replaceTextRange([param.range[1], param.range[1] + postSpace.length], "");
234
+ yield fixer.removeRange([param.range[1], rightToken.range[0]]);
216
235
  }
217
236
  });
218
237
  }
@@ -254,9 +273,9 @@ const genericSpacing = createEslintRule({
254
273
  }
255
274
  });
256
275
 
257
- const RULE_NAME$6 = "import-dedupe";
276
+ const RULE_NAME$8 = "import-dedupe";
258
277
  const importDedupe = createEslintRule({
259
- name: RULE_NAME$6,
278
+ name: RULE_NAME$8,
260
279
  meta: {
261
280
  type: "problem",
262
281
  docs: {
@@ -305,9 +324,9 @@ const importDedupe = createEslintRule({
305
324
  });
306
325
 
307
326
  const operatorOrAnyBracketOrKeywordRE = /^(\||&|\*|\+|\-|\/|%|<|>|<=|>=|==|!=|===|!==|\[|\(|\{|as|extends|implements|keyof|new|readonly|typeof|unique|unknown)/;
308
- const RULE_NAME$5 = "space-between-generic-and-paren";
327
+ const RULE_NAME$7 = "space-between-generic-and-paren";
309
328
  const spaceBetweenGenericAndParen = createEslintRule({
310
- name: RULE_NAME$5,
329
+ name: RULE_NAME$7,
311
330
  meta: {
312
331
  type: "layout",
313
332
  docs: {
@@ -333,7 +352,7 @@ const spaceBetweenGenericAndParen = createEslintRule({
333
352
  const postComma = text.slice(node.range[1]).match(/^(,)/)?.[0];
334
353
  const postQuestionMark = text.slice(spaceStartRange + postSpace.length).match(/^(\?)/)?.[0];
335
354
  const postOperatorOrAnyBracketOrKeyword = text.slice(spaceStartRange + postSpace.length).match(operatorOrAnyBracketOrKeywordRE)?.[0];
336
- if (postSpace && postSpace.length && !postEqual && !postComma && !postQuestionMark && !postOperatorOrAnyBracketOrKeyword && node.parent.type !== "TSInferType") {
355
+ if (postSpace && postSpace.length && !postEqual && !postComma && !postQuestionMark && !postOperatorOrAnyBracketOrKeyword && node.parent.type !== AST_NODE_TYPES.TSInferType) {
337
356
  context.report({
338
357
  loc: {
339
358
  start: {
@@ -352,7 +371,7 @@ const spaceBetweenGenericAndParen = createEslintRule({
352
371
  }
353
372
  });
354
373
  }
355
- if (node.parent?.parent.type === "FunctionDeclaration") {
374
+ if (node.parent?.parent.type === AST_NODE_TYPES.FunctionDeclaration) {
356
375
  const spaceEndRange = node.range[0] - 1;
357
376
  const pre = sourceCode.text.slice(0, spaceEndRange);
358
377
  const preSpace = pre.match(/(\s+)$/)?.[0];
@@ -381,19 +400,19 @@ const spaceBetweenGenericAndParen = createEslintRule({
381
400
  }
382
401
  });
383
402
 
384
- const RULE_NAME$4 = "no-spaces-before-paren";
385
- const noSpacesBeforeParen = createEslintRule({
386
- name: RULE_NAME$4,
403
+ const RULE_NAME$6 = "no-space-before-paren";
404
+ const noSpaceBeforeParen = createEslintRule({
405
+ name: RULE_NAME$6,
387
406
  meta: {
388
407
  type: "layout",
389
408
  docs: {
390
- description: "Spaces before paren",
409
+ description: "Space before paren",
391
410
  recommended: "error"
392
411
  },
393
412
  fixable: "whitespace",
394
413
  schema: [],
395
414
  messages: {
396
- noSpacesBeforeParen: "Expected no space before paren"
415
+ noSpaceBeforeParen: "Expected no space before paren"
397
416
  }
398
417
  },
399
418
  defaultOptions: [],
@@ -410,7 +429,7 @@ const noSpacesBeforeParen = createEslintRule({
410
429
  if (textBetweenImportAndParen.length > 0) {
411
430
  context.report({
412
431
  node,
413
- messageId: "noSpacesBeforeParen",
432
+ messageId: "noSpaceBeforeParen",
414
433
  *fix(fixer) {
415
434
  yield fixer.removeRange(textBetweenImportAndParenRange);
416
435
  }
@@ -419,7 +438,7 @@ const noSpacesBeforeParen = createEslintRule({
419
438
  },
420
439
  CallExpression(node) {
421
440
  let caller = "property" in node.callee ? node.callee.property : node.callee;
422
- if (caller.type === "TSInstantiationExpression" && "property" in caller.expression) {
441
+ if (caller.type === AST_NODE_TYPES.TSInstantiationExpression && "property" in caller.expression) {
423
442
  caller = caller.expression.property;
424
443
  }
425
444
  const callerEnd = ref(caller.range[1]);
@@ -439,7 +458,7 @@ const noSpacesBeforeParen = createEslintRule({
439
458
  if (textBetweenFunctionNameAndParen.value.length > 0 && textBetweenFunctionNameAndParen.value !== "?.") {
440
459
  context.report({
441
460
  node,
442
- messageId: "noSpacesBeforeParen",
461
+ messageId: "noSpaceBeforeParen",
443
462
  *fix(fixer) {
444
463
  yield fixer.replaceTextRange(textBetweenFunctionNameAndParenRange.value, node.optional ? "?." : "");
445
464
  }
@@ -452,7 +471,7 @@ const noSpacesBeforeParen = createEslintRule({
452
471
  if (preSpaces.length > 0) {
453
472
  context.report({
454
473
  node,
455
- messageId: "noSpacesBeforeParen",
474
+ messageId: "noSpaceBeforeParen",
456
475
  *fix(fixer) {
457
476
  yield fixer.removeRange([callerEnd.value, callerEnd.value + preSpaces.length]);
458
477
  }
@@ -461,7 +480,7 @@ const noSpacesBeforeParen = createEslintRule({
461
480
  if (postSpaces.length > 0) {
462
481
  context.report({
463
482
  node,
464
- messageId: "noSpacesBeforeParen",
483
+ messageId: "noSpaceBeforeParen",
465
484
  *fix(fixer) {
466
485
  yield fixer.removeRange([parenStart.value - postSpaces.length, parenStart.value]);
467
486
  }
@@ -470,7 +489,7 @@ const noSpacesBeforeParen = createEslintRule({
470
489
  if (spacesBeforeOptionalMark.length > 0 && !textBetweenFunctionNameAndParen.value.endsWith(" ")) {
471
490
  context.report({
472
491
  node,
473
- messageId: "noSpacesBeforeParen",
492
+ messageId: "noSpaceBeforeParen",
474
493
  *fix(fixer) {
475
494
  yield fixer.removeRange([parenStart.value - spacesBeforeOptionalMark.length - 2, parenStart.value - 2]);
476
495
  }
@@ -482,9 +501,9 @@ const noSpacesBeforeParen = createEslintRule({
482
501
  }
483
502
  });
484
503
 
485
- const RULE_NAME$3 = "space-in-empty-block";
504
+ const RULE_NAME$5 = "space-in-empty-block";
486
505
  const spaceInEmptyBlock = createEslintRule({
487
- name: RULE_NAME$3,
506
+ name: RULE_NAME$5,
488
507
  meta: {
489
508
  type: "layout",
490
509
  docs: {
@@ -549,9 +568,9 @@ const spaceInEmptyBlock = createEslintRule({
549
568
  }
550
569
  });
551
570
 
552
- const RULE_NAME$2 = "space-before-function-paren";
571
+ const RULE_NAME$4 = "space-before-function-paren";
553
572
  const spaceBeforeFunctionParen = createEslintRule({
554
- name: RULE_NAME$2,
573
+ name: RULE_NAME$4,
555
574
  meta: {
556
575
  type: "layout",
557
576
  docs: {
@@ -626,7 +645,7 @@ const spaceBeforeFunctionParen = createEslintRule({
626
645
  rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken);
627
646
  leftToken = sourceCode.getTokenBefore(rightToken);
628
647
  }
629
- const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken);
648
+ const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
630
649
  if (hasSpacing && functionConfig === "never") {
631
650
  context.report({
632
651
  node,
@@ -656,13 +675,13 @@ const spaceBeforeFunctionParen = createEslintRule({
656
675
  }
657
676
  });
658
677
 
659
- const RULE_NAME$1 = "semi-spacing";
678
+ const RULE_NAME$3 = "semi-spacing";
660
679
  const semiSpacing = createEslintRule({
661
- name: RULE_NAME$1,
680
+ name: RULE_NAME$3,
662
681
  meta: {
663
682
  type: "layout",
664
683
  docs: {
665
- description: "Semicolon spacing",
684
+ description: "Semicolon spacing in types",
666
685
  recommended: "error"
667
686
  },
668
687
  fixable: "whitespace",
@@ -674,29 +693,30 @@ const semiSpacing = createEslintRule({
674
693
  defaultOptions: [],
675
694
  create: (context) => {
676
695
  const sourceCode = context.getSourceCode();
677
- const text = sourceCode.text;
678
696
  return {
679
697
  TSTypeAliasDeclaration(node) {
680
- const sourceLine = text.slice(node.range[0], node.range[1]);
681
- const preSemiSpace = sourceLine.match(/(\s+);$/)?.[0];
682
- if (preSemiSpace) {
683
- const spaceStart = node.range[0] + sourceLine.length - preSemiSpace.length;
684
- const spaceEnd = node.range[0] + sourceLine.length - 1;
698
+ const leftToken = node.typeAnnotation;
699
+ const rightToken = sourceCode.getTokenAfter(node.typeAnnotation);
700
+ if (rightToken.type !== AST_TOKEN_TYPES.Punctuator || rightToken.value !== ";") {
701
+ return;
702
+ }
703
+ const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
704
+ if (hasSpacing) {
685
705
  context.report({
686
706
  loc: {
687
707
  start: {
688
- line: node.loc.start.line,
689
- column: node.loc.start.column + sourceLine.length - preSemiSpace.length
708
+ line: leftToken.loc.end.line,
709
+ column: leftToken.loc.end.column
690
710
  },
691
711
  end: {
692
- line: node.loc.start.line,
693
- column: node.loc.start.column + sourceLine.length - 1
712
+ line: rightToken.loc.start.line,
713
+ column: rightToken.loc.start.column
694
714
  }
695
715
  },
696
716
  node,
697
717
  messageId: "noSpaceBeforeSemi",
698
718
  *fix(fixer) {
699
- yield fixer.removeRange([spaceStart, spaceEnd]);
719
+ yield fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
700
720
  }
701
721
  });
702
722
  }
@@ -705,9 +725,9 @@ const semiSpacing = createEslintRule({
705
725
  }
706
726
  });
707
727
 
708
- const RULE_NAME = "no-inline-type-import";
728
+ const RULE_NAME$2 = "no-inline-type-import";
709
729
  const noInlineTypeImport = createEslintRule({
710
- name: RULE_NAME,
730
+ name: RULE_NAME$2,
711
731
  meta: {
712
732
  type: "layout",
713
733
  docs: {
@@ -754,6 +774,120 @@ import { ${valueSpecifiersText} } from "${node.source.value}";`);
754
774
  }
755
775
  });
756
776
 
777
+ const RULE_NAME$1 = "no-beginning-newline";
778
+ const noBeginningNewline = createEslintRule({
779
+ name: RULE_NAME$1,
780
+ meta: {
781
+ type: "layout",
782
+ docs: {
783
+ description: "No beginning newline",
784
+ recommended: "error"
785
+ },
786
+ fixable: "whitespace",
787
+ schema: [],
788
+ messages: {
789
+ noBeginningNewline: "No beginning newline"
790
+ }
791
+ },
792
+ defaultOptions: [],
793
+ create: (context) => {
794
+ const text = context.getSourceCode().text;
795
+ return {
796
+ Program: (node) => {
797
+ const newlines = text.match(/([\n]*)/)[1];
798
+ if (newlines.length > 0) {
799
+ context.report({
800
+ node,
801
+ loc: {
802
+ start: {
803
+ line: 0,
804
+ column: 0
805
+ },
806
+ end: node.loc.start
807
+ },
808
+ messageId: "noBeginningNewline",
809
+ *fix(fixer) {
810
+ yield fixer.removeRange([0, node.range[0]]);
811
+ }
812
+ });
813
+ }
814
+ }
815
+ };
816
+ }
817
+ });
818
+
819
+ const RULE_NAME = "array-bracket-spacing";
820
+ const arrayBracketSpacing = createEslintRule({
821
+ name: RULE_NAME,
822
+ meta: {
823
+ type: "layout",
824
+ docs: {
825
+ description: "Array bracket spacing",
826
+ recommended: "error"
827
+ },
828
+ fixable: "whitespace",
829
+ schema: [],
830
+ messages: {
831
+ arrayBracketSpacing: "Array bracket spacing mismatch"
832
+ }
833
+ },
834
+ defaultOptions: [],
835
+ create: (context) => {
836
+ const sourceCode = context.getSourceCode();
837
+ const text = sourceCode.getText();
838
+ const checkNode = (node) => {
839
+ const elements = node.type === AST_NODE_TYPES.TSTupleType ? node.elementTypes : node.elements;
840
+ const firstElement = elements[0];
841
+ const lastElement = elements[elements.length - 1];
842
+ if (!firstElement) {
843
+ return;
844
+ }
845
+ const leftToken = sourceCode.getTokenBefore(firstElement);
846
+ const rightToken = ref(sourceCode.getTokenAfter(lastElement));
847
+ if (rightToken.value.value === ",") {
848
+ rightToken.value = sourceCode.getTokenAfter(rightToken.value);
849
+ }
850
+ const textBetweenFirstAndToken = computed(() => text.slice(leftToken.range[1], firstElement.range[0]));
851
+ const isNewline = computed(() => textBetweenFirstAndToken.value.includes("\n"));
852
+ const textBetweenLastAndToken = computed(() => text.slice(lastElement.range[1], rightToken.value.range[0]));
853
+ const hasNewlineAfter = computed(() => textBetweenLastAndToken.value.includes("\n"));
854
+ if (sourceCode.isSpaceBetween(leftToken, firstElement) && !isNewline.value) {
855
+ context.report({
856
+ node,
857
+ messageId: "arrayBracketSpacing",
858
+ *fix(fixer) {
859
+ yield fixer.removeRange([leftToken.range[1], firstElement.range[0]]);
860
+ }
861
+ });
862
+ }
863
+ if (sourceCode.isSpaceBetween(lastElement, rightToken.value)) {
864
+ if (!isNewline.value) {
865
+ context.report({
866
+ node,
867
+ messageId: "arrayBracketSpacing",
868
+ *fix(fixer) {
869
+ yield fixer.removeRange([lastElement.range[1], rightToken.value.range[0]]);
870
+ }
871
+ });
872
+ }
873
+ }
874
+ if (isNewline.value && !hasNewlineAfter.value) {
875
+ context.report({
876
+ node,
877
+ messageId: "arrayBracketSpacing",
878
+ *fix(fixer) {
879
+ yield fixer.replaceTextRange([lastElement.range[1], rightToken.value.range[0]], "\n");
880
+ }
881
+ });
882
+ }
883
+ };
884
+ return {
885
+ TSTupleType: checkNode,
886
+ ArrayExpression: checkNode
887
+ };
888
+ }
889
+ });
890
+
757
891
  const index = {
758
892
  rules: {
759
893
  "import-dedupe": importDedupe,
@@ -762,8 +896,10 @@ const index = {
762
896
  "space-in-empty-block": spaceInEmptyBlock,
763
897
  "semi-spacing": semiSpacing,
764
898
  "no-inline-type-import": noInlineTypeImport,
765
- "no-spaces-before-paren": noSpacesBeforeParen,
766
- "space-before-function-paren": spaceBeforeFunctionParen
899
+ "no-space-before-paren": noSpaceBeforeParen,
900
+ "space-before-function-paren": spaceBeforeFunctionParen,
901
+ "no-beginning-newline": noBeginningNewline,
902
+ "array-bracket-spacing": arrayBracketSpacing
767
903
  }
768
904
  };
769
905
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@so1ve/eslint-plugin",
3
- "version": "0.44.0",
3
+ "version": "0.45.1",
4
4
  "author": "Anthony Fu <anthonyfu117@hotmail.com> (https://github.com/antfu/)",
5
5
  "contributors": [
6
6
  {
7
- "name": "Ray <nn_201312@163.com> (https://github.com/so1ve/)"
7
+ "name": "Ray <i@mk1.io> (https://github.com/so1ve/)"
8
8
  }
9
9
  ],
10
10
  "keywords": [
@@ -37,6 +37,7 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^18.11.18",
40
+ "@typescript-eslint/types": "^5.50.0",
40
41
  "unbuild": "^1.1.1",
41
42
  "vitest": "^0.28.3"
42
43
  },