eslint-plugin-perfectionist 4.0.2 → 4.1.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.
@@ -6,6 +6,7 @@ const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
6
6
  const isPartitionComment = require('../utils/is-partition-comment.js')
7
7
  const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
8
8
  const getCommentsBefore = require('../utils/get-comments-before.js')
9
+ const getNodeDecorators = require('../utils/get-node-decorators.js')
9
10
  const createEslintRule = require('../utils/create-eslint-rule.js')
10
11
  const getDecoratorName = require('../utils/get-decorator-name.js')
11
12
  const getGroupNumber = require('../utils/get-group-number.js')
@@ -125,19 +126,35 @@ const sortDecorators = createEslintRule.createEslintRule({
125
126
  },
126
127
  PropertyDefinition: propertyDefinition =>
127
128
  options.sortOnProperties
128
- ? sortDecorators$1(context, options, propertyDefinition.decorators)
129
+ ? sortDecorators$1(
130
+ context,
131
+ options,
132
+ getNodeDecorators.getNodeDecorators(propertyDefinition),
133
+ )
129
134
  : null,
130
135
  AccessorProperty: accessorDefinition =>
131
136
  options.sortOnAccessors
132
- ? sortDecorators$1(context, options, accessorDefinition.decorators)
137
+ ? sortDecorators$1(
138
+ context,
139
+ options,
140
+ getNodeDecorators.getNodeDecorators(accessorDefinition),
141
+ )
133
142
  : null,
134
143
  MethodDefinition: methodDefinition =>
135
144
  options.sortOnMethods
136
- ? sortDecorators$1(context, options, methodDefinition.decorators)
145
+ ? sortDecorators$1(
146
+ context,
147
+ options,
148
+ getNodeDecorators.getNodeDecorators(methodDefinition),
149
+ )
137
150
  : null,
138
- ClassDeclaration: Declaration =>
151
+ ClassDeclaration: declaration =>
139
152
  options.sortOnClasses
140
- ? sortDecorators$1(context, options, Declaration.decorators)
153
+ ? sortDecorators$1(
154
+ context,
155
+ options,
156
+ getNodeDecorators.getNodeDecorators(declaration),
157
+ )
141
158
  : null,
142
159
  }
143
160
  },
@@ -7,6 +7,7 @@ const isPartitionComment = require('../utils/is-partition-comment.js')
7
7
  const getCommentsBefore = require('../utils/get-comments-before.js')
8
8
  const createEslintRule = require('../utils/create-eslint-rule.js')
9
9
  const getLinesBetween = require('../utils/get-lines-between.js')
10
+ const getEnumMembers = require('../utils/get-enum-members.js')
10
11
  const getSourceCode = require('../utils/get-source-code.js')
11
12
  const toSingleLine = require('../utils/to-single-line.js')
12
13
  const rangeToDiff = require('../utils/range-to-diff.js')
@@ -29,8 +30,8 @@ let defaultOptions = {
29
30
  }
