-
Notifications
You must be signed in to change notification settings - Fork 29
/
sort-intersection-types.ts
110 lines (101 loc) 路 2.9 KB
/
sort-intersection-types.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { SortingNode } from '../typings'
import { createEslintRule } from '../utils/create-eslint-rule'
import { toSingleLine } from '../utils/to-single-line'
import { rangeToDiff } from '../utils/range-to-diff'
import { isPositive } from '../utils/is-positive'
import { SortOrder, SortType } from '../typings'
import { sortNodes } from '../utils/sort-nodes'
import { makeFixes } from '../utils/make-fixes'
import { complete } from '../utils/complete'
import { pairwise } from '../utils/pairwise'
import { compare } from '../utils/compare'
type MESSAGE_ID = 'unexpectedIntersectionTypesOrder'
type Options = [
Partial<{
'ignore-case': boolean
order: SortOrder
type: SortType
}>,
]
export const RULE_NAME = 'sort-intersection-types'
export default createEslintRule<Options, MESSAGE_ID>({
name: RULE_NAME,
meta: {
type: 'suggestion',
docs: {
description: 'enforce sorted intersection types',
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
type: {
enum: [
SortType.alphabetical,
SortType.natural,
SortType['line-length'],
],
default: SortType.alphabetical,
type: 'string',
},
order: {
enum: [SortOrder.asc, SortOrder.desc],
default: SortOrder.asc,
type: 'string',
},
'ignore-case': {
type: 'boolean',
default: false,
},
},
additionalProperties: false,
},
],
messages: {
unexpectedIntersectionTypesOrder:
'Expected "{{right}}" to come before "{{left}}"',
},
},
defaultOptions: [
{
type: SortType.alphabetical,
order: SortOrder.asc,
},
],
create: context => ({
TSIntersectionType: node => {
let options = complete(context.options.at(0), {
type: SortType.alphabetical,
'ignore-case': false,
order: SortOrder.asc,
})
let nodes: SortingNode[] = node.types.map(type => ({
group:
type.type === 'TSNullKeyword' || type.type === 'TSUndefinedKeyword'
? 'nullable'
: 'unknown',
name: context.sourceCode.text.slice(...type.range),
size: rangeToDiff(type.range),
node: type,
}))
pairwise(nodes, (left, right) => {
let compareValue = isPositive(compare(left, right, options))
if (compareValue) {
context.report({
messageId: 'unexpectedIntersectionTypesOrder',
data: {
left: toSingleLine(left.name),
right: toSingleLine(right.name),
},
node: right.node,
fix: fixer => {
let sortedNodes = sortNodes(nodes, options)
return makeFixes(fixer, nodes, sortedNodes, context.sourceCode)
},
})
}
})
},
}),
})