diff --git a/rules/sort-enums.ts b/rules/sort-enums.ts index 4cb13561c..fccd4de3f 100644 --- a/rules/sort-enums.ts +++ b/rules/sort-enums.ts @@ -128,6 +128,49 @@ export default createEslintRule({ let sourceCode = getSourceCode(context) let partitionComment = options.partitionByComment + let extractDependencies = ( + expression: TSESTree.Expression, + enumName: string, + ): string[] => { + let dependencies: string[] = [] + + let checkNode = (nodeValue: TSESTree.Node) => { + if ( + nodeValue.type === 'MemberExpression' && + nodeValue.object.type === 'Identifier' && + nodeValue.object.name === enumName && + nodeValue.property.type === 'Identifier' + ) { + /** + * enum Enum { + * A = 1, + * B = Enum.A + * } + */ + dependencies.push(nodeValue.property.name) + } else if (nodeValue.type === 'Identifier') { + /** + * enum Enum { + * A = 1, + * B = A + * } + */ + dependencies.push(nodeValue.name) + } + + if ('left' in nodeValue) { + checkNode(nodeValue.left) + } + + if ('right' in nodeValue) { + checkNode(nodeValue.right) + } + } + + checkNode(expression) + return dependencies + } + let formattedMembers: SortingNode[][] = members.reduce( (accumulator: SortingNode[][], member) => { let comment = getCommentBefore(member, sourceCode) @@ -145,9 +188,18 @@ export default createEslintRule({ ? `${member.id.value}` : `${sourceCode.text.slice(...member.id.range)}` - let sortingNode = { + let dependencies + if (member.initializer) { + dependencies = extractDependencies( + member.initializer, + node.id.name, + ) + } + + let sortingNode: SortingNode = { size: rangeToDiff(member.range), node: member, + dependencies, name, } accumulator.at(-1)!.push(sortingNode) diff --git a/test/sort-enums.test.ts b/test/sort-enums.test.ts index 76581ca26..2ec2d1813 100644 --- a/test/sort-enums.test.ts +++ b/test/sort-enums.test.ts @@ -1703,5 +1703,131 @@ describe(ruleName, () => { ], }, ) + + ruleTester.run(`${ruleName}: works with dependencies`, rule, { + valid: [], + invalid: [ + { + code: dedent` + enum Enum { + C = 'C', + B = 0, + A = B, + } + `, + output: dedent` + enum Enum { + B = 0, + A = B, + C = 'C', + } + `, + options: [ + { + type: 'alphabetical', + }, + ], + errors: [ + { + messageId: 'unexpectedEnumsOrder', + data: { + left: 'C', + right: 'B', + }, + }, + ], + }, + { + code: dedent` + enum Enum { + C = 'C', + B = 0, + A = Enum.B, + } + `, + output: dedent` + enum Enum { + B = 0, + A = Enum.B, + C = 'C', + } + `, + options: [ + { + type: 'alphabetical', + }, + ], + errors: [ + { + messageId: 'unexpectedEnumsOrder', + data: { + left: 'C', + right: 'B', + }, + }, + ], + }, + { + code: dedent` + enum Enum { + C = 3, + B = 0, + A = 1 | 2 | B | Enum.B, + } + `, + output: dedent` + enum Enum { + B = 0, + A = 1 | 2 | B | Enum.B, + C = 3, + } + `, + options: [ + { + type: 'alphabetical', + }, + ], + errors: [ + { + messageId: 'unexpectedEnumsOrder', + data: { + left: 'C', + right: 'B', + }, + }, + ], + }, + { + code: dedent` + enum Enum { + B = 'B', + A = AnotherEnum.B, + C = 'C', + } + `, + output: dedent` + enum Enum { + A = AnotherEnum.B, + B = 'B', + C = 'C', + } + `, + options: [ + { + type: 'alphabetical', + }, + ], + errors: [ + { + messageId: 'unexpectedEnumsOrder', + data: { + left: 'B', + right: 'A', + }, + }, + ], + }, + ], + }) }) })