Skip to content

Commit be0b68f

Browse files
hugop95azat-io
authored andcommittedNov 19, 2024
feat(sort-classes): add async modifier
1 parent 9f9f5c1 commit be0b68f

File tree

4 files changed

+128
-32
lines changed

4 files changed

+128
-32
lines changed
 

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ Predefined groups are characterized by a single selector and potentially multipl
321321

322322
#### Methods
323323
- Selectors: `get-method`, `set-method`, `method`.
324-
- Modifiers: `static`, `abstract`, `decorated`, `override`, `protected`, `private`, `public`, `optional`.
324+
- Modifiers: `static`, `abstract`, `decorated`, `override`, `protected`, `private`, `public`, `optional`, `async`.
325325
- Example: `private-static-accessor-property`, `protected-abstract-override-method` or `static-get-method`.
326326

327327
The `optional` modifier is incompatible with the `get-method` and `set-method` selectors.
@@ -339,7 +339,7 @@ The `abstract` modifier is incompatible with the `static`, `private` and `decora
339339

340340
#### Properties
341341
- Selectors: `function-property`, `property`.
342-
- Modifiers: `static`, `declare`, `abstract`, `decorated`, `override`, `readonly`, `protected`, `private`, `public`, `optional`.
342+
- Modifiers: `static`, `declare`, `abstract`, `decorated`, `override`, `readonly`, `protected`, `private`, `public`, `optional`, `async`.
343343
- Example: `readonly-decorated-property`.
344344

345345
The `abstract` modifier is incompatible with the `static`, `private` and `decorated` modifiers.
@@ -349,6 +349,8 @@ The `declare` modifier is incompatible with the `override` and `decorated` modif
349349
The `function-property` selector will match properties whose values are defined functions or arrow-functions.
350350
As such, the `declare` and `abstract` modifiers are incompatible with this selector.
351351

352+
The `async` modifier is reserved for the `function-property` selector.
353+
352354
#### Index-signatures
353355
- Selector: `index-signature`.
354356
- Modifiers: `static`, `readonly`.

‎rules/sort-classes.ts

+11-13
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
448448
modifiers.push('optional')
449449
}
450450

451+
if (member.value.async) {
452+
modifiers.push('async')
453+
}
454+
451455
if (member.kind === 'constructor') {
452456
selectors.push('constructor')
453457
}
@@ -544,26 +548,20 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
544548
modifiers.push('optional')
545549
}
546550

547-
let isFunctionProperty =
551+
if (
548552
member.value?.type === 'ArrowFunctionExpression' ||
549553
member.value?.type === 'FunctionExpression'
550-
if (isFunctionProperty) {
554+
) {
555+
if (member.value.async) {
556+
modifiers.push('async')
557+
}
551558
selectors.push('function-property')
552-
}
553-
554-
if (!isFunctionProperty && member.value) {
559+
} else if (member.value) {
555560
memberValue = sourceCode.getText(member.value)
561+
dependencies = extractDependencies(member.value, member.static)
556562
}
557563

558564
selectors.push('property')
559-
560-
if (
561-
member.type === 'PropertyDefinition' &&
562-
member.value &&
563-
!isFunctionProperty
564-
) {
565-
dependencies = extractDependencies(member.value, member.static)
566-
}
567565
}
568566

569567
for (let officialGroup of generatePredefinedGroups({

‎rules/sort-classes.types.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type PublicOrProtectedOrPrivateModifier =
77
| ProtectedModifier
88
| PrivateModifier
99
| PublicModifier
10+
type AsyncModifier = 'async'
1011
type StaticModifier = 'static'
1112
type AbstractModifier = 'abstract'
1213
type OverrideModifier = 'override'
@@ -23,6 +24,7 @@ export type Modifier =
2324
| ReadonlyModifier
2425
| DeclareModifier
2526
| StaticModifier
27+
| AsyncModifier
2628

2729
type ConstructorSelector = 'constructor'
2830
type FunctionPropertySelector = 'function-property'
@@ -50,6 +52,7 @@ type PublicOrProtectedOrPrivateModifierPrefix = WithDashSuffixOrEmpty<
5052
ProtectedModifier | PrivateModifier | PublicModifier
5153
>
5254

55+
type AsyncModifierPrefix = WithDashSuffixOrEmpty<AsyncModifier>
5356
type OverrideModifierPrefix = WithDashSuffixOrEmpty<OverrideModifier>
5457
type OptionalModifierPrefix = WithDashSuffixOrEmpty<OptionalModifier>
5558
type ReadonlyModifierPrefix = WithDashSuffixOrEmpty<ReadonlyModifier>
@@ -67,13 +70,13 @@ type GetMethodOrSetMethodSelector = GetMethodSelector | SetMethodSelector
6770
type ConstructorGroup =
6871
`${PublicOrProtectedOrPrivateModifierPrefix}${ConstructorSelector}`
6972
type FunctionPropertyGroup =
70-
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticModifierPrefix}${OverrideModifierPrefix}${ReadonlyModifierPrefix}${DecoratedModifierPrefix}${FunctionPropertySelector}`
73+
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticModifierPrefix}${OverrideModifierPrefix}${ReadonlyModifierPrefix}${DecoratedModifierPrefix}${AsyncModifierPrefix}${FunctionPropertySelector}`
7174
type DeclarePropertyGroup =
7275
`${DeclareModifierPrefix}${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${ReadonlyModifierPrefix}${OptionalModifierPrefix}${PropertySelector}`
7376
type NonDeclarePropertyGroup =
7477
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${OverrideModifierPrefix}${ReadonlyModifierPrefix}${DecoratedModifierPrefix}${OptionalModifierPrefix}${PropertySelector}`
7578
type MethodGroup =
76-
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${OverrideModifierPrefix}${DecoratedModifierPrefix}${OptionalModifierPrefix}${MethodSelector}`
79+
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${OverrideModifierPrefix}${DecoratedModifierPrefix}${AsyncModifierPrefix}${OptionalModifierPrefix}${MethodSelector}`
7780
type GetMethodOrSetMethodGroup =
7881
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${OverrideModifierPrefix}${DecoratedModifierPrefix}${GetMethodOrSetMethodSelector}`
7982
type AccessorPropertyGroup =
@@ -121,17 +124,19 @@ interface AllowedModifiersPerSelector {
121124
| OverrideModifier
122125
| OptionalModifier
123126
| StaticModifier
124-
'accessor-property':
127+
| AsyncModifier
128+
'function-property':
125129
| PublicOrProtectedOrPrivateModifier
126130
| DecoratedModifier
127-
| AbstractModifier
128131
| OverrideModifier
132+
| ReadonlyModifier
129133
| StaticModifier
130-
'function-property':
134+
| AsyncModifier
135+
'accessor-property':
131136
| PublicOrProtectedOrPrivateModifier
132137
| DecoratedModifier
138+
| AbstractModifier
133139
| OverrideModifier
134-
| ReadonlyModifier
135140
| StaticModifier
136141
'set-method':
137142
| PublicOrProtectedOrPrivateModifier
@@ -213,6 +218,7 @@ export let allSelectors: Selector[] = [
213218
]
214219

215220
export let allModifiers: Modifier[] = [
221+
'async',
216222
'protected',
217223
'private',
218224
'public',

‎test/sort-classes.test.ts

+101-11
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,17 @@ describe(ruleName, () => {
189189
code: dedent`
190190
abstract class Class {
191191
192-
p?(): void;
192+
async p?(): Promise<void>;
193193
194194
o?;
195195
196196
static {}
197197
198198
static readonly [key: string]: string;
199199
200-
private n = function() {};
200+
private n = async function() {};
201201
202-
private m = () => {};
202+
private m = async () => {};
203203
204204
declare private static readonly l;
205205
@@ -257,17 +257,17 @@ describe(ruleName, () => {
257257
258258
declare private static readonly l;
259259
260-
private m = () => {};
260+
private m = async () => {};
261261
262-
private n = function() {};
262+
private n = async function() {};
263263
264264
static readonly [key: string]: string;
265265
266266
static {}
267267
268268
o?;
269269
270-
p?(): void;
270+
async p?(): Promise<void>;
271271
}
272272
`,
273273
options: [
@@ -287,11 +287,11 @@ describe(ruleName, () => {
287287
'protected-property',
288288
'private-property',
289289
'declare-private-static-readonly-property',
290-
'function-property',
290+
'async-function-property',
291291
'static-readonly-index-signature',
292292
'static-block',
293293
'public-optional-property',
294-
'public-optional-method',
294+
'public-optional-async-method',
295295
],
296296
},
297297
],
@@ -300,7 +300,7 @@ describe(ruleName, () => {
300300
messageId: 'unexpectedClassesGroupOrder',
301301
data: {
302302
left: 'p',
303-
leftGroup: 'public-optional-method',
303+
leftGroup: 'public-optional-async-method',
304304
right: 'o',
305305
rightGroup: 'public-optional-property',
306306
},
@@ -329,7 +329,7 @@ describe(ruleName, () => {
329329
left: 'static readonly [key: string]',
330330
leftGroup: 'static-readonly-index-signature',
331331
right: 'n',
332-
rightGroup: 'function-property',
332+
rightGroup: 'async-function-property',
333333
},
334334
},
335335
{
@@ -343,7 +343,7 @@ describe(ruleName, () => {
343343
messageId: 'unexpectedClassesGroupOrder',
344344
data: {
345345
left: 'm',
346-
leftGroup: 'function-property',
346+
leftGroup: 'async-function-property',
347347
right: 'l',
348348
rightGroup: 'declare-private-static-readonly-property',
349349
},
@@ -926,6 +926,51 @@ describe(ruleName, () => {
926926
},
927927
)
928928
}
929+
930+
ruleTester.run(
931+
`${ruleName}(${type}): prioritize optional over async`,
932+
rule,
933+
{
934+
valid: [],
935+
invalid: [
936+
{
937+
code: dedent`
938+
export class Class {
939+
940+
a: string;
941+
942+
async z?(): Promise<string>;
943+
}
944+
`,
945+
output: dedent`
946+
export class Class {
947+
948+
async z?(): Promise<string>;
949+
950+
a: string;
951+
}
952+
`,
953+
options: [
954+
{
955+
...options,
956+
groups: [`optional-method`, 'property', 'async-method'],
957+
},
958+
],
959+
errors: [
960+
{
961+
messageId: 'unexpectedClassesGroupOrder',
962+
data: {
963+
left: 'a',
964+
leftGroup: 'property',
965+
right: 'z',
966+
rightGroup: `optional-method`,
967+
},
968+
},
969+
],
970+
},
971+
],
972+
},
973+
)
929974
})
930975

931976
describe(`${ruleName}(${type}): accessor modifiers priority`, () => {
@@ -1596,6 +1641,51 @@ describe(ruleName, () => {
15961641
},
15971642
)
15981643
}
1644+
1645+
ruleTester.run(
1646+
`${ruleName}(${type}): prioritize optional over async`,
1647+
rule,
1648+
{
1649+
valid: [],
1650+
invalid: [
1651+
{
1652+
code: dedent`
1653+
export class Class {
1654+
1655+
a(): void {}
1656+
1657+
z?: Promise<string> = async () => {};
1658+
}
1659+
`,
1660+
output: dedent`
1661+
export class Class {
1662+
1663+
z?: Promise<string> = async () => {};
1664+
1665+
a(): void {}
1666+
}
1667+
`,
1668+
options: [
1669+
{
1670+
...options,
1671+
groups: ['optional-property', 'method', `async-property`],
1672+
},
1673+
],
1674+
errors: [
1675+
{
1676+
messageId: 'unexpectedClassesGroupOrder',
1677+
data: {
1678+
left: 'a',
1679+
leftGroup: 'method',
1680+
right: 'z',
1681+
rightGroup: `optional-property`,
1682+
},
1683+
},
1684+
],
1685+
},
1686+
],
1687+
},
1688+
)
15991689
})
16001690

16011691
ruleTester.run(

0 commit comments

Comments
 (0)
Please sign in to comment.