30
31
  const sortEnums = createEslintRule.createEslintRule({
31
32
  create: context => ({
32
- TSEnumDeclaration: node => {
33
- let members = node.body.members ?? node.members ?? []
33
+ TSEnumDeclaration: enumDeclaration => {
34
+ let members = getEnumMembers.getEnumMembers(enumDeclaration)
34
35
  if (
35
36
  !isSortable.isSortable(members) ||
36
37
  !members.every(({ initializer }) => initializer)
@@ -81,11 +82,17 @@ const sortEnums = createEslintRule.createEslintRule({
81
82
  var _a
82
83
  let dependencies = []
83
84
  if (member.initializer) {
84
- dependencies = extractDependencies(member.initializer, node.id.name)
85
+ dependencies = extractDependencies(
86
+ member.initializer,
87
+ enumDeclaration.id.name,
88
+ )
85
89
  }
86
90
  let lastSortingNode =
87
91
  (_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1)
88
92
  let sortingNode = {
93
+ numericValue: member.initializer
94
+ ? getExpressionNumberValue(member.initializer)
95
+ : null,
89
96
  name:
90
97
  member.id.type === 'Literal'
91
98
  ? `${member.id.value}`
@@ -119,21 +126,22 @@ const sortEnums = createEslintRule.createEslintRule({
119
126
  },
120
127
  [[]],
121
128
  )
122
- let isNumericEnum = members.every(member => {
123
- var _a
124
- return (
125
- ((_a = member.initializer) == null ? void 0 : _a.type) ===
126
- 'Literal' && typeof member.initializer.value === 'number'
127
- )
128
- })
129
+ let sortingNodes = formattedMembers.flat()
130
+ let isNumericEnum = sortingNodes.every(
131
+ sortingNode =>
132
+ sortingNode.numericValue !== null &&
133
+ !Number.isNaN(sortingNode.numericValue),
134
+ )
129
135
  let compareOptions = {
130
136
  // Get the enum value rather than the name if needed
131
137
  nodeValueGetter:
132
138
  options.sortByValue || (isNumericEnum && options.forceNumericSort)
133
139
  ? sortingNode => {
134
140
  var _a, _b
141
+ if (isNumericEnum) {
142
+ return sortingNode.numericValue.toString()
143
+ }
135
144
  if (
136
- sortingNode.node.type === 'TSEnumMember' &&
137
145
  ((_a = sortingNode.node.initializer) == null
138
146
  ? void 0
139
147
  : _a.type) === 'Literal'
@@ -159,8 +167,8 @@ const sortEnums = createEslintRule.createEslintRule({
159
167
  }
160
168
  let sortNodesIgnoringEslintDisabledNodes = ignoreEslintDisabledNodes =>
161
169
  sortNodesByDependencies.sortNodesByDependencies(
162
- formattedMembers.flatMap(nodes2 =>
163
- sortNodes.sortNodes(nodes2, compareOptions, {
170
+ formattedMembers.flatMap(nodes =>
171
+ sortNodes.sortNodes(nodes, compareOptions, {
164
172
  ignoreEslintDisabledNodes,
165
173
  }),
166
174
  ),
@@ -171,8 +179,7 @@ const sortEnums = createEslintRule.createEslintRule({
171
179
  let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
172
180
  let sortedNodesExcludingEslintDisabled =
173
181
  sortNodesIgnoringEslintDisabledNodes(true)
174
- let nodes = formattedMembers.flat()
175
- pairwise.pairwise(nodes, (left, right) => {
182
+ pairwise.pairwise(sortingNodes, (left, right) => {
176
183
  let indexOfLeft = sortedNodes.indexOf(left)
177
184
  let indexOfRight = sortedNodes.indexOf(right)
178
185
  let indexOfRightExcludingEslintDisabled =
@@ -184,15 +191,18 @@ const sortEnums = createEslintRule.createEslintRule({
184
191
  return
185
192
  }
186
193
  let firstUnorderedNodeDependentOnRight =
187
- sortNodesByDependencies.getFirstUnorderedNodeDependentOn(right, nodes)
194
+ sortNodesByDependencies.getFirstUnorderedNodeDependentOn(
195
+ right,
196
+ sortingNodes,
197
+ )
188
198
  context.report({
189
199
  fix: fixer =>
190
200
  makeFixes.makeFixes({
191
201
  sortedNodes: sortedNodesExcludingEslintDisabled,
202
+ nodes: sortingNodes,
192
203
  sourceCode,
193
204
  options,
194
205
  fixer,
195
- nodes,
196
206
  }),
197
207
  data: {
198
208
  nodeDependentOnRight:
@@ -255,4 +265,72 @@ const sortEnums = createEslintRule.createEslintRule({
255
265
  defaultOptions: [defaultOptions],
256
266
  name: 'sort-enums',
257
267
  })
268
+ let getExpressionNumberValue = expression => {
269
+ switch (expression.type) {
270
+ case 'BinaryExpression':
271
+ return getBinaryExpressionNumberValue(
272
+ expression.left,
273
+ expression.right,
274
+ expression.operator,
275
+ )
276
+ case 'UnaryExpression':
277
+ return getUnaryExpressionNumberValue(
278
+ expression.argument,
279
+ expression.operator,
280
+ )
281
+ case 'Literal':
282
+ return typeof expression.value === 'number'
283
+ ? expression.value
284
+ : Number.NaN
285
+ default:
286
+ return Number.NaN
287
+ }
288
+ }
289
+ let getUnaryExpressionNumberValue = (argumentExpression, operator) => {
290
+ let argument = getExpressionNumberValue(argumentExpression)
291
+ switch (operator) {
292
+ case '+':
293
+ return argument
294
+ case '-':
295
+ return -argument
296
+ case '~':
297
+ return ~argument
298
+ default:
299
+ return Number.NaN
300
+ }
301
+ }
302
+ let getBinaryExpressionNumberValue = (
303
+ leftExpression,
304
+ rightExpression,
305
+ operator,
306
+ ) => {
307
+ let left = getExpressionNumberValue(leftExpression)
308
+ let right = getExpressionNumberValue(rightExpression)
309
+ switch (operator) {
310
+ case '**':
311
+ return left ** right
312
+ case '>>':
313
+ return left >> right
314
+ case '<<':
315
+ return left << right
316
+ case '+':
317
+ return left + right
318
+ case '-':
319
+ return left - right
320
+ case '*':
321
+ return left * right
322
+ case '/':
323
+ return left / right
324
+ case '%':
325
+ return left % right
326
+ case '|':
327
+ return left | right
328
+ case '&':
329
+ return left & right
330
+ case '^':
331
+ return left ^ right
332
+ default:
333
+ return Number.NaN
334
+ }
335
+ }
258
336
  module.exports = sortEnums
@@ -78,7 +78,7 @@ const sortHeritageClauses = createEslintRule.createEslintRule({
78
78
  name: 'sort-heritage-clauses',
79
79
  })
80
80
  let sortHeritageClauses$1 = (context, options, heritageClauses) => {
81
- if (!isSortable.isSortable(heritageClauses)) {
81
+ if (!heritageClauses || !isSortable.isSortable(heritageClauses)) {
82
82
  return
83
83
  }
84
84
  let sourceCode = getSourceCode.getSourceCode(context)
@@ -14,9 +14,11 @@ const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
14
14
  const getNewlinesErrors = require('../utils/get-newlines-errors.js')
15
15
  const makeNewlinesFixes = require('../utils/make-newlines-fixes.js')
16
16
  const getCommentsBefore = require('../utils/get-comments-before.js')
17
+ const getNodeDecorators = require('../utils/get-node-decorators.js')
17
18
  const createEslintRule = require('../utils/create-eslint-rule.js')
18
19
  const getLinesBetween = require('../utils/get-lines-between.js')
19
20
  const getGroupNumber = require('../utils/get-group-number.js')
21
+ const getEnumMembers = require('../utils/get-enum-members.js')
20
22
  const getSourceCode = require('../utils/get-source-code.js')
21
23
  const toSingleLine = require('../utils/to-single-line.js')
22
24
  const rangeToDiff = require('../utils/range-to-diff.js')
@@ -239,16 +241,19 @@ let analyzeModule = ({
239
241
  ;({ name } = nodeToParse.id)
240
242
  dependencies = [
241
243
  ...dependencies,
242
- ...extractDependencies(nodeToParse.body),
244
+ ...getEnumMembers
245
+ .getEnumMembers(nodeToParse)
246
+ .flatMap(extractDependencies),
243
247
  ]
244
248
  break
245
249
  case utils.AST_NODE_TYPES.ClassDeclaration:
246
250
  selector = 'class'
247
251
  name = (_b2 = nodeToParse.id) == null ? void 0 : _b2.name
248
- if (nodeToParse.decorators.length > 0) {
252
+ let nodeDecorators = getNodeDecorators.getNodeDecorators(nodeToParse)
253
+ if (nodeDecorators.length > 0) {
249
254
  modifiers.push('decorated')
250
255
  }
251
- for (let decorator of nodeToParse.decorators) {
256
+ for (let decorator of nodeDecorators) {
252
257
  if (decorator.expression.type === 'Identifier') {
253
258
  decorators.push(decorator.expression.name)
254
259
  } else if (
@@ -493,9 +498,6 @@ let extractDependencies = expression => {
493
498
  if ('right' in nodeValue) {
494
499
  checkNode(nodeValue.right)
495
500
  }
496
- if ('members' in nodeValue) {
497
- traverseNode(nodeValue.members)
498
- }
499
501
  if ('initializer' in nodeValue && nodeValue.initializer) {
500
502
  checkNode(nodeValue.initializer)
501
503
  }
@@ -20,6 +20,7 @@ const getSettings = require('../utils/get-settings.js')
20
20
  const isSortable = require('../utils/is-sortable.js')
21
21
  const useGroups = require('../utils/use-groups.js')
22
22
  const makeFixes = require('../utils/make-fixes.js')
23
+ const sortNodes = require('../utils/sort-nodes.js')
23
24
  const complete = require('../utils/complete.js')
24
25
  const pairwise = require('../utils/pairwise.js')
25
26
  const matches = require('../utils/matches.js')
@@ -28,6 +29,8 @@ let defaultOptions = {
28
29
  partitionByComment: false,
29
30
  newlinesBetween: 'ignore',
30
31
  specialCharacters: 'keep',
32
+ destructuredObjects: true,
33
+ objectDeclarations: true,
31
34
  styledComponents: true,
32
35
  destructureOnly: false,
33
36
  type: 'alphabetical',
@@ -40,7 +43,10 @@ let defaultOptions = {
40
43
  }
41
44
  const sortObjects = createEslintRule.createEslintRule({
42
45
  create: context => {
43
- let sortObject = node => {
46
+ let sortObject = nodeObject => {
47
+ if (!isSortable.isSortable(nodeObject.properties)) {
48
+ return
49
+ }
44
50
  let settings = getSettings.getSettings(context.settings)
45
51
  let options = complete.complete(
46
52
  context.options.at(0),
@@ -55,12 +61,16 @@ const sortObjects = createEslintRule.createEslintRule({
55
61
  validateNewlinesAndPartitionConfiguration.validateNewlinesAndPartitionConfiguration(
56
62
  options,
57
63
  )
58
- let shouldIgnore = false
59
- if (options.destructureOnly) {
60
- shouldIgnore = node.type !== 'ObjectPattern'
64
+ let isDestructuredObject = nodeObject.type === 'ObjectPattern'
65
+ if (isDestructuredObject) {
66
+ if (!options.destructuredObjects) {
67
+ return
68
+ }
69
+ } else if (options.destructureOnly || !options.objectDeclarations) {
70
+ return
61
71
  }
62
- if (!shouldIgnore && options.ignorePattern.length) {
63
- let variableParent = getNodeParent.getNodeParent(node, [
72
+ if (options.ignorePattern.length) {
73
+ let variableParent = getNodeParent.getNodeParent(nodeObject, [
64
74
  'VariableDeclarator',
65
75
  'Property',
66
76
  ])
@@ -83,21 +93,20 @@ const sortObjects = createEslintRule.createEslintRule({
83
93
  typeof variableIdentifier === 'string' &&
84
94
  checkMatch(variableIdentifier)
85
95
  ) {
86
- shouldIgnore = true
96
+ return
87
97
  }
88
- let callParent = getNodeParent.getNodeParent(node, ['CallExpression'])
98
+ let callParent = getNodeParent.getNodeParent(nodeObject, [
99
+ 'CallExpression',
100
+ ])
89
101
  let callIdentifier =
90
102
  (callParent == null ? void 0 : callParent.type) ===
91
103
  'CallExpression' && callParent.callee.type === 'Identifier'
92
104
  ? callParent.callee.name
93
105
  : null
94
106
  if (callIdentifier && checkMatch(callIdentifier)) {
95
- shouldIgnore = true
107
+ return
96
108
  }
97
109
  }
98
- if (shouldIgnore || !isSortable.isSortable(node.properties)) {
99
- return
100
- }
101
110
  let isStyledCallExpression = identifier =>
102
111
  identifier.type === 'Identifier' && identifier.name === 'styled'
103
112
  let isCssCallExpression = identifier =>
@@ -115,9 +124,9 @@ const sortObjects = createEslintRule.createEslintRule({
115
124
  styledNode.parent.name.name === 'style'))
116
125
  if (
117
126
  !options.styledComponents &&
118
- (isStyledComponents(node.parent) ||
119
- (node.parent.type === 'ArrowFunctionExpression' &&
120
- isStyledComponents(node.parent.parent)))
127
+ (isStyledComponents(nodeObject.parent) ||
128
+ (nodeObject.parent.type === 'ArrowFunctionExpression' &&
129
+ isStyledComponents(nodeObject.parent.parent)))
121
130
  ) {
122
131
  return
123
132
  }
@@ -271,11 +280,17 @@ const sortObjects = createEslintRule.createEslintRule({
271
280
  },
272
281
  [[]],
273
282
  )
274
- let formattedMembers = formatProperties(node.properties)
283
+ let formattedMembers = formatProperties(nodeObject.properties)
284
+ let nodesSortingFunction =
285
+ isDestructuredObject &&
286
+ typeof options.destructuredObjects === 'object' &&
287
+ !options.destructuredObjects.groups
288
+ ? sortNodes.sortNodes
289
+ : sortNodesByGroups.sortNodesByGroups
275
290
  let sortNodesIgnoringEslintDisabledNodes = ignoreEslintDisabledNodes =>
276
291
  sortNodesByDependencies.sortNodesByDependencies(
277
292
  formattedMembers.flatMap(nodes2 =>
278
- sortNodesByGroups.sortNodesByGroups(nodes2, options, {
293
+ nodesSortingFunction(nodes2, options, {
279
294
  ignoreEslintDisabledNodes,
280
295
  }),
281
296
  ),
@@ -371,6 +386,25 @@ const sortObjects = createEslintRule.createEslintRule({
371
386
  schema: [
372
387
  {
373
388
  properties: {
389
+ destructuredObjects: {
390
+ oneOf: [
391
+ {
392
+ type: 'boolean',
393
+ },
394
+ {
395
+ properties: {
396
+ groups: {
397
+ description:
398
+ 'Controls whether to use groups to sort destructured objects.',
399
+ type: 'boolean',
400
+ },
401
+ },
402
+ additionalProperties: false,
403
+ type: 'object',
404
+ },
405
+ ],
406
+ description: 'Controls whether to sort destructured objects.',
407
+ },
374
408
  ignorePattern: {
375
409
  description:
376
410
  'Specifies names or patterns for nodes that should be ignored by rule.',
@@ -388,6 +422,10 @@ const sortObjects = createEslintRule.createEslintRule({
388
422
  description: 'Controls whether to sort only destructured objects.',
389
423
  type: 'boolean',
390
424
  },
425
+ objectDeclarations: {
426
+ description: 'Controls whether to sort object declarations.',
427
+ type: 'boolean',
428
+ },
391
429
  styledComponents: {
392
430
  description: 'Controls whether to sort styled components.',
393
431
  type: 'boolean',
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
3
+ let getEnumMembers = value => {
4
+ var _a
5
+ return ((_a = value.body) == null ? void 0 : _a.members) ?? value.members
6
+ }
7
+ exports.getEnumMembers = getEnumMembers
@@ -0,0 +1,4 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
3
+ let getNodeDecorators = node => node.decorators ?? []
4
+ exports.getNodeDecorators = getNodeDecorators
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-perfectionist",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "ESLint plugin for sorting various data such as objects, imports, types, enums, JSX props, etc.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -23,8 +23,8 @@
23
23
  "./dist"
24
24
  ],
25
25
  "dependencies": {
26
- "@typescript-eslint/types": "^8.15.0",
27
- "@typescript-eslint/utils": "^8.15.0",
26
+ "@typescript-eslint/types": "^8.16.0",
27
+ "@typescript-eslint/utils": "^8.16.0",
28
28
  "natural-orderby": "^5.0.0"
29
29
  },
30
30
  "peerDependencies": {