Skip to content

Commit

Permalink
feat: add property-function groups in sort-class rule
Browse files Browse the repository at this point in the history
  • Loading branch information
hugop95 authored Aug 14, 2024
1 parent 8e15730 commit 41b92d3
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
12 changes: 11 additions & 1 deletion docs/content/rules/sort-classes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,17 @@ The `abstract` modifier is incompatible with the `static`, `private` and `decora
`constructor`, `get-method` and `set-method` elements will also be matched as `method`.

#### Properties
- Selector: `property`.
- Selectors: `function-property`, `property`.
- Modifiers: `static`, `declare`, `abstract`, `decorated`, `override`, `readonly`, `protected`, `private`, `public`.
- Example: `readonly-decorated-property`.

The `abstract` modifier is incompatible with the `static`, `private` and `decorated` modifiers.

The `declare` modifier is incompatible with the `override` and `decorated` modifiers.

The `function-property` selector will match properties whose values are defined functions or arrow-functions.
As such, the `declare` and `abstract` modifiers are incompatible with this selector.

#### Index-signatures
- Selector: `index-signature`.
- Modifiers: `static`, `readonly`.
Expand Down Expand Up @@ -317,6 +321,12 @@ abstract class Example extends BaseExample {
@SomeDecorator
private _value: number;

// private-function-property
private arrowProperty = () => {};

// private-function-property
private functionProperty = function() {};

// 'private-property'
private name: string;

Expand Down
12 changes: 12 additions & 0 deletions rules/sort-classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export type Modifier =
| StaticModifier

type ConstructorSelector = 'constructor'
type FunctionPropertySelector = 'function-property'
type PropertySelector = 'property'
type MethodSelector = 'method'
type GetMethodSelector = 'get-method'
Expand All @@ -52,6 +53,7 @@ type StaticBlockSelector = 'static-block'
type AccessorPropertySelector = 'accessor-property'
export type Selector =
| AccessorPropertySelector
| FunctionPropertySelector
| IndexSignatureSelector
| ConstructorSelector
| StaticBlockSelector
Expand Down Expand Up @@ -84,6 +86,8 @@ type MethodOrGetMethodOrSetMethodSelector =

type ConstructorGroup =
`${PublicOrProtectedOrPrivateModifierPrefix}${ConstructorSelector}`
type FunctionPropertyGroup =
`${PublicOrProtectedOrPrivateModifierPrefix}${StaticModifierPrefix}${OverrideModifierPrefix}${ReadonlyModifierPrefix}${DecoratedModifierPrefix}${FunctionPropertySelector}`
type DeclarePropertyGroup =
`${DeclareModifierPrefix}${PublicOrProtectedOrPrivateModifierPrefix}${StaticOrAbstractModifierPrefix}${ReadonlyModifierPrefix}${PropertySelector}`
type NonDeclarePropertyGroup =
Expand All @@ -105,6 +109,7 @@ type Group =
| MethodOrGetMethodOrSetMethodGroup
| NonDeclarePropertyGroup
| AccessorPropertyGroup
| FunctionPropertyGroup
| DeclarePropertyGroup
| IndexSignatureGroup
| ConstructorGroup
Expand Down Expand Up @@ -474,6 +479,13 @@ export default createEslintRule<Options, MESSAGE_ID>({
modifiers.push('public')
}

if (
member.value?.type === 'ArrowFunctionExpression' ||
member.value?.type === 'FunctionExpression'
) {
selectors.push('function-property')
}

selectors.push('property')
}
for (let officialGroup of generateOfficialGroups(
Expand Down
117 changes: 117 additions & 0 deletions test/sort-classes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ describe(ruleName, () => {
static readonly [key: string]: string;
private n = function() {};
private m = () => {};
declare private static readonly l;
private k = 'k';
Expand Down Expand Up @@ -241,6 +245,10 @@ describe(ruleName, () => {
declare private static readonly l;
private m = () => {};
private n = function() {};
static readonly [key: string]: string;
static {}
Expand All @@ -263,6 +271,7 @@ describe(ruleName, () => {
'protected-property',
'private-property',
'declare-private-static-readonly-property',
'function-property',
'static-readonly-index-signature',
'static-block',
],
Expand All @@ -283,6 +292,22 @@ describe(ruleName, () => {
data: {
left: 'static readonly [key: string]',
leftGroup: 'static-readonly-index-signature',
right: 'n',
rightGroup: 'function-property',
},
},
{
messageId: 'unexpectedClassesOrder',
data: {
left: 'n',
right: 'm',
},
},
{
messageId: 'unexpectedClassesGroupOrder',
data: {
left: 'm',
leftGroup: 'function-property',
right: 'l',
rightGroup: 'declare-private-static-readonly-property',
},
Expand Down Expand Up @@ -1020,6 +1045,98 @@ describe(ruleName, () => {
}
})

describe('property selectors priority', () => {
ruleTester.run(
`${ruleName}(${type}): prioritize function property over property`,
rule,
{
valid: [],
invalid: [
{
code: dedent`
export class Class {
a = function() {}
z: string;
}
`,
output: dedent`
export class Class {
z: string;
a = function() {}
}
`,
options: [
{
...options,
groups: ['property', 'function-property'],
},
],
errors: [
{
messageId: 'unexpectedClassesGroupOrder',
data: {
left: 'a',
leftGroup: 'function-property',
right: 'z',
rightGroup: 'property',
},
},
],
},
],
},
)

ruleTester.run(
`${ruleName}(${type}): prioritize function property over property for arrow functions`,
rule,
{
valid: [],
invalid: [
{
code: dedent`
export class Class {
a = () => {}
z: string;
}
`,
output: dedent`
export class Class {
z: string;
a = () => {}
}
`,
options: [
{
...options,
groups: ['property', 'function-property'],
},
],
errors: [
{
messageId: 'unexpectedClassesGroupOrder',
data: {
left: 'a',
leftGroup: 'function-property',
right: 'z',
rightGroup: 'property',
},
},
],
},
],
},
)
})

describe('property modifiers priority', () => {
ruleTester.run(
`${ruleName}(${type}): prioritize static over declare`,
Expand Down

0 comments on commit 41b92d3

Please sign in to comment.