Skip to content

Commit

Permalink
feat(sort-maps): adds useConfigurationIf.allNamesMatchPattern
Browse files Browse the repository at this point in the history
  • Loading branch information
hugop95 committed Jan 17, 2025
1 parent a49ca89 commit 1438df5
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 21 deletions.
48 changes: 48 additions & 0 deletions docs/content/rules/sort-maps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Specifies the sorting method.
- `'natural'` — Sort items in a [natural](https://github.com/yobacca/natural-orderby) order (e.g., “item2” < “item10”).
- `'line-length'` — Sort items by the length of the code line (shorter lines first).
- `'custom'` — Sort items using the alphabet entered in the [`alphabet`](#alphabet) option.
- `'unsorted'` — Do not sort items. To be used with the [`useConfigurationIf`](#useconfigurationif) option.

### order

Expand Down Expand Up @@ -189,6 +190,51 @@ Specifies how new lines should be handled between map members.

This option is only applicable when `partitionByNewLine` is `false`.

### useConfigurationIf

<sub>
type: `{ allNamesMatchPattern?: string }`
</sub>
<sub>default: `{}`</sub>

Allows you to specify filters to match a particular options configuration for a given object.

The first matching options configuration will be used. If no configuration matches, the default options configuration will be used.

- `allNamesMatchPattern` — A regexp pattern that all object keys must match.

Example configuration:
```ts
{
'perfectionist/sort-maps': [
'error',
{
groups: ['r', 'g', 'b'], // Sort colors by RGB
customGroups: [
{
elementNamePattern: '^r$',
groupName: 'r',
},
{
elementNamePattern: '^g$',
groupName: 'g',
},
{
elementNamePattern: '^b$',
groupName: 'b',
},
],
useConfigurationIf: {
allNamesMatchPattern: '^r|g|b$',
},
},
{
type: 'alphabetical' // Fallback configuration
}
],
}
```

### groups

<sub>
Expand Down Expand Up @@ -282,6 +328,7 @@ Custom groups have a higher priority than any predefined group.
partitionByNewLine: false,
partitionByComment: false,
newlinesBetween: false,
useConfigurationIf: {},
groups: [],
customGroups: [],
},
Expand Down Expand Up @@ -311,6 +358,7 @@ Custom groups have a higher priority than any predefined group.
partitionByNewLine: false,
partitionByComment: false,
newlinesBetween: false,
useConfigurationIf: {},
groups: [],
customGroups: [],
},
Expand Down
71 changes: 50 additions & 21 deletions rules/sort-maps.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import type { TSESTree } from '@typescript-eslint/types'
import type { TSESLint } from '@typescript-eslint/utils'

import { TSESTree } from '@typescript-eslint/types'

import type { SortingNode } from '../types/sorting-node'
import type { Options } from './sort-maps/types'

import {
buildUseConfigurationIfJsonSchema,
buildCustomGroupsArrayJsonSchema,
partitionByCommentJsonSchema,
partitionByNewLineJsonSchema,
Expand All @@ -19,6 +22,7 @@ import {
import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
import { getMatchingContextOptions } from '../utils/get-matching-context-options'
import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
import { doesCustomGroupMatch } from './sort-maps/does-custom-group-match'
import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
Expand Down Expand Up @@ -52,6 +56,7 @@ let defaultOptions: Required<Options[0]> = {
partitionByComment: false,
partitionByNewLine: false,
newlinesBetween: 'ignore',
useConfigurationIf: {},
type: 'alphabetical',
ignoreCase: true,
customGroups: [],
Expand All @@ -77,8 +82,21 @@ export default createEslintRule<Options, MESSAGE_ID>({
return
}

let sourceCode = getSourceCode(context)
let settings = getSettings(context.settings)
let options = complete(context.options.at(0), settings, defaultOptions)

let matchedContextOptions = getMatchingContextOptions({
nodeNames: elements
.filter(
element =>
element !== null &&
element.type !== TSESTree.AST_NODE_TYPES.SpreadElement,
)
.map(element => getNodeName({ sourceCode, element })),
contextOptions: context.options,
})

let options = complete(matchedContextOptions[0], settings, defaultOptions)
validateCustomSortConfiguration(options)
validateGeneratedGroupsConfiguration({
customGroups: options.customGroups,
Expand All @@ -87,7 +105,6 @@ export default createEslintRule<Options, MESSAGE_ID>({
modifiers: [],
})

let sourceCode = getSourceCode(context)
let eslintDisabledLines = getEslintDisabledLines({
ruleName: context.id,
sourceCode,
Expand All @@ -110,21 +127,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
for (let part of parts) {
let formattedMembers: SortingNode[][] = [[]]
for (let element of part) {
let name: string

if (element.type === 'ArrayExpression') {
let [left] = element.elements

if (!left) {
name = `${left}`
} else if (left.type === 'Literal') {
name = left.raw
} else {
name = sourceCode.getText(left)
}
} else {
name = sourceCode.getText(element)
}
let name: string = getNodeName({
sourceCode,
element,
})

let lastSortingNode = formattedMembers.at(-1)?.at(-1)

Expand Down Expand Up @@ -254,8 +260,8 @@ export default createEslintRule<Options, MESSAGE_ID>({
},
}),
meta: {
schema: [
{
schema: {
items: {
properties: {
partitionByComment: {
...partitionByCommentJsonSchema,
Expand All @@ -265,6 +271,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
customGroups: buildCustomGroupsArrayJsonSchema({
singleCustomGroupJsonSchema,
}),
useConfigurationIf: buildUseConfigurationIfJsonSchema(),
partitionByNewLine: partitionByNewLineJsonSchema,
specialCharacters: specialCharactersJsonSchema,
newlinesBetween: newlinesBetweenJsonSchema,
Expand All @@ -278,7 +285,9 @@ export default createEslintRule<Options, MESSAGE_ID>({
additionalProperties: false,
type: 'object',
},
],
uniqueItems: true,
type: 'array',
},
messages: {
unexpectedMapElementsGroupOrder:
'Expected "{{right}}" ({{rightGroup}}) to come before "{{left}}" ({{leftGroup}}).',
Expand All @@ -300,3 +309,23 @@ export default createEslintRule<Options, MESSAGE_ID>({
defaultOptions: [defaultOptions],
name: 'sort-maps',
})

let getNodeName = ({
sourceCode,
element,
}: {
sourceCode: TSESLint.SourceCode
element: TSESTree.Expression
}): string => {
if (element.type === 'ArrayExpression') {
let [left] = element.elements

if (!left) {
return `${left}`
} else if (left.type === 'Literal') {
return left.raw
}
return sourceCode.getText(left)
}
return sourceCode.getText(element)
}
3 changes: 3 additions & 0 deletions rules/sort-maps/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export type Options = Partial<{
| Group[]
| Group
)[]
useConfigurationIf: {
allNamesMatchPattern?: string
}
type: 'alphabetical' | 'line-length' | 'natural' | 'custom'
newlinesBetween: 'ignore' | 'always' | 'never'
specialCharacters: 'remove' | 'trim' | 'keep'
Expand Down
77 changes: 77 additions & 0 deletions test/rules/sort-maps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,83 @@ describe(ruleName, () => {
},
)
})

describe(`${ruleName}(${type}): allows to use 'useConfigurationIf'`, () => {
ruleTester.run(
`${ruleName}(${type}): allows to use 'allNamesMatchPattern'`,
rule,
{
invalid: [
{
options: [
{
...options,
useConfigurationIf: {
allNamesMatchPattern: 'foo',
},
},
{
...options,
customGroups: [
{
elementNamePattern: '^r$',
groupName: 'r',
},
{
elementNamePattern: '^g$',
groupName: 'g',
},
{
elementNamePattern: '^b$',
groupName: 'b',
},
],
useConfigurationIf: {
allNamesMatchPattern: '^r|g|b$',
},
groups: ['r', 'g', 'b'],
},
],
errors: [
{
data: {
rightGroup: 'g',
leftGroup: 'b',
right: 'g',
left: 'b',
},
messageId: 'unexpectedMapElementsGroupOrder',
},
{
data: {
rightGroup: 'r',
leftGroup: 'g',
right: 'r',
left: 'g',
},
messageId: 'unexpectedMapElementsGroupOrder',
},
],
output: dedent`
new Map([
[r, null],
[g, null],
[b, null]
])
`,
code: dedent`
new Map([
[b, null],
[g, null],
[r, null]
])
`,
},
],
valid: [],
},
)
})
})

describe(`${ruleName}: sorting by natural order`, () => {
Expand Down

0 comments on commit 1438df5

Please sign in to comment.