eslint-plugin-perfectionist 4.0.3 → 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.
@@ -30,8 +30,8 @@ let defaultOptions = {
30
30
  }
31
31
  const sortEnums = createEslintRule.createEslintRule({
32
32
  create: context => ({
33
- TSEnumDeclaration: node => {
34
- let members = getEnumMembers.getEnumMembers(node)
33
+ TSEnumDeclaration: enumDeclaration => {
34
+ let members = getEnumMembers.getEnumMembers(enumDeclaration)
35
35
  if (
36
36
  !isSortable.isSortable(members) ||
37
37
  !members.every(({ initializer }) => initializer)
@@ -82,11 +82,17 @@ const sortEnums = createEslintRule.createEslintRule({
82
82
  var _a
83
83
  let dependencies = []
84
84
  if (member.initializer) {
85
- dependencies = extractDependencies(member.initializer, node.id.name)
85
+ dependencies = extractDependencies(
86
+ member.initializer,
87
+ enumDeclaration.id.name,
88
+ )
86
89
  }
87
90
  let lastSortingNode =
88
91
  (_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1)
89
92
  let sortingNode = {
93
+ numericValue: member.initializer
94
+ ? getExpressionNumberValue(member.initializer)
95
+ : null,
90
96
  name:
91
97
  member.id.type === 'Literal'
92
98
  ? `${member.id.value}`
@@ -120,21 +126,22 @@ const sortEnums = createEslintRule.createEslintRule({
120
126
  },
121
127
  [[]],
122
128
  )
123
- let isNumericEnum = members.every(member => {
124
- var _a
125
- return (
126
- ((_a = member.initializer) == null ? void 0 : _a.type) ===
127
- 'Literal' && typeof member.initializer.value === 'number'
128
- )
129
- })
129
+ let sortingNodes = formattedMembers.flat()
130
+ let isNumericEnum = sortingNodes.every(
131
+ sortingNode =>
132
+ sortingNode.numericValue !== null &&
133
+ !Number.isNaN(sortingNode.numericValue),
134
+ )
130
135
  let compareOptions = {
131
136
  // Get the enum value rather than the name if needed
132
137
  nodeValueGetter:
133
138
  options.sortByValue || (isNumericEnum && options.forceNumericSort)
134
139
  ? sortingNode => {
135
140
  var _a, _b
141
+ if (isNumericEnum) {
142
+ return sortingNode.numericValue.toString()
143
+ }
136
144
  if (
137
- sortingNode.node.type === 'TSEnumMember' &&
138
145
  ((_a = sortingNode.node.initializer) == null
139
146
  ? void 0
140
147
  : _a.type) === 'Literal'
@@ -160,8 +167,8 @@ const sortEnums = createEslintRule.createEslintRule({
160
167
  }
161
168
  let sortNodesIgnoringEslintDisabledNodes = ignoreEslintDisabledNodes =>
162
169
  sortNodesByDependencies.sortNodesByDependencies(
163
- formattedMembers.flatMap(nodes2 =>
164
- sortNodes.sortNodes(nodes2, compareOptions, {
170
+ formattedMembers.flatMap(nodes =>
171
+ sortNodes.sortNodes(nodes, compareOptions, {
165
172
  ignoreEslintDisabledNodes,
166
173
  }),
167
174
  ),
@@ -172,8 +179,7 @@ const sortEnums = createEslintRule.createEslintRule({
172
179
  let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
173
180
  let sortedNodesExcludingEslintDisabled =
174
181
  sortNodesIgnoringEslintDisabledNodes(true)
175
- let nodes = formattedMembers.flat()
176
- pairwise.pairwise(nodes, (left, right) => {
182
+ pairwise.pairwise(sortingNodes, (left, right) => {
177
183
  let indexOfLeft = sortedNodes.indexOf(left)
178
184
  let indexOfRight = sortedNodes.indexOf(right)
179
185
  let indexOfRightExcludingEslintDisabled =
@@ -185,15 +191,18 @@ const sortEnums = createEslintRule.createEslintRule({
185
191
  return
186
192
  }
187
193
  let firstUnorderedNodeDependentOnRight =
188
- sortNodesByDependencies.getFirstUnorderedNodeDependentOn(right, nodes)
194
+ sortNodesByDependencies.getFirstUnorderedNodeDependentOn(
195
+ right,
196
+ sortingNodes,
197
+ )
189
198
  context.report({
190
199
  fix: fixer =>
191
200
  makeFixes.makeFixes({
192
201
  sortedNodes: sortedNodesExcludingEslintDisabled,
202
+ nodes: sortingNodes,
193
203
  sourceCode,
194
204
  options,
195
205
  fixer,
196
- nodes,
197
206
  }),
198
207
  data: {
199
208
  nodeDependentOnRight:
@@ -256,4 +265,72 @@ const sortEnums = createEslintRule.createEslintRule({
256
265
  defaultOptions: [defaultOptions],
257
266
  name: 'sort-enums',
258
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
+ }
259
336
  module.exports = sortEnums
@@ -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',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-perfectionist",
3
- "version": "4.0.3",
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": {