Skip to content

Commit 9cbace4

Browse files
committed
feat: todo
1 parent 51922cb commit 9cbace4

30 files changed

+1064
-1802
lines changed

rules/sort-enums.ts

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import type { TSESTree } from '@typescript-eslint/types'
22

3-
import type { NodeValueGetterFunction } from '../utils/compare/compare'
43
import type { SortEnumsSortingNode, Options } from './sort-enums/types'
5-
import type { TypeOption } from '../types/common-options'
64

75
import {
86
buildCustomGroupsArrayJsonSchema,
@@ -20,13 +18,13 @@ import {
2018
ORDER_ERROR,
2119
} from '../utils/report-errors'
2220
import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
23-
import { getCustomGroupOverriddenOptions } from '../utils/build-default-options-by-group-index-computer'
21+
import { buildDefaultOptionsByGroupIndexComputer } from '../utils/build-default-options-by-group-index-computer'
22+
import { buildComparatorByOptionsComputer } from './sort-enums/build-comparator-by-options-computer'
2423
import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
2524
import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
2625
import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
2726
import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
2827
import { doesCustomGroupMatch } from '../utils/does-custom-group-match'
29-
import { UnreachableCaseError } from '../utils/unreachable-case-error'
3028
import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
3129
import { singleCustomGroupJsonSchema } from './sort-enums/types'
3230
import { createEslintRule } from '../utils/create-eslint-rule'
@@ -198,29 +196,15 @@ export default createEslintRule<Options, MessageId>({
198196
sortingNode => sortingNode.numericValue !== null,
199197
)
200198

201-
let nodeValueGetter = computeNodeValueGetter({
202-
isNumericEnum,
203-
options,
204-
})
205-
let overriddenOptions = {
206-
...options,
207-
type: computeOptionType({
208-
isNumericEnum,
209-
options,
210-
}),
211-
}
212199
function sortNodesExcludingEslintDisabled(
213200
ignoreEslintDisabledNodes: boolean,
214201
): SortEnumsSortingNode[] {
215202
let nodesSortedByGroups = formattedMembers.flatMap(sortingNodes =>
216203
sortNodesByGroups({
217-
optionsByGroupIndexComputer: groupIndex => ({
218-
options: getCustomGroupOverriddenOptions({
219-
options: overriddenOptions,
220-
groupIndex,
221-
}),
222-
nodeValueGetter,
223-
}),
204+
optionsByGroupIndexComputer:
205+
buildDefaultOptionsByGroupIndexComputer(options),
206+
comparatorByOptionsComputer:
207+
buildComparatorByOptionsComputer(isNumericEnum),
224208
ignoreEslintDisabledNodes,
225209
groups: options.groups,
226210
nodes: sortingNodes,
@@ -329,35 +313,6 @@ function getBinaryExpressionNumberValue(
329313
}
330314
}
331315

332-
function computeNodeValueGetter({
333-
isNumericEnum,
334-
options,
335-
}: {
336-
options: Pick<Required<Options[number]>, 'sortByValue'>
337-
isNumericEnum: boolean
338-
}): NodeValueGetterFunction<SortEnumsSortingNode> | null {
339-
switch (options.sortByValue) {
340-
case 'ifNumericEnum':
341-
if (!isNumericEnum) {
342-
return null
343-
}
344-
break
345-
case 'always':
346-
break
347-
case 'never':
348-
return null
349-
/* v8 ignore next 2 */
350-
default:
351-
throw new UnreachableCaseError(options.sortByValue)
352-
}
353-
return sortingNode => {
354-
if (isNumericEnum) {
355-
return sortingNode.numericValue!.toString()
356-
}
357-
return sortingNode.value ?? ''
358-
}
359-
}
360-
361316
function getExpressionNumberValue(expression: TSESTree.Node): number | null {
362317
switch (expression.type) {
363318
case 'BinaryExpression':
@@ -398,23 +353,3 @@ function getUnaryExpressionNumberValue(
398353
return null
399354
}
400355
}
401-
402-
function computeOptionType({
403-
isNumericEnum,
404-
options,
405-
}: {
406-
options: Pick<Required<Options[number]>, 'sortByValue' | 'type'>
407-
isNumericEnum: boolean
408-
}): TypeOption {
409-
/**
410-
* If the enum is numeric, and we sort by value, always use the `natural` sort
411-
* type, which will correctly sort them.
412-
*/
413-
if (!isNumericEnum) {
414-
return options.type
415-
}
416-
if (options.sortByValue === 'never') {
417-
return options.type
418-
}
419-
return 'natural'
420-
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import type { ComparatorByOptionsComputer } from '../../utils/compare/default-comparator-by-options-computer'
2+
import type { SortEnumsSortingNode, Options } from './types'
3+
4+
import { defaultComparatorByOptionsComputer } from '../../utils/compare/default-comparator-by-options-computer'
5+
import { compareAlphabetically } from '../../utils/compare/compare-alphabetically'
6+
import { compareByCustomSort } from '../../utils/compare/compare-by-custom-sort'
7+
import { compareByLineLength } from '../../utils/compare/compare-by-line-length'
8+
import { computeNaturalSort } from '../../utils/compare/compute-natural-sort'
9+
import { unsortedComparator } from '../../utils/compare/unsorted-comparator'
10+
import { UnreachableCaseError } from '../../utils/unreachable-case-error'
11+
12+
export function buildComparatorByOptionsComputer(
13+
isNumericEnum: boolean,
14+
): ComparatorByOptionsComputer<
15+
Required<Options[number]>,
16+
SortEnumsSortingNode
17+
> {
18+
return options => {
19+
switch (options.sortByValue) {
20+
case 'ifNumericEnum':
21+
if (isNumericEnum) {
22+
return byNumericValueComparatorComputer(options)
23+
}
24+
return defaultComparatorByOptionsComputer(options)
25+
case 'always':
26+
if (isNumericEnum) {
27+
return byNumericValueComparatorComputer(options)
28+
}
29+
return byNonNumericValueComparatorComputer(options)
30+
case 'never':
31+
return defaultComparatorByOptionsComputer(options)
32+
default: {
33+
throw new UnreachableCaseError(options.sortByValue)
34+
}
35+
}
36+
}
37+
}
38+
39+
let byNonNumericValueComparatorComputer: ComparatorByOptionsComputer<
40+
Required<Options[number]>,
41+
SortEnumsSortingNode
42+
> = options => {
43+
switch (options.type) {
44+
case 'alphabetical':
45+
return (a, b) =>
46+
compareAlphabetically(
47+
a.value?.toString() ?? '',
48+
b.value?.toString() ?? '',
49+
options,
50+
)
51+
case 'line-length':
52+
return (a, b) => compareByLineLength(a, b, options)
53+
case 'unsorted':
54+
return unsortedComparator
55+
case 'natural':
56+
return (a, b) =>
57+
computeNaturalSort(
58+
a.value?.toString() ?? '',
59+
b.value?.toString() ?? '',
60+
options,
61+
)
62+
case 'custom':
63+
return (a, b) =>
64+
compareByCustomSort(a.value ?? '', b.value ?? '', options)
65+
default:
66+
throw new UnreachableCaseError(options.type)
67+
}
68+
}
69+
70+
let byNumericValueComparatorComputer: ComparatorByOptionsComputer<
71+
Required<Options[number]>,
72+
SortEnumsSortingNode
73+
> = options => {
74+
switch (options.type) {
75+
case 'alphabetical':
76+
case 'line-length':
77+
case 'natural':
78+
case 'custom':
79+
return (a, b) =>
80+
computeNaturalSort(
81+
a.numericValue!.toString(),
82+
b.numericValue!.toString(),
83+
options,
84+
)
85+
case 'unsorted':
86+
return unsortedComparator
87+
default:
88+
throw new UnreachableCaseError(options.type)
89+
}
90+
}

rules/sort-imports.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,11 @@ export default createEslintRule<Options, MessageId>({
309309
): SortImportsSortingNode[] {
310310
let nodesSortedByGroups = nodeGroups.flatMap(nodes =>
311311
sortNodesByGroups({
312-
isNodeIgnoredForGroup: ({ groupIndex }) => {
312+
isNodeIgnoredForGroup: ({ group }) => {
313313
if (options.sortSideEffects) {
314314
return false
315315
}
316-
return isSideEffectOnlyGroup(options.groups[groupIndex])
316+
return isSideEffectOnlyGroup(group)
317317
},
318318
optionsByGroupIndexComputer:
319319
buildDefaultOptionsByGroupIndexComputer(options),

rules/sort-object-types.ts

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ import {
3636
} from '../utils/report-errors'
3737
import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
3838
import { filterOptionsByDeclarationCommentMatches } from '../utils/filter-options-by-declaration-comment-matches'
39+
import { buildOptionsByGroupIndexComputer } from './sort-object-types/build-options-by-group-index-computer'
3940
import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
40-
import { getCustomGroupsCompareOptions } from './sort-object-types/get-custom-groups-compare-options'
41+
import { comparatorByOptionsComputer } from './sort-object-types/comparator-by-options-computer'
4142
import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
4243
import { filterOptionsByAllNamesMatch } from '../utils/filter-options-by-all-names-match'
4344
import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
@@ -312,21 +313,6 @@ export function sortObjectTypeElements<MessageIds extends string>({
312313
): SortObjectTypesSortingNode[] {
313314
return formattedMembers.flatMap(groupedNodes =>
314315
sortNodesByGroups({
315-
optionsByGroupIndexComputer: groupIndex => {
316-
let {
317-
fallbackSortNodeValueGetter,
318-
options: overriddenOptions,
319-
nodeValueGetter,
320-
} = getCustomGroupsCompareOptions(options, groupIndex)
321-
return {
322-
options: {
323-
...options,
324-
...overriddenOptions,
325-
},
326-
fallbackSortNodeValueGetter,
327-
nodeValueGetter,
328-
}
329-
},
330316
isNodeIgnoredForGroup: ({ groupOptions, node }) => {
331317
switch (groupOptions.sortBy) {
332318
case 'value':
@@ -338,6 +324,8 @@ export function sortObjectTypeElements<MessageIds extends string>({
338324
throw new UnreachableCaseError(groupOptions.sortBy)
339325
}
340326
},
327+
optionsByGroupIndexComputer: buildOptionsByGroupIndexComputer(options),
328+
comparatorByOptionsComputer,
341329
ignoreEslintDisabledNodes,
342330
groups: options.groups,
343331
nodes: groupedNodes,

rules/sort-object-types/build-node-value-getter.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { OptionsByGroupIndexComputer } from '../../utils/sort-nodes-by-groups'
2+
import type { Options } from './types'
3+
4+
import { computeOverriddenOptionsByGroupIndex } from '../../utils/build-default-options-by-group-index-computer'
5+
import { computeGroupName } from '../../utils/compute-group-name'
6+
7+
export function buildOptionsByGroupIndexComputer(
8+
options: Required<Options[number]>,
9+
): OptionsByGroupIndexComputer<Required<Options[number]>> {
10+
return groupIndex => computeOptionsForGroupIndex(options, groupIndex)
11+
}
12+
13+
/**
14+
* Retrieves sorting options for a specific group with object-type-specific
15+
* overrides.
16+
*
17+
* Extends the base custom groups functionality to support 'sortBy' option,
18+
* which determines whether to sort object type members by their key name or
19+
* value. Custom groups can override both the primary sortBy and fallback sortBy
20+
* settings.
21+
*
22+
* @param options - Rule options including custom groups configuration.
23+
* @param groupIndex - Index of the group to get options for.
24+
* @returns Sorting options with appropriate node value getters for the sort
25+
* strategy.
26+
*/
27+
function computeOptionsForGroupIndex(
28+
options: Required<Options[number]>,
29+
groupIndex: number,
30+
): Required<Options[number]> {
31+
let overriddenOptions = computeOverriddenOptionsByGroupIndex(
32+
options,
33+
groupIndex,
34+
)
35+
36+
let { fallbackSort, customGroups, sortBy, groups } = options
37+
let fallbackSortBy = fallbackSort.sortBy
38+
let group = groups[groupIndex]
39+
let groupName = group ? computeGroupName(group) : null
40+
let customGroup = customGroups.find(
41+
currentGroup => groupName === currentGroup.groupName,
42+
)
43+
44+
if (customGroup) {
45+
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
46+
if ('sortBy' in customGroup && customGroup.sortBy) {
47+
;({ sortBy } = customGroup)
48+
}
49+
}
50+
51+
return {
52+
...overriddenOptions,
53+
fallbackSort: {
54+
...overriddenOptions.fallbackSort,
55+
...(fallbackSortBy ? { sortBy: fallbackSortBy } : {}),
56+
},
57+
sortBy,
58+
}
59+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { ComparatorByOptionsComputer } from '../../utils/compare/default-comparator-by-options-computer'
2+
import type { SortObjectTypesSortingNode, Options } from './types'
3+
4+
import { defaultComparatorByOptionsComputer } from '../../utils/compare/default-comparator-by-options-computer'
5+
import { compareAlphabetically } from '../../utils/compare/compare-alphabetically'
6+
import { compareByCustomSort } from '../../utils/compare/compare-by-custom-sort'
7+
import { compareByLineLength } from '../../utils/compare/compare-by-line-length'
8+
import { computeNaturalSort } from '../../utils/compare/compute-natural-sort'
9+
import { unsortedComparator } from '../../utils/compare/unsorted-comparator'
10+
import { UnreachableCaseError } from '../../utils/unreachable-case-error'
11+
12+
export let comparatorByOptionsComputer: ComparatorByOptionsComputer<
13+
Required<Options[number]>,
14+
SortObjectTypesSortingNode
15+
> = options => {
16+
switch (options.sortBy) {
17+
case 'value':
18+
return byValueComparatorComputer(options)
19+
case 'name':
20+
return defaultComparatorByOptionsComputer(options)
21+
default:
22+
throw new UnreachableCaseError(options.sortBy)
23+
}
24+
}
25+
26+
let byValueComparatorComputer: ComparatorByOptionsComputer<
27+
Required<Options[number]>,
28+
SortObjectTypesSortingNode
29+
> = options => {
30+
switch (options.type) {
31+
case 'alphabetical':
32+
return (a, b) =>
33+
compareAlphabetically(a.value ?? '', b.value ?? '', options)
34+
case 'line-length':
35+
return (a, b) => compareByLineLength(a, b, options)
36+
case 'unsorted':
37+
return unsortedComparator
38+
case 'natural':
39+
return (a, b) => computeNaturalSort(a.value ?? '', b.value ?? '', options)
40+
case 'custom':
41+
return (a, b) =>
42+
compareByCustomSort(a.value ?? '', b.value ?? '', options)
43+
default:
44+
throw new UnreachableCaseError(options.type)
45+
}
46+
}

0 commit comments

Comments
 (0)