eslint-plugin-perfectionist 4.2.0 → 4.4.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/alphabet.d.ts +176 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/rules/sort-array-includes-utils.js +30 -0
- package/dist/rules/sort-array-includes.js +150 -54
- package/dist/rules/sort-array-includes.types.js +10 -0
- package/dist/rules/sort-classes.js +19 -16
- package/dist/rules/sort-decorators.js +11 -6
- package/dist/rules/sort-enums.js +39 -31
- package/dist/rules/sort-exports.js +11 -5
- package/dist/rules/sort-heritage-clauses.js +12 -6
- package/dist/rules/sort-imports.js +34 -21
- package/dist/rules/sort-interfaces.js +3 -1
- package/dist/rules/sort-intersection-types.js +24 -19
- package/dist/rules/sort-jsx-props.js +12 -7
- package/dist/rules/sort-maps.js +18 -13
- package/dist/rules/sort-modules.js +23 -18
- package/dist/rules/sort-named-exports.js +18 -13
- package/dist/rules/sort-named-imports.js +18 -13
- package/dist/rules/sort-object-types.js +149 -103
- package/dist/rules/sort-objects.js +142 -58
- package/dist/rules/sort-sets.js +14 -5
- package/dist/rules/sort-switch-case.js +16 -14
- package/dist/rules/sort-union-types.js +24 -19
- package/dist/rules/sort-variable-declarations.js +18 -13
- package/dist/utils/alphabet.js +385 -0
- package/dist/utils/common-json-schemas.js +27 -5
- package/dist/utils/compare.js +88 -38
- package/dist/utils/convert-boolean-to-sign.js +4 -0
- package/dist/utils/create-node-index-map.js +10 -0
- package/dist/{rules → utils}/get-custom-groups-compare-options.js +1 -0
- package/dist/utils/{get-node-parent.js → get-first-node-parent-with-type.js} +3 -4
- package/dist/utils/get-matching-context-options.js +18 -0
- package/dist/utils/get-settings.js +1 -0
- package/dist/utils/is-node-function-type.js +15 -0
- package/dist/utils/is-partition-comment.js +4 -1
- package/dist/utils/pairwise.js +1 -3
- package/dist/utils/validate-custom-sort-configuration.js +11 -0
- package/dist/{rules → utils}/validate-generated-groups-configuration.js +1 -1
- package/dist/utils/validate-groups-configuration.js +11 -5
- package/package.json +7 -3
- package/readme.md +4 -3
|
@@ -5,13 +5,17 @@ Object.defineProperties(exports, {
|
|
|
5
5
|
})
|
|
6
6
|
const commonJsonSchemas = require('../utils/common-json-schemas.js')
|
|
7
7
|
const validateNewlinesAndPartitionConfiguration = require('../utils/validate-newlines-and-partition-configuration.js')
|
|
8
|
-
const validateGeneratedGroupsConfiguration = require('
|
|
9
|
-
const
|
|
8
|
+
const validateGeneratedGroupsConfiguration = require('../utils/validate-generated-groups-configuration.js')
|
|
9
|
+
const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
|
|
10
|
+
const getCustomGroupsCompareOptions = require('../utils/get-custom-groups-compare-options.js')
|
|
11
|
+
const getMatchingContextOptions = require('../utils/get-matching-context-options.js')
|
|
10
12
|
const generatePredefinedGroups = require('../utils/generate-predefined-groups.js')
|
|
11
13
|
const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
|
|
12
14
|
const sortObjectTypes_types = require('./sort-object-types.types.js')
|
|
13
15
|
const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
|
|
14
16
|
const isPartitionComment = require('../utils/is-partition-comment.js')
|
|
17
|
+
const isNodeFunctionType = require('../utils/is-node-function-type.js')
|
|
18
|
+
const createNodeIndexMap = require('../utils/create-node-index-map.js')
|
|
15
19
|
const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
|
|
16
20
|
const getCommentsBefore = require('../utils/get-comments-before.js')
|
|
17
21
|
const makeNewlinesFixes = require('../utils/make-newlines-fixes.js')
|
|
@@ -37,55 +41,69 @@ let defaultOptions = {
|
|
|
37
41
|
partitionByNewLine: false,
|
|
38
42
|
newlinesBetween: 'ignore',
|
|
39
43
|
specialCharacters: 'keep',
|
|
44
|
+
useConfigurationIf: {},
|
|
40
45
|
type: 'alphabetical',
|
|
41
46
|
groupKind: 'mixed',
|
|
42
47
|
ignorePattern: [],
|
|
43
48
|
ignoreCase: true,
|
|
44
49
|
customGroups: {},
|
|
45
50
|
locales: 'en-US',
|
|
51
|
+
alphabet: '',
|
|
46
52
|
order: 'asc',
|
|
47
53
|
groups: [],
|
|
48
54
|
}
|
|
49
55
|
let jsonSchema = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
items: {
|
|
57
|
+
properties: {
|
|
58
|
+
ignorePattern: {
|
|
59
|
+
description:
|
|
60
|
+
'Specifies names or patterns for nodes that should be ignored by rule.',
|
|
61
|
+
items: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
},
|
|
64
|
+
type: 'array',
|
|
65
|
+
},
|
|
66
|
+
useConfigurationIf: commonJsonSchemas.buildUseConfigurationIfJsonSchema({
|
|
67
|
+
additionalProperties: {
|
|
68
|
+
declarationMatchesPattern: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
partitionByComment: {
|
|
74
|
+
...commonJsonSchemas.partitionByCommentJsonSchema,
|
|
75
|
+
description:
|
|
76
|
+
'Allows you to use comments to separate members into logical groups.',
|
|
77
|
+
},
|
|
78
|
+
customGroups: {
|
|
79
|
+
oneOf: [
|
|
80
|
+
commonJsonSchemas.customGroupsJsonSchema,
|
|
81
|
+
commonJsonSchemas.buildCustomGroupsArrayJsonSchema({
|
|
82
|
+
singleCustomGroupJsonSchema:
|
|
83
|
+
sortObjectTypes_types.singleCustomGroupJsonSchema,
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
groupKind: {
|
|
88
|
+
enum: ['mixed', 'required-first', 'optional-first'],
|
|
89
|
+
description: 'Specifies top-level groups.',
|
|
55
90
|
type: 'string',
|
|
56
91
|
},
|
|
57
|
-
type:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
commonJsonSchemas.customGroupsJsonSchema,
|
|
67
|
-
commonJsonSchemas.buildCustomGroupsArrayJsonSchema({
|
|
68
|
-
singleCustomGroupJsonSchema:
|
|
69
|
-
sortObjectTypes_types.singleCustomGroupJsonSchema,
|
|
70
|
-
}),
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
groupKind: {
|
|
74
|
-
enum: ['mixed', 'required-first', 'optional-first'],
|
|
75
|
-
description: 'Specifies top-level groups.',
|
|
76
|
-
type: 'string',
|
|
92
|
+
type: commonJsonSchemas.buildTypeJsonSchema({ withUnsorted: true }),
|
|
93
|
+
partitionByNewLine: commonJsonSchemas.partitionByNewLineJsonSchema,
|
|
94
|
+
specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
|
|
95
|
+
newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
|
|
96
|
+
ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
|
|
97
|
+
alphabet: commonJsonSchemas.alphabetJsonSchema,
|
|
98
|
+
locales: commonJsonSchemas.localesJsonSchema,
|
|
99
|
+
groups: commonJsonSchemas.groupsJsonSchema,
|
|
100
|
+
order: commonJsonSchemas.orderJsonSchema,
|
|
77
101
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
|
|
81
|
-
ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
|
|
82
|
-
locales: commonJsonSchemas.localesJsonSchema,
|
|
83
|
-
groups: commonJsonSchemas.groupsJsonSchema,
|
|
84
|
-
order: commonJsonSchemas.orderJsonSchema,
|
|
85
|
-
type: commonJsonSchemas.typeJsonSchema,
|
|
102
|
+
additionalProperties: false,
|
|
103
|
+
type: 'object',
|
|
86
104
|
},
|
|
87
|
-
|
|
88
|
-
type: '
|
|
105
|
+
uniqueItems: true,
|
|
106
|
+
type: 'array',
|
|
89
107
|
}
|
|
90
108
|
const sortObjectTypes = createEslintRule.createEslintRule({
|
|
91
109
|
meta: {
|
|
@@ -104,7 +122,7 @@ const sortObjectTypes = createEslintRule.createEslintRule({
|
|
|
104
122
|
description: 'Enforce sorted object types.',
|
|
105
123
|
recommended: true,
|
|
106
124
|
},
|
|
107
|
-
schema:
|
|
125
|
+
schema: jsonSchema,
|
|
108
126
|
type: 'suggestion',
|
|
109
127
|
fixable: 'code',
|
|
110
128
|
},
|
|
@@ -138,11 +156,45 @@ let sortObjectTypeElements = ({
|
|
|
138
156
|
return
|
|
139
157
|
}
|
|
140
158
|
let settings = getSettings.getSettings(context.settings)
|
|
141
|
-
let
|
|
142
|
-
|
|
159
|
+
let sourceCode = getSourceCode.getSourceCode(context)
|
|
160
|
+
let matchedContextOptions = getMatchingContextOptions
|
|
161
|
+
.getMatchingContextOptions({
|
|
162
|
+
nodeNames: elements.map(node =>
|
|
163
|
+
getNodeName({ typeElement: node, sourceCode }),
|
|
164
|
+
),
|
|
165
|
+
contextOptions: context.options,
|
|
166
|
+
})
|
|
167
|
+
.find(options2 => {
|
|
168
|
+
var _a
|
|
169
|
+
if (
|
|
170
|
+
!((_a = options2.useConfigurationIf) == null
|
|
171
|
+
? void 0
|
|
172
|
+
: _a.declarationMatchesPattern)
|
|
173
|
+
) {
|
|
174
|
+
return true
|
|
175
|
+
}
|
|
176
|
+
if (!parentNodeName) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
return matches.matches(
|
|
180
|
+
parentNodeName,
|
|
181
|
+
options2.useConfigurationIf.declarationMatchesPattern,
|
|
182
|
+
)
|
|
183
|
+
})
|
|
184
|
+
let completeOptions = complete.complete(
|
|
185
|
+
matchedContextOptions,
|
|
143
186
|
settings,
|
|
144
187
|
defaultOptions,
|
|
145
188
|
)
|
|
189
|
+
let { type } = completeOptions
|
|
190
|
+
if (type === 'unsorted') {
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
let options = {
|
|
194
|
+
...completeOptions,
|
|
195
|
+
type,
|
|
196
|
+
}
|
|
197
|
+
validateCustomSortConfiguration.validateCustomSortConfiguration(options)
|
|
146
198
|
validateGeneratedGroupsConfiguration.validateGeneratedGroupsConfiguration({
|
|
147
199
|
customGroups: options.customGroups,
|
|
148
200
|
selectors: sortObjectTypes_types.allSelectors,
|
|
@@ -159,70 +211,29 @@ let sortObjectTypeElements = ({
|
|
|
159
211
|
) {
|
|
160
212
|
return
|
|
161
213
|
}
|
|
162
|
-
let sourceCode = getSourceCode.getSourceCode(context)
|
|
163
214
|
let eslintDisabledLines = getEslintDisabledLines.getEslintDisabledLines({
|
|
164
215
|
ruleName: context.id,
|
|
165
216
|
sourceCode,
|
|
166
217
|
})
|
|
167
218
|
let formattedMembers = elements.reduce(
|
|
168
219
|
(accumulator, typeElement) => {
|
|
169
|
-
|
|
170
|
-
|
|
220
|
+
if (
|
|
221
|
+
typeElement.type === 'TSCallSignatureDeclaration' ||
|
|
222
|
+
typeElement.type === 'TSConstructSignatureDeclaration'
|
|
223
|
+
) {
|
|
171
224
|
accumulator.push([])
|
|
172
225
|
return accumulator
|
|
173
226
|
}
|
|
174
|
-
let
|
|
175
|
-
let lastSortingNode =
|
|
176
|
-
(_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1)
|
|
227
|
+
let lastGroup = accumulator.at(-1)
|
|
228
|
+
let lastSortingNode = lastGroup == null ? void 0 : lastGroup.at(-1)
|
|
177
229
|
let { setCustomGroups, defineGroup, getGroup } =
|
|
178
230
|
useGroups.useGroups(options)
|
|
179
|
-
let formatName = value => value.replace(/[,;]$/u, '')
|
|
180
|
-
if (typeElement.type === 'TSPropertySignature') {
|
|
181
|
-
if (typeElement.key.type === 'Identifier') {
|
|
182
|
-
;({ name } = typeElement.key)
|
|
183
|
-
} else if (typeElement.key.type === 'Literal') {
|
|
184
|
-
name = `${typeElement.key.value}`
|
|
185
|
-
} else {
|
|
186
|
-
let end =
|
|
187
|
-
((_b = typeElement.typeAnnotation) == null
|
|
188
|
-
? void 0
|
|
189
|
-
: _b.range.at(0)) ??
|
|
190
|
-
typeElement.range.at(1) - (typeElement.optional ? '?'.length : 0)
|
|
191
|
-
name = sourceCode.text.slice(typeElement.range.at(0), end)
|
|
192
|
-
}
|
|
193
|
-
} else if (typeElement.type === 'TSIndexSignature') {
|
|
194
|
-
let endIndex =
|
|
195
|
-
((_c = typeElement.typeAnnotation) == null
|
|
196
|
-
? void 0
|
|
197
|
-
: _c.range.at(0)) ?? typeElement.range.at(1)
|
|
198
|
-
name = formatName(
|
|
199
|
-
sourceCode.text.slice(typeElement.range.at(0), endIndex),
|
|
200
|
-
)
|
|
201
|
-
} else if (
|
|
202
|
-
typeElement.type === 'TSMethodSignature' &&
|
|
203
|
-
'name' in typeElement.key
|
|
204
|
-
) {
|
|
205
|
-
;({ name } = typeElement.key)
|
|
206
|
-
} else {
|
|
207
|
-
name = formatName(
|
|
208
|
-
sourceCode.text.slice(
|
|
209
|
-
typeElement.range.at(0),
|
|
210
|
-
typeElement.range.at(1),
|
|
211
|
-
),
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
231
|
let selectors = []
|
|
215
232
|
let modifiers = []
|
|
216
233
|
if (typeElement.type === 'TSIndexSignature') {
|
|
217
234
|
selectors.push('index-signature')
|
|
218
235
|
}
|
|
219
|
-
if (
|
|
220
|
-
typeElement.type === 'TSMethodSignature' ||
|
|
221
|
-
(typeElement.type === 'TSPropertySignature' &&
|
|
222
|
-
((_d = typeElement.typeAnnotation) == null
|
|
223
|
-
? void 0
|
|
224
|
-
: _d.typeAnnotation.type) === 'TSFunctionType')
|
|
225
|
-
) {
|
|
236
|
+
if (isNodeFunctionType.isNodeFunctionType(typeElement)) {
|
|
226
237
|
selectors.push('method')
|
|
227
238
|
}
|
|
228
239
|
if (typeElement.loc.start.line !== typeElement.loc.end.line) {
|
|
@@ -230,8 +241,9 @@ let sortObjectTypeElements = ({
|
|
|
230
241
|
selectors.push('multiline')
|
|
231
242
|
}
|
|
232
243
|
if (
|
|
233
|
-
!
|
|
234
|
-
|
|
244
|
+
!['index-signature', 'method'].some(selector =>
|
|
245
|
+
selectors.includes(selector),
|
|
246
|
+
)
|
|
235
247
|
) {
|
|
236
248
|
selectors.push('property')
|
|
237
249
|
}
|
|
@@ -241,15 +253,15 @@ let sortObjectTypeElements = ({
|
|
|
241
253
|
} else {
|
|
242
254
|
modifiers.push('required')
|
|
243
255
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
)) {
|
|
256
|
+
let predefinedGroups = generatePredefinedGroups.generatePredefinedGroups({
|
|
257
|
+
cache: cachedGroupsByModifiersAndSelectors,
|
|
258
|
+
selectors,
|
|
259
|
+
modifiers,
|
|
260
|
+
})
|
|
261
|
+
for (let predefinedGroup of predefinedGroups) {
|
|
251
262
|
defineGroup(predefinedGroup)
|
|
252
263
|
}
|
|
264
|
+
let name = getNodeName({ typeElement, sourceCode })
|
|
253
265
|
if (Array.isArray(options.customGroups)) {
|
|
254
266
|
for (let customGroup of options.customGroups) {
|
|
255
267
|
if (
|
|
@@ -302,9 +314,10 @@ let sortObjectTypeElements = ({
|
|
|
302
314
|
sortingNode,
|
|
303
315
|
))
|
|
304
316
|
) {
|
|
305
|
-
|
|
317
|
+
lastGroup = []
|
|
318
|
+
accumulator.push(lastGroup)
|
|
306
319
|
}
|
|
307
|
-
|
|
320
|
+
lastGroup == null ? void 0 : lastGroup.push(sortingNode)
|
|
308
321
|
return accumulator
|
|
309
322
|
},
|
|
310
323
|
[[]],
|
|
@@ -338,17 +351,18 @@ let sortObjectTypeElements = ({
|
|
|
338
351
|
let sortedNodes = sortNodesExcludingEslintDisabled(false)
|
|
339
352
|
let sortedNodesExcludingEslintDisabled =
|
|
340
353
|
sortNodesExcludingEslintDisabled(true)
|
|
354
|
+
let nodeIndexMap = createNodeIndexMap.createNodeIndexMap(sortedNodes)
|
|
341
355
|
pairwise.pairwise(nodes, (left, right) => {
|
|
342
356
|
let leftNumber = getGroupNumber.getGroupNumber(options.groups, left)
|
|
343
357
|
let rightNumber = getGroupNumber.getGroupNumber(options.groups, right)
|
|
344
|
-
let
|
|
345
|
-
let
|
|
358
|
+
let leftIndex = nodeIndexMap.get(left)
|
|
359
|
+
let rightIndex = nodeIndexMap.get(right)
|
|
346
360
|
let indexOfRightExcludingEslintDisabled =
|
|
347
361
|
sortedNodesExcludingEslintDisabled.indexOf(right)
|
|
348
362
|
let messageIds = []
|
|
349
363
|
if (
|
|
350
|
-
|
|
351
|
-
|
|
364
|
+
leftIndex > rightIndex ||
|
|
365
|
+
leftIndex >= indexOfRightExcludingEslintDisabled
|
|
352
366
|
) {
|
|
353
367
|
messageIds.push(
|
|
354
368
|
leftNumber === rightNumber
|
|
@@ -400,6 +414,38 @@ let sortObjectTypeElements = ({
|
|
|
400
414
|
})
|
|
401
415
|
}
|
|
402
416
|
}
|
|
417
|
+
let getNodeName = ({ typeElement, sourceCode }) => {
|
|
418
|
+
var _a, _b
|
|
419
|
+
let name
|
|
420
|
+
let formatName = value => value.replace(/[,;]$/u, '')
|
|
421
|
+
if (typeElement.type === 'TSPropertySignature') {
|
|
422
|
+
if (typeElement.key.type === 'Identifier') {
|
|
423
|
+
;({ name } = typeElement.key)
|
|
424
|
+
} else if (typeElement.key.type === 'Literal') {
|
|
425
|
+
name = `${typeElement.key.value}`
|
|
426
|
+
} else {
|
|
427
|
+
let end =
|
|
428
|
+
((_a = typeElement.typeAnnotation) == null ? void 0 : _a.range.at(0)) ??
|
|
429
|
+
typeElement.range.at(1) - (typeElement.optional ? '?'.length : 0)
|
|
430
|
+
name = sourceCode.text.slice(typeElement.range.at(0), end)
|
|
431
|
+
}
|
|
432
|
+
} else if (typeElement.type === 'TSIndexSignature') {
|
|
433
|
+
let endIndex =
|
|
434
|
+
((_b = typeElement.typeAnnotation) == null ? void 0 : _b.range.at(0)) ??
|
|
435
|
+
typeElement.range.at(1)
|
|
436
|
+
name = formatName(sourceCode.text.slice(typeElement.range.at(0), endIndex))
|
|
437
|
+
} else if (
|
|
438
|
+
typeElement.type === 'TSMethodSignature' &&
|
|
439
|
+
'name' in typeElement.key
|
|
440
|
+
) {
|
|
441
|
+
;({ name } = typeElement.key)
|
|
442
|
+
} else {
|
|
443
|
+
name = formatName(
|
|
444
|
+
sourceCode.text.slice(typeElement.range.at(0), typeElement.range.at(1)),
|
|
445
|
+
)
|
|
446
|
+
}
|
|
447
|
+
return name
|
|
448
|
+
}
|
|
403
449
|
exports.default = sortObjectTypes
|
|
404
450
|
exports.jsonSchema = jsonSchema
|
|
405
451
|
exports.sortObjectTypeElements = sortObjectTypeElements
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
const types = require('@typescript-eslint/types')
|
|
2
3
|
const commonJsonSchemas = require('../utils/common-json-schemas.js')
|
|
3
4
|
const sortNodesByDependencies = require('../utils/sort-nodes-by-dependencies.js')
|
|
4
5
|
const validateNewlinesAndPartitionConfiguration = require('../utils/validate-newlines-and-partition-configuration.js')
|
|
6
|
+
const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
|
|
7
|
+
const getFirstNodeParentWithType = require('../utils/get-first-node-parent-with-type.js')
|
|
5
8
|
const validateGroupsConfiguration = require('../utils/validate-groups-configuration.js')
|
|
9
|
+
const getMatchingContextOptions = require('../utils/get-matching-context-options.js')
|
|
6
10
|
const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
|
|
7
11
|
const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
|
|
12
|
+
const createNodeIndexMap = require('../utils/create-node-index-map.js')
|
|
8
13
|
const isPartitionComment = require('../utils/is-partition-comment.js')
|
|
9
14
|
const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
|
|
10
15
|
const getCommentsBefore = require('../utils/get-comments-before.js')
|
|
@@ -14,7 +19,6 @@ const createEslintRule = require('../utils/create-eslint-rule.js')
|
|
|
14
19
|
const getLinesBetween = require('../utils/get-lines-between.js')
|
|
15
20
|
const getGroupNumber = require('../utils/get-group-number.js')
|
|
16
21
|
const getSourceCode = require('../utils/get-source-code.js')
|
|
17
|
-
const getNodeParent = require('../utils/get-node-parent.js')
|
|
18
22
|
const rangeToDiff = require('../utils/range-to-diff.js')
|
|
19
23
|
const getSettings = require('../utils/get-settings.js')
|
|
20
24
|
const isSortable = require('../utils/is-sortable.js')
|
|
@@ -33,26 +37,67 @@ let defaultOptions = {
|
|
|
33
37
|
objectDeclarations: true,
|
|
34
38
|
styledComponents: true,
|
|
35
39
|
destructureOnly: false,
|
|
40
|
+
useConfigurationIf: {},
|
|
36
41
|
type: 'alphabetical',
|
|
37
42
|
ignorePattern: [],
|
|
38
43
|
ignoreCase: true,
|
|
39
44
|
customGroups: {},
|
|
40
45
|
locales: 'en-US',
|
|
46
|
+
alphabet: '',
|
|
41
47
|
order: 'asc',
|
|
42
48
|
groups: [],
|
|
43
49
|
}
|
|
44
50
|
const sortObjects = createEslintRule.createEslintRule({
|
|
45
51
|
create: context => {
|
|
52
|
+
let settings = getSettings.getSettings(context.settings)
|
|
53
|
+
let sourceCode = getSourceCode.getSourceCode(context)
|
|
46
54
|
let sortObject = nodeObject => {
|
|
47
55
|
if (!isSortable.isSortable(nodeObject.properties)) {
|
|
48
56
|
return
|
|
49
57
|
}
|
|
50
|
-
let
|
|
51
|
-
let
|
|
52
|
-
|
|
58
|
+
let objectParent = getObjectParent({ node: nodeObject })
|
|
59
|
+
let matchedContextOptions = getMatchingContextOptions
|
|
60
|
+
.getMatchingContextOptions({
|
|
61
|
+
nodeNames: nodeObject.properties
|
|
62
|
+
.map(property => getNodeName({ sourceCode, property }))
|
|
63
|
+
.filter(nodeName => nodeName !== null),
|
|
64
|
+
contextOptions: context.options,
|
|
65
|
+
})
|
|
66
|
+
.find(options2 => {
|
|
67
|
+
var _a
|
|
68
|
+
if (
|
|
69
|
+
!((_a = options2.useConfigurationIf) == null
|
|
70
|
+
? void 0
|
|
71
|
+
: _a.callingFunctionNamePattern)
|
|
72
|
+
) {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
if (
|
|
76
|
+
(objectParent == null ? void 0 : objectParent.type) ===
|
|
77
|
+
'VariableDeclarator' ||
|
|
78
|
+
!(objectParent == null ? void 0 : objectParent.name)
|
|
79
|
+
) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
return matches.matches(
|
|
83
|
+
objectParent.name,
|
|
84
|
+
options2.useConfigurationIf.callingFunctionNamePattern,
|
|
85
|
+
)
|
|
86
|
+
})
|
|
87
|
+
let completeOptions = complete.complete(
|
|
88
|
+
matchedContextOptions,
|
|
53
89
|
settings,
|
|
54
90
|
defaultOptions,
|
|
55
91
|
)
|
|
92
|
+
let { type } = completeOptions
|
|
93
|
+
if (type === 'unsorted') {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
let options = {
|
|
97
|
+
...completeOptions,
|
|
98
|
+
type,
|
|
99
|
+
}
|
|
100
|
+
validateCustomSortConfiguration.validateCustomSortConfiguration(options)
|
|
56
101
|
validateGroupsConfiguration.validateGroupsConfiguration(
|
|
57
102
|
options.groups,
|
|
58
103
|
['multiline', 'method', 'unknown'],
|
|
@@ -69,43 +114,13 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
69
114
|
} else if (options.destructureOnly || !options.objectDeclarations) {
|
|
70
115
|
return
|
|
71
116
|
}
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
'VariableDeclarator'
|
|
80
|
-
? variableParent.id
|
|
81
|
-
: variableParent == null
|
|
82
|
-
? void 0
|
|
83
|
-
: variableParent.key
|
|
84
|
-
let variableIdentifier =
|
|
85
|
-
(parentId == null ? void 0 : parentId.type) === 'Identifier'
|
|
86
|
-
? parentId.name
|
|
87
|
-
: null
|
|
88
|
-
let checkMatch = identifier =>
|
|
89
|
-
options.ignorePattern.some(pattern =>
|
|
90
|
-
matches.matches(identifier, pattern),
|
|
91
|
-
)
|
|
92
|
-
if (
|
|
93
|
-
typeof variableIdentifier === 'string' &&
|
|
94
|
-
checkMatch(variableIdentifier)
|
|
95
|
-
) {
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
let callParent = getNodeParent.getNodeParent(nodeObject, [
|
|
99
|
-
'CallExpression',
|
|
100
|
-
])
|
|
101
|
-
let callIdentifier =
|
|
102
|
-
(callParent == null ? void 0 : callParent.type) ===
|
|
103
|
-
'CallExpression' && callParent.callee.type === 'Identifier'
|
|
104
|
-
? callParent.callee.name
|
|
105
|
-
: null
|
|
106
|
-
if (callIdentifier && checkMatch(callIdentifier)) {
|
|
107
|
-
return
|
|
108
|
-
}
|
|
117
|
+
if (
|
|
118
|
+
(objectParent == null ? void 0 : objectParent.name) &&
|
|
119
|
+
options.ignorePattern.some(pattern =>
|
|
120
|
+
matches.matches(objectParent.name, pattern),
|
|
121
|
+
)
|
|
122
|
+
) {
|
|
123
|
+
return
|
|
109
124
|
}
|
|
110
125
|
let isStyledCallExpression = identifier =>
|
|
111
126
|
identifier.type === 'Identifier' && identifier.name === 'styled'
|
|
@@ -130,7 +145,6 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
130
145
|
) {
|
|
131
146
|
return
|
|
132
147
|
}
|
|
133
|
-
let sourceCode = getSourceCode.getSourceCode(context)
|
|
134
148
|
let eslintDisabledLines = getEslintDisabledLines.getEslintDisabledLines({
|
|
135
149
|
ruleName: context.id,
|
|
136
150
|
sourceCode,
|
|
@@ -263,14 +277,13 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
263
277
|
lastProperty,
|
|
264
278
|
propertySortingNode,
|
|
265
279
|
)) ||
|
|
266
|
-
(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
))
|
|
280
|
+
isPartitionComment.hasPartitionComment(
|
|
281
|
+
options.partitionByComment,
|
|
282
|
+
getCommentsBefore.getCommentsBefore({
|
|
283
|
+
node: property,
|
|
284
|
+
sourceCode,
|
|
285
|
+
}),
|
|
286
|
+
)
|
|
274
287
|
) {
|
|
275
288
|
accumulator.push([])
|
|
276
289
|
}
|
|
@@ -301,18 +314,19 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
301
314
|
let sortedNodesExcludingEslintDisabled =
|
|
302
315
|
sortNodesIgnoringEslintDisabledNodes(true)
|
|
303
316
|
let nodes = formattedMembers.flat()
|
|
317
|
+
let nodeIndexMap = createNodeIndexMap.createNodeIndexMap(sortedNodes)
|
|
304
318
|
pairwise.pairwise(nodes, (left, right) => {
|
|
305
319
|
let leftNumber = getGroupNumber.getGroupNumber(options.groups, left)
|
|
306
320
|
let rightNumber = getGroupNumber.getGroupNumber(options.groups, right)
|
|
307
|
-
let
|
|
308
|
-
let
|
|
321
|
+
let leftIndex = nodeIndexMap.get(left)
|
|
322
|
+
let rightIndex = nodeIndexMap.get(right)
|
|
309
323
|
let indexOfRightExcludingEslintDisabled =
|
|
310
324
|
sortedNodesExcludingEslintDisabled.indexOf(right)
|
|
311
325
|
let messageIds = []
|
|
312
326
|
let firstUnorderedNodeDependentOnRight
|
|
313
327
|
if (
|
|
314
|
-
|
|
315
|
-
|
|
328
|
+
leftIndex > rightIndex ||
|
|
329
|
+
leftIndex >= indexOfRightExcludingEslintDisabled
|
|
316
330
|
) {
|
|
317
331
|
firstUnorderedNodeDependentOnRight =
|
|
318
332
|
sortNodesByDependencies.getFirstUnorderedNodeDependentOn(
|
|
@@ -382,8 +396,8 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
382
396
|
}
|
|
383
397
|
},
|
|
384
398
|
meta: {
|
|
385
|
-
schema:
|
|
386
|
-
{
|
|
399
|
+
schema: {
|
|
400
|
+
items: {
|
|
387
401
|
properties: {
|
|
388
402
|
destructuredObjects: {
|
|
389
403
|
oneOf: [
|
|
@@ -412,6 +426,14 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
412
426
|
},
|
|
413
427
|
type: 'array',
|
|
414
428
|
},
|
|
429
|
+
useConfigurationIf:
|
|
430
|
+
commonJsonSchemas.buildUseConfigurationIfJsonSchema({
|
|
431
|
+
additionalProperties: {
|
|
432
|
+
callingFunctionNamePattern: {
|
|
433
|
+
type: 'string',
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
}),
|
|
415
437
|
partitionByComment: {
|
|
416
438
|
...commonJsonSchemas.partitionByCommentJsonSchema,
|
|
417
439
|
description:
|
|
@@ -429,20 +451,23 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
429
451
|
description: 'Controls whether to sort styled components.',
|
|
430
452
|
type: 'boolean',
|
|
431
453
|
},
|
|
454
|
+
type: commonJsonSchemas.buildTypeJsonSchema({ withUnsorted: true }),
|
|
432
455
|
partitionByNewLine: commonJsonSchemas.partitionByNewLineJsonSchema,
|
|
433
456
|
specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
|
|
434
457
|
newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
|
|
435
458
|
customGroups: commonJsonSchemas.customGroupsJsonSchema,
|
|
436
459
|
ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
|
|
460
|
+
alphabet: commonJsonSchemas.alphabetJsonSchema,
|
|
437
461
|
locales: commonJsonSchemas.localesJsonSchema,
|
|
438
462
|
groups: commonJsonSchemas.groupsJsonSchema,
|
|
439
463
|
order: commonJsonSchemas.orderJsonSchema,
|
|
440
|
-
type: commonJsonSchemas.typeJsonSchema,
|
|
441
464
|
},
|
|
442
465
|
additionalProperties: false,
|
|
443
466
|
type: 'object',
|
|
444
467
|
},
|
|
445
|
-
|
|
468
|
+
uniqueItems: true,
|
|
469
|
+
type: 'array',
|
|
470
|
+
},
|
|
446
471
|
messages: {
|
|
447
472
|
unexpectedObjectsGroupOrder:
|
|
448
473
|
'Expected "{{right}}" ({{rightGroup}}) to come before "{{left}}" ({{leftGroup}}).',
|
|
@@ -465,4 +490,63 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
465
490
|
defaultOptions: [defaultOptions],
|
|
466
491
|
name: 'sort-objects',
|
|
467
492
|
})
|
|
493
|
+
let getNodeName = ({ sourceCode, property }) => {
|
|
494
|
+
if (property.type === 'SpreadElement' || property.type === 'RestElement') {
|
|
495
|
+
return null
|
|
496
|
+
}
|
|
497
|
+
if (property.key.type === 'Identifier') {
|
|
498
|
+
return property.key.name
|
|
499
|
+
} else if (property.key.type === 'Literal') {
|
|
500
|
+
return `${property.key.value}`
|
|
501
|
+
}
|
|
502
|
+
return sourceCode.getText(property.key)
|
|
503
|
+
}
|
|
504
|
+
let getObjectParent = ({ node }) => {
|
|
505
|
+
let variableParentName = getVariableParentName({ node })
|
|
506
|
+
if (variableParentName) {
|
|
507
|
+
return {
|
|
508
|
+
type: 'VariableDeclarator',
|
|
509
|
+
name: variableParentName,
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
let callParentName = getCallExpressionParentName({ node })
|
|
513
|
+
if (callParentName) {
|
|
514
|
+
return {
|
|
515
|
+
type: 'CallExpression',
|
|
516
|
+
name: callParentName,
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return null
|
|
520
|
+
}
|
|
521
|
+
let getVariableParentName = ({ node }) => {
|
|
522
|
+
let variableParent = getFirstNodeParentWithType.getFirstNodeParentWithType({
|
|
523
|
+
allowedTypes: [
|
|
524
|
+
types.TSESTree.AST_NODE_TYPES.VariableDeclarator,
|
|
525
|
+
types.TSESTree.AST_NODE_TYPES.Property,
|
|
526
|
+
],
|
|
527
|
+
node,
|
|
528
|
+
})
|
|
529
|
+
if (!variableParent) {
|
|
530
|
+
return null
|
|
531
|
+
}
|
|
532
|
+
let parentId
|
|
533
|
+
if (variableParent.type === 'VariableDeclarator') {
|
|
534
|
+
parentId = variableParent.id
|
|
535
|
+
} else if ('key' in variableParent) {
|
|
536
|
+
parentId = variableParent.key
|
|
537
|
+
} else {
|
|
538
|
+
return null
|
|
539
|
+
}
|
|
540
|
+
return parentId.type === 'Identifier' ? parentId.name : null
|
|
541
|
+
}
|
|
542
|
+
let getCallExpressionParentName = ({ node }) => {
|
|
543
|
+
let callParent = getFirstNodeParentWithType.getFirstNodeParentWithType({
|
|
544
|
+
allowedTypes: [types.TSESTree.AST_NODE_TYPES.CallExpression],
|
|
545
|
+
node,
|
|
546
|
+
})
|
|
547
|
+
if (!callParent) {
|
|
548
|
+
return null
|
|
549
|
+
}
|
|
550
|
+
return callParent.callee.type === 'Identifier' ? callParent.callee.name : null
|
|
551
|
+
}
|
|
468
552
|
module.exports = sortObjects
|