eslint-plugin-perfectionist 2.7.0 → 2.9.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.
Files changed (84) hide show
  1. package/dist/configs/recommended-alphabetical.js +9 -1
  2. package/dist/configs/recommended-alphabetical.mjs +5 -10
  3. package/dist/configs/recommended-line-length.js +9 -1
  4. package/dist/configs/recommended-line-length.mjs +5 -10
  5. package/dist/configs/recommended-natural.js +9 -1
  6. package/dist/configs/recommended-natural.mjs +5 -10
  7. package/dist/index.js +135 -3
  8. package/dist/index.mjs +76 -2197
  9. package/dist/package.json.js +4 -0
  10. package/dist/package.json.mjs +4 -0
  11. package/dist/rules/sort-array-includes.js +129 -0
  12. package/dist/rules/sort-array-includes.mjs +129 -0
  13. package/dist/rules/sort-astro-attributes.js +161 -0
  14. package/dist/rules/sort-astro-attributes.mjs +161 -0
  15. package/dist/rules/sort-classes.js +213 -0
  16. package/dist/rules/sort-classes.mjs +213 -0
  17. package/dist/rules/sort-enums.js +117 -0
  18. package/dist/rules/sort-enums.mjs +117 -0
  19. package/dist/rules/sort-exports.js +104 -0
  20. package/dist/rules/sort-exports.mjs +104 -0
  21. package/dist/rules/sort-imports.js +439 -0
  22. package/dist/rules/sort-imports.mjs +439 -0
  23. package/dist/rules/sort-interfaces.js +253 -0
  24. package/dist/rules/sort-interfaces.mjs +253 -0
  25. package/dist/rules/sort-intersection-types.js +92 -0
  26. package/dist/rules/sort-intersection-types.mjs +92 -0
  27. package/dist/rules/sort-jsx-props.js +156 -0
  28. package/dist/rules/sort-jsx-props.mjs +156 -0
  29. package/dist/rules/sort-maps.js +125 -0
  30. package/dist/rules/sort-maps.mjs +125 -0
  31. package/dist/rules/sort-named-exports.js +105 -0
  32. package/dist/rules/sort-named-exports.mjs +105 -0
  33. package/dist/rules/sort-named-imports.js +123 -0
  34. package/dist/rules/sort-named-imports.mjs +123 -0
  35. package/dist/rules/sort-object-types.js +189 -0
  36. package/dist/rules/sort-object-types.mjs +189 -0
  37. package/dist/rules/sort-objects.js +265 -0
  38. package/dist/rules/sort-objects.mjs +265 -0
  39. package/dist/rules/sort-svelte-attributes.js +168 -0
  40. package/dist/rules/sort-svelte-attributes.mjs +168 -0
  41. package/dist/rules/sort-union-types.js +120 -0
  42. package/dist/rules/sort-union-types.mjs +120 -0
  43. package/dist/rules/sort-vue-attributes.js +165 -0
  44. package/dist/rules/sort-vue-attributes.mjs +165 -0
  45. package/dist/typings/index.js +29 -0
  46. package/dist/typings/index.mjs +29 -0
  47. package/dist/utils/compare.js +38 -0
  48. package/dist/utils/compare.mjs +38 -0
  49. package/dist/utils/complete.js +4 -0
  50. package/dist/utils/complete.mjs +4 -0
  51. package/dist/utils/create-eslint-rule.js +7 -0
  52. package/dist/utils/create-eslint-rule.mjs +7 -0
  53. package/dist/utils/get-comment-after.js +13 -0
  54. package/dist/utils/get-comment-after.mjs +13 -0
  55. package/dist/utils/get-comment-before.js +14 -0
  56. package/dist/utils/get-comment-before.mjs +14 -0
  57. package/dist/utils/get-group-number.js +12 -0
  58. package/dist/utils/get-group-number.mjs +12 -0
  59. package/dist/utils/get-lines-between.js +10 -0
  60. package/dist/utils/get-lines-between.mjs +10 -0
  61. package/dist/utils/get-node-parent.js +14 -0
  62. package/dist/utils/get-node-parent.mjs +14 -0
  63. package/dist/utils/get-node-range.js +41 -0
  64. package/dist/utils/get-node-range.mjs +41 -0
  65. package/dist/utils/is-member-optional.js +12 -0
  66. package/dist/utils/is-member-optional.mjs +12 -0
  67. package/dist/utils/is-partition-comment.js +11 -0
  68. package/dist/utils/is-partition-comment.mjs +11 -0
  69. package/dist/utils/is-positive.js +4 -0
  70. package/dist/utils/is-positive.mjs +4 -0
  71. package/dist/utils/make-fixes.js +38 -0
  72. package/dist/utils/make-fixes.mjs +38 -0
  73. package/dist/utils/pairwise.js +14 -0
  74. package/dist/utils/pairwise.mjs +14 -0
  75. package/dist/utils/range-to-diff.js +7 -0
  76. package/dist/utils/range-to-diff.mjs +7 -0
  77. package/dist/utils/sort-nodes.js +5 -0
  78. package/dist/utils/sort-nodes.mjs +5 -0
  79. package/dist/utils/to-single-line.js +4 -0
  80. package/dist/utils/to-single-line.mjs +4 -0
  81. package/dist/utils/use-groups.js +35 -0
  82. package/dist/utils/use-groups.mjs +35 -0
  83. package/package.json +1 -1
  84. package/readme.md +20 -19
