Skip to content

Commit

Permalink
feat(sort-enums): add partition-by-comment option
Browse files Browse the repository at this point in the history
  • Loading branch information
chirokas authored Mar 13, 2024
1 parent 40b1a49 commit ec3d11c
Show file tree
Hide file tree
Showing 3 changed files with 523 additions and 28 deletions.
9 changes: 9 additions & 0 deletions docs/rules/sort-enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ interface Options {
type?: 'alphabetical' | 'natural' | 'line-length'
order?: 'asc' | 'desc'
'ignore-case'?: boolean
'partition-by-comment'?: string[] | string | boolean
}
```

Expand All @@ -95,6 +96,14 @@ interface Options {

Only affects alphabetical and natural sorting. When `true` the rule ignores the case-sensitivity of the order.

### partition-by-comment

<sub>(default: `false`)</sub>

You can set comments that would separate the members of enums into logical parts. If set to `true`, all enum member comments will be treated as delimiters.

The [minimatch](https://github.com/isaacs/minimatch) library is used for pattern matching.

## ⚙️ Usage

::: code-group
Expand Down
88 changes: 60 additions & 28 deletions rules/sort-enums.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { SortingNode } from '../typings'
import type { PartitionComment, SortingNode } from '../typings'

import { isPartitionComment } from '../utils/is-partition-comment'
import { createEslintRule } from '../utils/create-eslint-rule'
import { getCommentBefore } from '../utils/get-comment-before'
import { toSingleLine } from '../utils/to-single-line'
import { rangeToDiff } from '../utils/range-to-diff'
import { isPositive } from '../utils/is-positive'
Expand All @@ -15,6 +17,7 @@ type MESSAGE_ID = 'unexpectedEnumsOrder'

type Options = [
Partial<{
'partition-by-comment': PartitionComment
'ignore-case': boolean
order: SortOrder
type: SortType
Expand All @@ -35,6 +38,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
{
type: 'object',
properties: {
'partition-by-comment': {
default: false,
type: ['boolean', 'string', 'array'],
},
type: {
enum: [
SortType.alphabetical,
Expand Down Expand Up @@ -77,36 +84,61 @@ export default createEslintRule<Options, MESSAGE_ID>({
type: SortType.alphabetical,
order: SortOrder.asc,
'ignore-case': false,
'partition-by-comment': false,
})

let nodes: SortingNode[] = node.members.map(member => ({
name:
member.id.type === 'Literal'
? `${member.id.value}`
: `${context.sourceCode.text.slice(...member.id.range)}`,
size: rangeToDiff(member.range),
node: member,
}))
let partitionComment = options['partition-by-comment']

pairwise(nodes, (left, right) => {
if (isPositive(compare(left, right, options))) {
context.report({
messageId: 'unexpectedEnumsOrder',
data: {
left: toSingleLine(left.name),
right: toSingleLine(right.name),
},
node: right.node,
fix: fixer =>
makeFixes(
fixer,
nodes,
sortNodes(nodes, options),
context.sourceCode,
),
})
}
})
let formattedMembers: SortingNode[][] = node.members.reduce(
(accumulator: SortingNode[][], member) => {
let comment = getCommentBefore(member, context.sourceCode)

if (
partitionComment &&
comment &&
isPartitionComment(partitionComment, comment.value)
) {
accumulator.push([])
}

let name =
member.id.type === 'Literal'
? `${member.id.value}`
: `${context.sourceCode.text.slice(...member.id.range)}`

let sortingNode = {
name,
node: member,
size: rangeToDiff(member.range),
}
accumulator.at(-1)!.push(sortingNode)
return accumulator
},
[[]],
)

for (let nodes of formattedMembers) {
pairwise(nodes, (left, right) => {
if (isPositive(compare(left, right, options))) {
context.report({
messageId: 'unexpectedEnumsOrder',
data: {
left: toSingleLine(left.name),
right: toSingleLine(right.name),
},
node: right.node,
fix: fixer =>
makeFixes(
fixer,
nodes,
sortNodes(nodes, options),
context.sourceCode,
{ partitionComment },
),
})
}
})
}
}
},
}),
Expand Down
Loading

0 comments on commit ec3d11c

Please sign in to comment.