Skip to content

Commit 1f454d9

Browse files
hugop95azat-io
authored andcommittedNov 19, 2024
feat(sort-objects): add multiline and method groups
1 parent 5557198 commit 1f454d9

File tree

3 files changed

+71
-40
lines changed

3 files changed

+71
-40
lines changed
 

‎docs/content/rules/sort-objects.mdx

+15-11
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ Allows you to specify a list of object keys groups for sorting. Groups help orga
260260

261261
Predefined groups:
262262

263+
- `'multiline'` — Properties with multiline definitions, such as methods or complex type declarations.
264+
- `'method'` - Members that are methods.
263265
- `'unknown'` — Properties that don’t fit into any group specified in the `groups` option.
264266

265267
If the `unknown` group is not specified in the `groups` option, it will automatically be added to the end of the list.
@@ -293,17 +295,18 @@ Custom group matching takes precedence over predefined group matching.
293295
#### Example
294296

295297
Put all properties starting with `id` and `name` at the top, put metadata at the bottom.
296-
Anything else is put in the middle.
298+
Regroup multiline and in the middle, above unknown-matched properties.
297299

298300
```ts
299301
const user = {
300302
id: 'id', // top
301303
name: 'John', // top
302-
age: 40, // unknown
303-
isAdmin: false, // unknown
304-
localization: { // unknown
304+
getEmail: () => null, // method
305+
localization: { // multiline
305306
// Stuff about localization
306307
},
308+
age: 40, // unknown
309+
isAdmin: false, // unknown
307310
lastUpdated_metadata: null, // bottom
308311
version_metadata: '1' // bottom
309312
}
@@ -314,14 +317,15 @@ const user = {
314317
```js
315318
{
316319
groups: [
317-
+ 'top', // [!code ++]
318-
'unknown',
319-
'bottom' // [!code ++]
320+
+ 'top', // [!code ++]
321+
['multiline', 'method'], // [!code ++]
322+
['unknown'], // [!code ++]
323+
'bottom' // [!code ++]
320324
],
321-
+ customGroups: { // [!code ++]
322-
+ top: ['id', 'name'] // [!code ++]
323-
+ bottom: '*_metadata' // [!code ++]
324-
+ } // [!code ++]
325+
+ customGroups: { // [!code ++]
326+
+ top: ['id', 'name'] // [!code ++]
327+
+ bottom: '*_metadata' // [!code ++]
328+
+ } // [!code ++]
325329
}
326330
```
327331

‎rules/sort-objects.ts

+27-29
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,7 @@ type MESSAGE_ID =
3030
| 'unexpectedObjectsGroupOrder'
3131
| 'unexpectedObjectsOrder'
3232

33-
export enum Position {
34-
'exception' = 'exception',
35-
'ignore' = 'ignore',
36-
}
37-
38-
type Group = 'unknown' | string
39-
type SortingNodeWithPosition = SortingNodeWithDependencies & {
40-
position: Position
41-
}
33+
type Group = 'multiline' | 'unknown' | 'method' | string
4234

4335
type Options = [
4436
Partial<{
@@ -220,7 +212,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
220212

221213
validateGroupsConfiguration(
222214
options.groups,
223-
['unknown'],
215+
['multiline', 'method', 'unknown'],
224216
Object.keys(options.customGroups),
225217
)
226218

@@ -383,9 +375,9 @@ export default createEslintRule<Options, MESSAGE_ID>({
383375
| TSESTree.RestElement
384376
| TSESTree.Property
385377
)[],
386-
): SortingNodeWithPosition[][] =>
378+
): SortingNodeWithDependencies[][] =>
387379
props.reduce(
388-
(accumulator: SortingNodeWithPosition[][], prop) => {
380+
(accumulator: SortingNodeWithDependencies[][], prop) => {
389381
if (
390382
prop.type === 'SpreadElement' ||
391383
prop.type === 'RestElement'
@@ -409,10 +401,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
409401
}
410402

411403
let name: string
412-
let position: Position = Position.ignore
413404
let dependencies: string[] = []
414405

415-
let { getGroup, setCustomGroups } = useGroups(options)
406+
let { getGroup, defineGroup, setCustomGroups } =
407+
useGroups(options)
416408

417409
if (prop.key.type === 'Identifier') {
418410
;({ name } = prop.key)
@@ -422,9 +414,28 @@ export default createEslintRule<Options, MESSAGE_ID>({
422414
name = sourceCode.text.slice(...prop.key.range)
423415
}
424416

425-
let propSortingNode = {
417+
if (prop.value.type === 'AssignmentPattern') {
418+
dependencies = extractDependencies(prop.value)
419+
}
420+
421+
setCustomGroups(options.customGroups, name)
422+
423+
if (
424+
prop.value.type === 'ArrowFunctionExpression' ||
425+
prop.value.type === 'FunctionExpression'
426+
) {
427+
defineGroup('method')
428+
}
429+
430+
if (prop.loc.start.line !== prop.loc.end.line) {
431+
defineGroup('multiline')
432+
}
433+
434+
let propSortingNode: SortingNodeWithDependencies = {
426435
size: rangeToDiff(prop.range),
427436
node: prop,
437+
group: getGroup(),
438+
dependencies,
428439
name,
429440
}
430441

@@ -436,20 +447,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
436447
accumulator.push([])
437448
}
438449

439-
if (prop.value.type === 'AssignmentPattern') {
440-
dependencies = extractDependencies(prop.value)
441-
}
442-
443-
setCustomGroups(options.customGroups, name)
444-
445-
let value = {
446-
...propSortingNode,
447-
group: getGroup(),
448-
dependencies,
449-
position,
450-
}
451-
452-
accumulator.at(-1)!.push(value)
450+
accumulator.at(-1)!.push(propSortingNode)
453451

454452
return accumulator
455453
},

‎test/sort-objects.test.ts

+29
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,35 @@ describe(ruleName, () => {
16171617
invalid: [],
16181618
},
16191619
)
1620+
1621+
ruleTester.run(
1622+
`${ruleName}(${type}): allows to set groups for sorting`,
1623+
rule,
1624+
{
1625+
valid: [
1626+
{
1627+
code: dedent`
1628+
let obj = {
1629+
z: {
1630+
// Some multiline stuff
1631+
},
1632+
f: 'a',
1633+
a1: () => {},
1634+
a2: function() {},
1635+
a3() {},
1636+
}
1637+
`,
1638+
options: [
1639+
{
1640+
...options,
1641+
groups: ['multiline', 'unknown', 'method'],
1642+
},
1643+
],
1644+
},
1645+
],
1646+
invalid: [],
1647+
},
1648+
)
16201649
})
16211650

16221651
describe(`${ruleName}: sorting by natural order`, () => {

0 commit comments

Comments
 (0)
Please sign in to comment.