@@ -0,0 +1,439 @@
1
+ import { builtinModules } from "node:module";
2
+ import { minimatch } from "minimatch";
3
+ import { getCommentBefore } from "../utils/get-comment-before.mjs";
4
+ import { createEslintRule } from "../utils/create-eslint-rule.mjs";
5
+ import { getLinesBetween } from "../utils/get-lines-between.mjs";
6
+ import { getGroupNumber } from "../utils/get-group-number.mjs";
7
+ import { getNodeRange } from "../utils/get-node-range.mjs";
8
+ import { rangeToDiff } from "../utils/range-to-diff.mjs";
9
+ import { isPositive } from "../utils/is-positive.mjs";
10
+ import { SortType, SortOrder } from "../typings/index.mjs";
11
+ import { useGroups } from "../utils/use-groups.mjs";
12
+ import { sortNodes } from "../utils/sort-nodes.mjs";
13
+ import { complete } from "../utils/complete.mjs";
14
+ import { pairwise } from "../utils/pairwise.mjs";
15
+ import { compare } from "../utils/compare.mjs";
16
+ const RULE_NAME = "sort-imports";
17
+ const sortImports = createEslintRule({
18
+ name: RULE_NAME,
19
+ meta: {
20
+ type: "suggestion",
21
+ docs: {
22
+ description: "enforce sorted imports"
23
+ },
24
+ fixable: "code",
25
+ schema: [
26
+ {
27
+ id: "sort-imports",
28
+ type: "object",
29
+ properties: {
30
+ "custom-groups": {
31
+ type: "object",
32
+ properties: {
33
+ type: {
34
+ type: "object"
35
+ },
36
+ value: {
37
+ type: "object"
38
+ }
39
+ },
40
+ additionalProperties: false
41
+ },
42
+ type: {
43
+ enum: [
44
+ SortType.alphabetical,
45
+ SortType.natural,
46
+ SortType["line-length"]
47
+ ],
48
+ default: SortType.alphabetical,
49
+ type: "string"
50
+ },
51
+ order: {
52
+ enum: [SortOrder.asc, SortOrder.desc],
53
+ default: SortOrder.asc,
54
+ type: "string"
55
+ },
56
+ "ignore-case": {
57
+ type: "boolean",
58
+ default: false
59
+ },
60
+ groups: {
61
+ type: "array",
62
+ default: []
63
+ },
64
+ "internal-pattern": {
65
+ items: {
66
+ type: "string"
67
+ },
68
+ type: "array"
69
+ },
70
+ "newlines-between": {
71
+ enum: [
72
+ "ignore",
73
+ "always",
74
+ "never"
75
+ /* never */
76
+ ],
77
+ default: "always",
78
+ type: "string"
79
+ },
80
+ "max-line-length": {
81
+ type: "integer",
82
+ minimum: 0,
83
+ exclusiveMinimum: true
84
+ }
85
+ },
86
+ allOf: [
87
+ { $ref: "#/definitions/max-line-length-requires-line-length-type" }
88
+ ],
89
+ additionalProperties: false,
90
+ dependencies: {
91
+ "max-line-length": ["type"]
92
+ },
93
+ definitions: {
94
+ "is-line-length": {
95
+ properties: {
96
+ type: { enum: [SortType["line-length"]], type: "string" }
97
+ },
98
+ required: ["type"],
99
+ type: "object"
100
+ },
101
+ "max-line-length-requires-line-length-type": {
102
+ anyOf: [
103
+ {
104
+ not: { required: ["max-line-length"], type: "object" },
105
+ type: "object"
106
+ },
107
+ { $ref: "#/definitions/is-line-length" }
108
+ ]
109
+ }
110
+ }
111
+ }
112
+ ],
113
+ messages: {
114
+ unexpectedImportsOrder: 'Expected "{{right}}" to come before "{{left}}"',
115
+ missedSpacingBetweenImports: 'Missed spacing between "{{left}}" and "{{right}}" imports',
116
+ extraSpacingBetweenImports: 'Extra spacing between "{{left}}" and "{{right}}" imports'
117
+ }
118
+ },
119
+ defaultOptions: [
120
+ {
121
+ type: SortType.alphabetical,
122
+ order: SortOrder.asc
123
+ }
124
+ ],
125
+ create: (context) => {
126
+ let options = complete(context.options.at(0), {
127
+ "newlines-between": "always",
128
+ "custom-groups": { type: {}, value: {} },
129
+ "internal-pattern": ["~/**"],
130
+ type: SortType.alphabetical,
131
+ order: SortOrder.asc,
132
+ "ignore-case": false,
133
+ groups: []
134
+ });
135
+ let hasUnknownGroup = false;
136
+ for (let group of options.groups) {
137
+ if (Array.isArray(group)) {
138
+ for (let subGroup of group) {
139
+ if (subGroup === "unknown") {
140
+ hasUnknownGroup = true;
141
+ }
142
+ }
143
+ } else {
144
+ if (group === "unknown") {
145
+ hasUnknownGroup = true;
146
+ }
147
+ }
148
+ }
149
+ if (!hasUnknownGroup) {
150
+ options.groups = [...options.groups, "unknown"];
151
+ }
152
+ let nodes = [];
153
+ let isSideEffectImport = (node) => node.type === "ImportDeclaration" && node.specifiers.length === 0;
154
+ let computeGroup = (node) => {
155
+ let isStyle = (value) => [".less", ".scss", ".sass", ".styl", ".pcss", ".css", ".sss"].some(
156
+ (extension) => value.endsWith(extension)
157
+ );
158
+ let isIndex = (value) => [
159
+ "./index.d.js",
160
+ "./index.d.ts",
161
+ "./index.js",
162
+ "./index.ts",
163
+ "./index",
164
+ "./",
165
+ "."
166
+ ].includes(value);
167
+ let isParent = (value) => value.indexOf("..") === 0;
168
+ let isSibling = (value) => value.indexOf("./") === 0;
169
+ let { getGroup, defineGroup, setCustomGroups } = useGroups(options.groups);
170
+ let isInternal = (nodeElement) => options["internal-pattern"].length && options["internal-pattern"].some(
171
+ (pattern) => minimatch(nodeElement.source.value, pattern, {
172
+ nocomment: true
173
+ })
174
+ );
175
+ let isCoreModule = (value) => {
176
+ let bunModules = [
177
+ "bun",
178
+ "bun:ffi",
179
+ "bun:jsc",
180
+ "bun:sqlite",
181
+ "bun:test",
182
+ "bun:wrap",
183
+ "detect-libc",
184
+ "undici",
185
+ "ws"
186
+ ];
187
+ return builtinModules.includes(
188
+ value.startsWith("node:") ? value.split("node:")[1] : value
189
+ ) || bunModules.includes(value);
190
+ };
191
+ let isExternal = (value) => !(value.startsWith(".") || value.startsWith("/"));
192
+ if (node.importKind === "type") {
193
+ if (node.type === "ImportDeclaration") {
194
+ setCustomGroups(options["custom-groups"].type, node.source.value);
195
+ if (isIndex(node.source.value)) {
196
+ defineGroup("index-type");
197
+ }
198
+ if (isSibling(node.source.value)) {
199
+ defineGroup("sibling-type");
200
+ }
201
+ if (isParent(node.source.value)) {
202
+ defineGroup("parent-type");
203
+ }
204
+ if (isInternal(node)) {
205
+ defineGroup("internal-type");
206
+ }
207
+ if (isCoreModule(node.source.value)) {
208
+ defineGroup("builtin-type");
209
+ }
210
+ if (isExternal(node.source.value)) {
211
+ defineGroup("external-type");
212
+ }
213
+ }
214
+ defineGroup("type");
215
+ }
216
+ if (node.type === "ImportDeclaration") {
217
+ setCustomGroups(options["custom-groups"].value, node.source.value);
218
+ if (isSideEffectImport(node) && isStyle(node.source.value)) {
219
+ defineGroup("side-effect-style");
220
+ }
221
+ if (isSideEffectImport(node)) {
222
+ defineGroup("side-effect");
223
+ }
224
+ if (isStyle(node.source.value)) {
225
+ defineGroup("style");
226
+ }
227
+ if (isIndex(node.source.value)) {
228
+ defineGroup("index");
229
+ }
230
+ if (isSibling(node.source.value)) {
231
+ defineGroup("sibling");
232
+ }
233
+ if (isParent(node.source.value)) {
234
+ defineGroup("parent");
235
+ }
236
+ if (isInternal(node)) {
237
+ defineGroup("internal");
238
+ }
239
+ if (isCoreModule(node.source.value)) {
240
+ defineGroup("builtin");
241
+ }
242
+ if (isExternal(node.source.value)) {
243
+ defineGroup("external");
244
+ }
245
+ }
246
+ return getGroup();
247
+ };
248
+ let hasMultipleImportDeclarations = (node) => node.specifiers.length > 1;
249
+ let registerNode = (node) => {
250
+ let name;
251
+ if (node.type === "ImportDeclaration") {
252
+ name = node.source.value;
253
+ } else {
254
+ if (node.moduleReference.type === "TSExternalModuleReference" && node.moduleReference.expression.type === "Literal") {
255
+ name = `${node.moduleReference.expression.value}`;
256
+ } else {
257
+ name = context.sourceCode.text.slice(...node.moduleReference.range);
258
+ }
259
+ }
260
+ nodes.push({
261
+ size: rangeToDiff(node.range),
262
+ group: computeGroup(node),
263
+ name,
264
+ node,
265
+ ...options.type === SortType["line-length"] && options["max-line-length"] && {
266
+ hasMultipleImportDeclarations: hasMultipleImportDeclarations(
267
+ node
268
+ )
269
+ }
270
+ });
271
+ };
272
+ return {
273
+ TSImportEqualsDeclaration: registerNode,
274
+ ImportDeclaration: registerNode,
275
+ "Program:exit": () => {
276
+ var _a;
277
+ let hasContentBetweenNodes = (left, right) => !!context.sourceCode.getTokensBetween(
278
+ left.node,
279
+ getCommentBefore(right.node, context.sourceCode) || right.node,
280
+ {
281
+ includeComments: true
282
+ }
283
+ ).length;
284
+ let fix = (fixer, nodesToFix) => {
285
+ let fixes = [];
286
+ let grouped = {};
287
+ for (let node of nodesToFix) {
288
+ let groupNum = getGroupNumber(options.groups, node);
289
+ if (!(groupNum in grouped)) {
290
+ grouped[groupNum] = [node];
291
+ } else {
292
+ grouped[groupNum] = sortNodes(
293
+ [...grouped[groupNum], node],
294
+ options
295
+ );
296
+ }
297
+ }
298
+ let formatted = Object.keys(grouped).sort((a, b) => Number(a) - Number(b)).reduce(
299
+ (accumulator, group) => [
300
+ ...accumulator,
301
+ ...grouped[group]
302
+ ],
303
+ []
304
+ );
305
+ for (let i = 0, max = formatted.length; i < max; i++) {
306
+ let node = formatted.at(i);
307
+ fixes.push(
308
+ fixer.replaceTextRange(
309
+ getNodeRange(nodesToFix.at(i).node, context.sourceCode),
310
+ context.sourceCode.text.slice(
311
+ ...getNodeRange(node.node, context.sourceCode)
312
+ )
313
+ )
314
+ );
315
+ if (options["newlines-between"] !== "ignore") {
316
+ let nextNode = formatted.at(i + 1);
317
+ if (nextNode) {
318
+ let linesBetweenImports = getLinesBetween(
319
+ context.sourceCode,
320
+ nodesToFix.at(i),
321
+ nodesToFix.at(i + 1)
322
+ );
323
+ if (options["newlines-between"] === "always" && getGroupNumber(options.groups, node) === getGroupNumber(options.groups, nextNode) && linesBetweenImports !== 0 || options["newlines-between"] === "never" && linesBetweenImports > 0) {
324
+ fixes.push(
325
+ fixer.removeRange([
326
+ getNodeRange(
327
+ nodesToFix.at(i).node,
328
+ context.sourceCode
329
+ ).at(1),
330
+ getNodeRange(
331
+ nodesToFix.at(i + 1).node,
332
+ context.sourceCode
333
+ ).at(0) - 1
334
+ ])
335
+ );
336
+ }
337
+ if (options["newlines-between"] === "always" && getGroupNumber(options.groups, node) !== getGroupNumber(options.groups, nextNode) && linesBetweenImports > 1) {
338
+ fixes.push(
339
+ fixer.replaceTextRange(
340
+ [
341
+ getNodeRange(
342
+ nodesToFix.at(i).node,
343
+ context.sourceCode
344
+ ).at(1),
345
+ getNodeRange(
346
+ nodesToFix.at(i + 1).node,
347
+ context.sourceCode
348
+ ).at(0) - 1
349
+ ],
350
+ "\n"
351
+ )
352
+ );
353
+ }
354
+ if (options["newlines-between"] === "always" && getGroupNumber(options.groups, node) !== getGroupNumber(options.groups, nextNode) && linesBetweenImports === 0) {
355
+ fixes.push(
356
+ fixer.insertTextAfterRange(
357
+ getNodeRange(nodesToFix.at(i).node, context.sourceCode),
358
+ "\n"
359
+ )
360
+ );
361
+ }
362
+ }
363
+ }
364
+ }
365
+ return fixes;
366
+ };
367
+ let splittedNodes = [[]];
368
+ for (let node of nodes) {
369
+ let lastNode = (_a = splittedNodes.at(-1)) == null ? void 0 : _a.at(-1);
370
+ if (lastNode && hasContentBetweenNodes(lastNode, node)) {
371
+ splittedNodes.push([node]);
372
+ } else {
373
+ splittedNodes.at(-1).push(node);
374
+ }
375
+ }
376
+ for (let nodeList of splittedNodes) {
377
+ pairwise(nodeList, (left, right) => {
378
+ let leftNum = getGroupNumber(options.groups, left);
379
+ let rightNum = getGroupNumber(options.groups, right);
380
+ let numberOfEmptyLinesBetween = getLinesBetween(
381
+ context.sourceCode,
382
+ left,
383
+ right
384
+ );
385
+ if (!(isSideEffectImport(left.node) && isSideEffectImport(right.node)) && !hasContentBetweenNodes(left, right) && (leftNum > rightNum || leftNum === rightNum && isPositive(compare(left, right, options)))) {
386
+ context.report({
387
+ messageId: "unexpectedImportsOrder",
388
+ data: {
389
+ left: left.name,
390
+ right: right.name
391
+ },
392
+ node: right.node,
393
+ fix: (fixer) => fix(fixer, nodeList)
394
+ });
395
+ }
396
+ if (options["newlines-between"] === "never" && numberOfEmptyLinesBetween > 0) {
397
+ context.report({
398
+ messageId: "extraSpacingBetweenImports",
399
+ data: {
400
+ left: left.name,
401
+ right: right.name
402
+ },
403
+ node: right.node,
404
+ fix: (fixer) => fix(fixer, nodeList)
405
+ });
406
+ }
407
+ if (options["newlines-between"] === "always") {
408
+ if (leftNum < rightNum && numberOfEmptyLinesBetween === 0) {
409
+ context.report({
410
+ messageId: "missedSpacingBetweenImports",
411
+ data: {
412
+ left: left.name,
413
+ right: right.name
414
+ },
415
+ node: right.node,
416
+ fix: (fixer) => fix(fixer, nodeList)
417
+ });
418
+ } else if (numberOfEmptyLinesBetween > 1 || leftNum === rightNum && numberOfEmptyLinesBetween > 0) {
419
+ context.report({
420
+ messageId: "extraSpacingBetweenImports",
421
+ data: {
422
+ left: left.name,
423
+ right: right.name
424
+ },
425
+ node: right.node,
426
+ fix: (fixer) => fix(fixer, nodeList)
427
+ });
428
+ }
429
+ }
430
+ });
431
+ }
432
+ }
433
+ };
434
+ }
435
+ });
436
+ export {
437
+ RULE_NAME,
438
+ sortImports as default
439
+ };
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const minimatch = require("minimatch");
4
+ const index = require("../typings/index.js");
5
+ const createEslintRule = require("../utils/create-eslint-rule.js");
6
+ const isMemberOptional = require("../utils/is-member-optional.js");
7
+ const getLinesBetween = require("../utils/get-lines-between.js");
8
+ const getGroupNumber = require("../utils/get-group-number.js");
9
+ const toSingleLine = require("../utils/to-single-line.js");
10
+ const rangeToDiff = require("../utils/range-to-diff.js");
11
+ const isPositive = require("../utils/is-positive.js");
12
+ const useGroups = require("../utils/use-groups.js");
13
+ const sortNodes = require("../utils/sort-nodes.js");
14
+ const makeFixes = require("../utils/make-fixes.js");
15
+ const complete = require("../utils/complete.js");
16
+ const pairwise = require("../utils/pairwise.js");
17
+ const compare = require("../utils/compare.js");
18
+ const RULE_NAME = "sort-interfaces";
19
+ const sortInterfaces = createEslintRule.createEslintRule({
20
+ name: RULE_NAME,
21
+ meta: {
22
+ type: "suggestion",
23
+ docs: {
24
+ description: "enforce sorted interface properties"
25
+ },
26
+ fixable: "code",
27
+ schema: [
28
+ {
29
+ type: "object",
30
+ properties: {
31
+ "custom-groups": {
32
+ type: "object"
33
+ },
34
+ "optionality-order": {
35
+ enum: [
36
+ index.OptionalityOrder.ignore,
37
+ index.OptionalityOrder["optional-first"],
38
+ index.OptionalityOrder["required-first"]
39
+ ],
40
+ default: index.OptionalityOrder.ignore,
41
+ type: "string"
42
+ },
43
+ type: {
44
+ enum: [
45
+ index.SortType.alphabetical,
46
+ index.SortType.natural,
47
+ index.SortType["line-length"]
48
+ ],
49
+ default: index.SortType.alphabetical,
50
+ type: "string"
51
+ },
52
+ order: {
53
+ enum: [index.SortOrder.asc, index.SortOrder.desc],
54
+ default: index.SortOrder.asc,
55
+ type: "string"
56
+ },
57
+ "ignore-case": {
58
+ type: "boolean",
59
+ default: false
60
+ },
61
+ "ignore-pattern": {
62
+ items: {
63
+ type: "string"
64
+ },
65
+ type: "array"
66
+ },
67
+ groups: {
68
+ type: "array",
69
+ default: []
70
+ },
71
+ "partition-by-new-line": {
72
+ type: "boolean",
73
+ default: false
74
+ }
75
+ },
76
+ additionalProperties: false
77
+ }
78
+ ],
79
+ messages: {
80
+ unexpectedInterfacePropertiesOrder: 'Expected "{{right}}" to come before "{{left}}"'
81
+ }
82
+ },
83
+ defaultOptions: [
84
+ {
85
+ type: index.SortType.alphabetical,
86
+ order: index.SortOrder.asc
87
+ }
88
+ ],
89
+ create: (context) => ({
90
+ TSInterfaceDeclaration: (node) => {
91
+ if (node.body.body.length > 1) {
92
+ let options = complete.complete(context.options.at(0), {
93
+ "optionality-order": index.OptionalityOrder.ignore,
94
+ "partition-by-new-line": false,
95
+ type: index.SortType.alphabetical,
96
+ "ignore-case": false,
97
+ order: index.SortOrder.asc,
98
+ "ignore-pattern": [],
99
+ "custom-groups": {},
100
+ groups: []
101
+ });
102
+ if (!options["ignore-pattern"].some(
103
+ (pattern) => minimatch.minimatch(node.id.name, pattern, {
104
+ nocomment: true
105
+ })
106
+ )) {
107
+ let formattedMembers = node.body.body.reduce(
108
+ (accumulator, element) => {
109
+ var _a, _b, _c, _d;
110
+ if (element.type === "TSCallSignatureDeclaration") {
111
+ accumulator.push([]);
112
+ return accumulator;
113
+ }
114
+ let lastElement = (_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1);
115
+ let name;
116
+ let { getGroup, defineGroup, setCustomGroups } = useGroups.useGroups(
117
+ options.groups
118
+ );
119
+ if (element.type === "TSPropertySignature") {
120
+ if (element.key.type === "Identifier") {
121
+ ({ name } = element.key);
122
+ } else if (element.key.type === "Literal") {
123
+ name = `${element.key.value}`;
124
+ } else {
125
+ let end = ((_b = element.typeAnnotation) == null ? void 0 : _b.range.at(0)) ?? element.range.at(1) - (element.optional ? "?".length : 0);
126
+ name = context.sourceCode.text.slice(element.range.at(0), end);
127
+ }
128
+ } else if (element.type === "TSIndexSignature") {
129
+ let endIndex = ((_c = element.typeAnnotation) == null ? void 0 : _c.range.at(0)) ?? element.range.at(1);
130
+ name = context.sourceCode.text.slice(
131
+ element.range.at(0),
132
+ endIndex
133
+ );
134
+ } else {
135
+ let endIndex = ((_d = element.returnType) == null ? void 0 : _d.range.at(0)) ?? element.range.at(1);
136
+ name = context.sourceCode.text.slice(
137
+ element.range.at(0),
138
+ endIndex
139
+ );
140
+ }
141
+ let elementSortingNode = {
142
+ size: rangeToDiff.rangeToDiff(element.range),
143
+ node: element,
144
+ name
145
+ };
146
+ if (options["partition-by-new-line"] && lastElement && getLinesBetween.getLinesBetween(
147
+ context.sourceCode,
148
+ lastElement,
149
+ elementSortingNode
150
+ )) {
151
+ accumulator.push([]);
152
+ }
153
+ setCustomGroups(options["custom-groups"], name);
154
+ if (element.loc.start.line !== element.loc.end.line) {
155
+ defineGroup("multiline");
156
+ }
157
+ accumulator.at(-1).push({
158
+ ...elementSortingNode,
159
+ group: getGroup()
160
+ });
161
+ return accumulator;
162
+ },
163
+ [[]]
164
+ );
165
+ let toSorted = (nodes) => {
166
+ let grouped = {};
167
+ for (let currentNode of nodes) {
168
+ let groupNum = getGroupNumber.getGroupNumber(options.groups, currentNode);
169
+ if (!(groupNum in grouped)) {
170
+ grouped[groupNum] = [currentNode];
171
+ } else {
172
+ grouped[groupNum] = sortNodes.sortNodes(
173
+ [...grouped[groupNum], currentNode],
174
+ options
175
+ );
176
+ }
177
+ }
178
+ let sortedNodes = [];
179
+ for (let group of Object.keys(grouped).sort(
180
+ (a, b) => Number(a) - Number(b)
181
+ )) {
182
+ sortedNodes.push(...sortNodes.sortNodes(grouped[group], options));
183
+ }
184
+ return sortedNodes;
185
+ };
186
+ let checkGroupSort = (left, right) => {
187
+ let leftNum = getGroupNumber.getGroupNumber(options.groups, left);
188
+ let rightNum = getGroupNumber.getGroupNumber(options.groups, right);
189
+ return leftNum > rightNum || leftNum === rightNum && isPositive.isPositive(compare.compare(left, right, options));
190
+ };
191
+ let optionalityOrder = options["optionality-order"];
192
+ let checkOrder = (members, left, right, iteration) => {
193
+ if (optionalityOrder === index.OptionalityOrder.ignore) {
194
+ return checkGroupSort(left, right);
195
+ }
196
+ let switchIndex = members.findIndex(
197
+ (_, i) => i && isMemberOptional.isMemberOptional(members[i - 1].node) !== isMemberOptional.isMemberOptional(members[i].node)
198
+ );
199
+ if (iteration < switchIndex && iteration + 1 !== switchIndex) {
200
+ return checkGroupSort(left, right);
201
+ }
202
+ if (isMemberOptional.isMemberOptional(left.node) !== isMemberOptional.isMemberOptional(right.node)) {
203
+ return isMemberOptional.isMemberOptional(left.node) !== (optionalityOrder === index.OptionalityOrder["optional-first"]);
204
+ }
205
+ return checkGroupSort(left, right);
206
+ };
207
+ for (let nodes of formattedMembers) {
208
+ pairwise.pairwise(nodes, (left, right, iteration) => {
209
+ if (checkOrder(nodes, left, right, iteration)) {
210
+ context.report({
211
+ messageId: "unexpectedInterfacePropertiesOrder",
212
+ data: {
213
+ left: toSingleLine.toSingleLine(left.name),
214
+ right: toSingleLine.toSingleLine(right.name)
215
+ },
216
+ node: right.node,
217
+ fix: (fixer) => {
218
+ let sortedNodes;
219
+ if (optionalityOrder !== index.OptionalityOrder.ignore) {
220
+ let optionalNodes = nodes.filter(
221
+ (member) => isMemberOptional.isMemberOptional(member.node)
222
+ );
223
+ let requiredNodes = nodes.filter(
224
+ (member) => !isMemberOptional.isMemberOptional(member.node)
225
+ );
226
+ sortedNodes = optionalityOrder === index.OptionalityOrder["optional-first"] ? [
227
+ ...toSorted(optionalNodes),
228
+ ...toSorted(requiredNodes)
229
+ ] : [
230
+ ...toSorted(requiredNodes),
231
+ ...toSorted(optionalNodes)
232
+ ];
233
+ } else {
234
+ sortedNodes = toSorted(nodes);
235
+ }
236
+ return makeFixes.makeFixes(
237
+ fixer,
238
+ nodes,
239
+ sortedNodes,
240
+ context.sourceCode
241
+ );
242
+ }
243
+ });
244
+ }
245
+ });
246
+ }
247
+ }
248
+ }
249
+ }
250
+ })
251
+ });
252
+ exports.RULE_NAME = RULE_NAME;
253
+ exports.default = sortInterfaces;