Skip to content

Commit 768c959

Browse files
committed
feat: todo
1 parent bb1af3c commit 768c959

10 files changed

Lines changed: 1019 additions & 41 deletions

docs/content/rules/sort-export-attributes.mdx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,64 @@ or [`customGroups`](#customgroups) options.
188188

189189
This option is only applicable when [`partitionByNewLine`](#partitionbynewline) is `false`.
190190

191+
### useConfigurationIf
192+
193+
<sub>
194+
type:
195+
```ts
196+
{
197+
allNamesMatchPattern?:
198+
| string
199+
| string[]
200+
| { pattern: string; flags: string }
201+
| { pattern: string; flags: string }[]
202+
matchesAstSelector?: string
203+
}
204+
```
205+
</sub>
206+
<sub>default: `{}`</sub>
207+
208+
Specifies filters to match a particular options configuration for a given export.
209+
210+
The first matching options configuration will be used. If no configuration matches, the default options configuration will be used.
211+
212+
- `allNamesMatchPattern` — A regexp pattern that all export attributes must match.
213+
214+
Example configuration:
215+
```ts
216+
{
217+
'perfectionist/sort-export-attributes': [
218+
'error',
219+
{
220+
groups: ['r', 'g', 'b'], // Sort colors by RGB
221+
customGroups: [
222+
{
223+
elementNamePattern: '^r$',
224+
groupName: 'r',
225+
},
226+
{
227+
elementNamePattern: '^g$',
228+
groupName: 'g',
229+
},
230+
{
231+
elementNamePattern: '^b$',
232+
groupName: 'b',
233+
},
234+
],
235+
useConfigurationIf: {
236+
allNamesMatchPattern: '^[rgb]$',
237+
},
238+
},
239+
{
240+
type: 'alphabetical' // Fallback configuration
241+
}
242+
],
243+
}
244+
```
245+
246+
- `matchesAstSelector` — An [AST selector](https://eslint.org/docs/latest/extend/selectors) matching an `ExportNamedDeclaration` node.
247+
To avoid unexpected behavior, do not use `:exit` or `:enter` pseudo-selectors.
248+
191249
### groups
192250

193251
<sub>
@@ -309,6 +367,7 @@ An attribute matches a custom group when its name satisfies `elementNamePattern`
309367
partitionByNewLine: false,
310368
newlinesBetween: 'ignore',
311369
newlinesInside: 'ignore',
370+
useConfigurationIf: {},
312371
groups: [],
313372
customGroups: [],
314373
},
@@ -340,6 +399,7 @@ An attribute matches a custom group when its name satisfies `elementNamePattern`
340399
partitionByNewLine: false,
341400
newlinesBetween: 'ignore',
342401
newlinesInside: 'ignore',
402+
useConfigurationIf: {},
343403
groups: [],
344404
customGroups: [],
345405
},

docs/content/rules/sort-import-attributes.mdx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,64 @@ or [`customGroups`](#customgroups) options.
188188

189189
This option is only applicable when [`partitionByNewLine`](#partitionbynewline) is `false`.
190190

191+
### useConfigurationIf
192+
193+
<sub>
194+
type:
195+
```ts
196+
{
197+
allNamesMatchPattern?:
198+
| string
199+
| string[]
200+
| { pattern: string; flags: string }
201+
| { pattern: string; flags: string }[]
202+
matchesAstSelector?: string
203+
}
204+
```
205+
</sub>
206+
<sub>default: `{}`</sub>
207+
208+
Specifies filters to match a particular options configuration for a given import.
209+
210+
The first matching options configuration will be used. If no configuration matches, the default options configuration will be used.
211+
212+
- `allNamesMatchPattern` — A regexp pattern that all import attributes must match.
213+
214+
Example configuration:
215+
```ts
216+
{
217+
'perfectionist/sort-import-attributes': [
218+
'error',
219+
{
220+
groups: ['r', 'g', 'b'], // Sort colors by RGB
221+
customGroups: [
222+
{
223+
elementNamePattern: '^r$',
224+
groupName: 'r',
225+
},
226+
{
227+
elementNamePattern: '^g$',
228+
groupName: 'g',
229+
},
230+
{
231+
elementNamePattern: '^b$',
232+
groupName: 'b',
233+
},
234+
],
235+
useConfigurationIf: {
236+
allNamesMatchPattern: '^[rgb]$',
237+
},
238+
},
239+
{
240+
type: 'alphabetical' // Fallback configuration
241+
}
242+
],
243+
}
244+
```
245+
246+
- `matchesAstSelector` — An [AST selector](https://eslint.org/docs/latest/extend/selectors) matching an `ImportDeclaration` node.
247+
To avoid unexpected behavior, do not use `:exit` or `:enter` pseudo-selectors.
248+
191249
### groups
192250

193251
<sub>
@@ -309,6 +367,7 @@ An attribute matches a custom group when its name satisfies `elementNamePattern`
309367
partitionByNewLine: false,
310368
newlinesBetween: 'ignore',
311369
newlinesInside: 'ignore',
370+
useConfigurationIf: {},
312371
groups: [],
313372
customGroups: [],
314373
},
@@ -340,6 +399,7 @@ An attribute matches a custom group when its name satisfies `elementNamePattern`
340399
partitionByNewLine: false,
341400
newlinesBetween: 'ignore',
342401
newlinesInside: 'ignore',
402+
useConfigurationIf: {},
343403
groups: [],
344404
customGroups: [],
345405
},

rules/sort-export-attributes.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
2+
import type { TSESTree } from '@typescript-eslint/types'
3+
4+
import { AST_NODE_TYPES } from '@typescript-eslint/utils'
5+
16
import type { Options } from './sort-export-attributes/types'
27

8+
import {
9+
buildUseConfigurationIfJsonSchema,
10+
matchesAstSelectorJsonSchema,
11+
buildCommonJsonSchemas,
12+
} from '../utils/json-schemas/common-json-schemas'
313
import {
414
partitionByCommentJsonSchema,
515
partitionByNewLineJsonSchema,
@@ -12,7 +22,7 @@ import {
1222
} from '../utils/report-errors'
1323
import { sortImportOrExportAttributes } from './sort-import-attributes/sort-import-or-export-attributes'
1424
import { buildCommonGroupsJsonSchemas } from '../utils/json-schemas/common-groups-json-schemas'
15-
import { buildCommonJsonSchemas } from '../utils/json-schemas/common-json-schemas'
25+
import { buildAstListeners } from '../utils/build-ast-listeners'
1626
import { createEslintRule } from '../utils/create-eslint-rule'
1727

1828
const ORDER_ERROR_ID = 'unexpectedExportAttributesOrder'
@@ -33,6 +43,7 @@ let defaultOptions: Required<Options[0]> = {
3343
partitionByComment: false,
3444
partitionByNewLine: false,
3545
newlinesBetween: 'ignore',
46+
useConfigurationIf: {},
3647
type: 'alphabetical',
3748
ignoreCase: true,
3849
customGroups: [],
@@ -49,6 +60,11 @@ export default createEslintRule<Options, MessageId>({
4960
properties: {
5061
...buildCommonJsonSchemas(),
5162
...buildCommonGroupsJsonSchemas(),
63+
useConfigurationIf: buildUseConfigurationIfJsonSchema({
64+
additionalProperties: {
65+
matchesAstSelector: matchesAstSelectorJsonSchema,
66+
},
67+
}),
5268
partitionByComment: partitionByCommentJsonSchema,
5369
partitionByNewLine: partitionByNewLineJsonSchema,
5470
},
@@ -72,20 +88,35 @@ export default createEslintRule<Options, MessageId>({
7288
type: 'suggestion',
7389
fixable: 'code',
7490
},
75-
create: context => ({
76-
ExportNamedDeclaration: node =>
77-
sortImportOrExportAttributes({
78-
availableMessageIds: {
79-
missedSpacingBetweenMembers: MISSED_SPACING_ERROR_ID,
80-
extraSpacingBetweenMembers: EXTRA_SPACING_ERROR_ID,
81-
unexpectedGroupOrder: GROUP_ORDER_ERROR_ID,
82-
unexpectedOrder: ORDER_ERROR_ID,
83-
},
84-
defaultOptions,
85-
context,
86-
node,
87-
}),
88-
}),
91+
create: context =>
92+
buildAstListeners({
93+
nodeTypes: [AST_NODE_TYPES.ExportNamedDeclaration],
94+
sorter: sortExportAttributes,
95+
context,
96+
}),
8997
defaultOptions: [defaultOptions],
9098
name: 'sort-export-attributes',
9199
})
100+
101+
function sortExportAttributes({
102+
matchedAstSelectors,
103+
context,
104+
node,
105+
}: {
106+
context: Readonly<RuleContext<MessageId, Options>>
107+
matchedAstSelectors: ReadonlySet<string>
108+
node: TSESTree.ExportNamedDeclaration
109+
}): void {
110+
sortImportOrExportAttributes<MessageId>({
111+
availableMessageIds: {
112+
missedSpacingBetweenMembers: MISSED_SPACING_ERROR_ID,
113+
extraSpacingBetweenMembers: EXTRA_SPACING_ERROR_ID,
114+
unexpectedGroupOrder: GROUP_ORDER_ERROR_ID,
115+
unexpectedOrder: ORDER_ERROR_ID,
116+
},
117+
matchedAstSelectors,
118+
defaultOptions,
119+
context,
120+
node,
121+
})
122+
}

rules/sort-export-attributes/types.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1-
import type { TSESTree } from '@typescript-eslint/types'
2-
1+
import type { RegexOption, TypeOption } from '../../types/common-options'
32
import type { AllCommonOptions } from '../../types/all-common-options'
4-
import type { TypeOption } from '../../types/common-options'
5-
import type { SortingNode } from '../../types/sorting-node'
63

74
export type Options = Partial<
8-
AllCommonOptions<TypeOption, AdditionalSortOptions, CustomGroupMatchOptions>
9-
>[]
5+
{
6+
/**
7+
* Conditional configuration based on pattern matching.
8+
*/
9+
useConfigurationIf: {
10+
/**
11+
* Regular expression pattern to match against all attribute key names.
12+
* The rule is only applied when all names match this pattern.
13+
*/
14+
allNamesMatchPattern?: RegexOption
1015

11-
export type SortExportAttributesSortingNode =
12-
SortingNode<TSESTree.ImportAttribute>
16+
/**
17+
* AST selector to match against ImportDeclaration or
18+
* ExportNamedDeclaration nodes.
19+
*/
20+
matchesAstSelector?: string
21+
}
22+
} & AllCommonOptions<
23+
TypeOption,
24+
AdditionalSortOptions,
25+
CustomGroupMatchOptions
26+
>
27+
>[]
1328

1429
/**
1530
* Match options for a custom group.

rules/sort-import-attributes.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
2+
import type { TSESTree } from '@typescript-eslint/types'
3+
4+
import { AST_NODE_TYPES } from '@typescript-eslint/utils'
5+
16
import type { Options } from './sort-import-attributes/types'
27

8+
import {
9+
buildUseConfigurationIfJsonSchema,
10+
matchesAstSelectorJsonSchema,
11+
buildCommonJsonSchemas,
12+
} from '../utils/json-schemas/common-json-schemas'
313
import {
414
partitionByCommentJsonSchema,
515
partitionByNewLineJsonSchema,
@@ -12,7 +22,7 @@ import {
1222
} from '../utils/report-errors'
1323
import { sortImportOrExportAttributes } from './sort-import-attributes/sort-import-or-export-attributes'
1424
import { buildCommonGroupsJsonSchemas } from '../utils/json-schemas/common-groups-json-schemas'
15-
import { buildCommonJsonSchemas } from '../utils/json-schemas/common-json-schemas'
25+
import { buildAstListeners } from '../utils/build-ast-listeners'
1626
import { createEslintRule } from '../utils/create-eslint-rule'
1727

1828
const ORDER_ERROR_ID = 'unexpectedImportAttributesOrder'
@@ -33,6 +43,7 @@ let defaultOptions: Required<Options[0]> = {
3343
partitionByComment: false,
3444
partitionByNewLine: false,
3545
newlinesBetween: 'ignore',
46+
useConfigurationIf: {},
3647
type: 'alphabetical',
3748
ignoreCase: true,
3849
customGroups: [],
@@ -49,6 +60,11 @@ export default createEslintRule<Options, MessageId>({
4960
properties: {
5061
...buildCommonJsonSchemas(),
5162
...buildCommonGroupsJsonSchemas(),
63+
useConfigurationIf: buildUseConfigurationIfJsonSchema({
64+
additionalProperties: {
65+
matchesAstSelector: matchesAstSelectorJsonSchema,
66+
},
67+
}),
5268
partitionByComment: partitionByCommentJsonSchema,
5369
partitionByNewLine: partitionByNewLineJsonSchema,
5470
},
@@ -72,20 +88,35 @@ export default createEslintRule<Options, MessageId>({
7288
type: 'suggestion',
7389
fixable: 'code',
7490
},
75-
create: context => ({
76-
ImportDeclaration: node =>
77-
sortImportOrExportAttributes({
78-
availableMessageIds: {
79-
missedSpacingBetweenMembers: MISSED_SPACING_ERROR_ID,
80-
extraSpacingBetweenMembers: EXTRA_SPACING_ERROR_ID,
81-
unexpectedGroupOrder: GROUP_ORDER_ERROR_ID,
82-
unexpectedOrder: ORDER_ERROR_ID,
83-
},
84-
defaultOptions,
85-
context,
86-
node,
87-
}),
88-
}),
91+
create: context =>
92+
buildAstListeners({
93+
nodeTypes: [AST_NODE_TYPES.ImportDeclaration],
94+
sorter: sortImportAttributes,
95+
context,
96+
}),
8997
defaultOptions: [defaultOptions],
9098
name: 'sort-import-attributes',
9199
})
100+
101+
function sortImportAttributes({
102+
matchedAstSelectors,
103+
context,
104+
node,
105+
}: {
106+
context: Readonly<RuleContext<MessageId, Options>>
107+
matchedAstSelectors: ReadonlySet<string>
108+
node: TSESTree.ImportDeclaration
109+
}): void {
110+
sortImportOrExportAttributes<MessageId>({
111+
availableMessageIds: {
112+
missedSpacingBetweenMembers: MISSED_SPACING_ERROR_ID,
113+
extraSpacingBetweenMembers: EXTRA_SPACING_ERROR_ID,
114+
unexpectedGroupOrder: GROUP_ORDER_ERROR_ID,
115+
unexpectedOrder: ORDER_ERROR_ID,
116+
},
117+
matchedAstSelectors,
118+
defaultOptions,
119+
context,
120+
node,
121+
})
122+
}

0 commit comments

Comments
 (0)