Skip to content

Commit

Permalink
feat: add partition by new line option to sort-interfaces rule
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-io committed Nov 11, 2023
1 parent 8654e44 commit 48532ef
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 4 deletions.
9 changes: 8 additions & 1 deletion docs/rules/sort-interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ interface Options {
order?: 'asc' | 'desc'
'ignore-case'?: boolean
groups?: (Group | Group[])[]
'custom-groups': { [key: Group]: string[] | string }
'custom-groups'?: { [key: Group]: string[] | string }
'ignore-pattern'?: string[]
'partition-by-new-line'?: boolean
}
```

Expand Down Expand Up @@ -159,6 +160,12 @@ If you need to ignore a rule for some interfaces, you can specify their names or

The [minimatch](https://github.com/isaacs/minimatch) library is used for pattern matching.

### partition-by-new-line

<sub>(default: `false`)</sub>

When `true`, does not sort the interface's element if there is an empty string between them.

## ⚙️ Usage

::: code-group
Expand Down
26 changes: 23 additions & 3 deletions rules/sort-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { minimatch } from 'minimatch'
import type { SortingNode } from '../typings'

import { createEslintRule } from '../utils/create-eslint-rule'
import { getLinesBetween } from '../utils/get-lines-between'
import { getGroupNumber } from '../utils/get-group-number'
import { toSingleLine } from '../utils/to-single-line'
import { rangeToDiff } from '../utils/range-to-diff'
Expand All @@ -23,6 +24,7 @@ type Options<T extends string[]> = [
Partial<{
'custom-groups': { [key: string]: string[] | string }
groups: (Group<T>[] | Group<T>)[]
'partition-by-new-line': boolean
'ignore-pattern': string[]
'ignore-case': boolean
order: SortOrder
Expand Down Expand Up @@ -75,6 +77,10 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
type: 'array',
default: [],
},
'partition-by-new-line': {
type: 'boolean',
default: false,
},
},
additionalProperties: false,
},
Expand All @@ -94,6 +100,7 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
TSInterfaceDeclaration: node => {
if (node.body.body.length > 1) {
let options = complete(context.options.at(0), {
'partition-by-new-line': false,
type: SortType.alphabetical,
'ignore-case': false,
order: SortOrder.asc,
Expand All @@ -118,6 +125,7 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
return accumulator
}

let lastElement = accumulator.at(-1)?.at(-1)
let name: string

let { getGroup, defineGroup, setCustomGroups } = useGroups(
Expand Down Expand Up @@ -148,17 +156,29 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
name = source.text.slice(element.range.at(0), endIndex)
}

let elementSortingNode = {
size: rangeToDiff(element.range),
node: element,
name,
}

if (
options['partition-by-new-line'] &&
lastElement &&
getLinesBetween(source, lastElement, elementSortingNode)
) {
accumulator.push([])
}

setCustomGroups(options['custom-groups'], name)

if (element.loc.start.line !== element.loc.end.line) {
defineGroup('multiline')
}

accumulator.at(-1)!.push({
size: rangeToDiff(element.range),
...elementSortingNode,
group: getGroup(),
node: element,
name,
})

return accumulator
Expand Down
253 changes: 253 additions & 0 deletions test/sort-interfaces.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,88 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
firstName: string
id: string
lastName: string
type: 'Human' | 'Demon'
age?: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
id: string
firstName: string
lastName: string
type: 'Human' | 'Demon'
age?: number
height: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
}
`,
output: dedent`
interface PhantomhiveHouseResiden {
firstName: string
id: string
lastName: string
type: 'Human' | 'Demon'
age?: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'id',
right: 'firstName',
},
},
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'height',
right: 'bloodType',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: sorting by natural order`, () => {
Expand Down Expand Up @@ -1155,6 +1237,88 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
firstName: string
id: string
lastName: string
type: 'Human' | 'Demon'
age?: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
id: string
firstName: string
lastName: string
type: 'Human' | 'Demon'
age?: number
height: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
}
`,
output: dedent`
interface PhantomhiveHouseResiden {
firstName: string
id: string
lastName: string
type: 'Human' | 'Demon'
age?: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'id',
right: 'firstName',
},
},
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'height',
right: 'bloodType',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: sorting by line length`, () => {
Expand Down Expand Up @@ -1680,6 +1844,95 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
firstName: string
lastName: string
id: string
type: 'Human' | 'Demon'
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
age?: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
interface PhantomhiveHouseResiden {
id: string
firstName: string
lastName: string
type: 'Human' | 'Demon'
age?: number
height: number
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
}
`,
output: dedent`
interface PhantomhiveHouseResiden {
firstName: string
lastName: string
id: string
type: 'Human' | 'Demon'
bloodType: 'Polaris' | 'Vega' | 'Canopus' | 'Sirius'
height: number
age?: number
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'id',
right: 'firstName',
},
},
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'age',
right: 'height',
},
},
{
messageId: 'unexpectedInterfacePropertiesOrder',
data: {
left: 'height',
right: 'bloodType',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: misc`, () => {
Expand Down

0 comments on commit 48532ef

Please sign in to comment.