From 742852311452be679f0f5099f9f488d5f4704542 Mon Sep 17 00:00:00 2001 From: "Azat S." Date: Wed, 31 Jul 2024 17:11:13 +0300 Subject: [PATCH] fix: fix switch case sorting with grouped default case --- rules/sort-switch-case.ts | 34 ++++-- test/sort-switch-case.test.ts | 190 +++++++++++++++++++++++++++++++++- 2 files changed, 212 insertions(+), 12 deletions(-) diff --git a/rules/sort-switch-case.ts b/rules/sort-switch-case.ts index 91293fcc..19ca175f 100644 --- a/rules/sort-switch-case.ts +++ b/rules/sort-switch-case.ts @@ -92,16 +92,18 @@ export default createEslintRule({ if (isDiscriminantIdentifier && isCasesHasBreak) { let nodes = node.cases.map>( (caseNode: TSESTree.SwitchCase) => { - let name + let name: string if (caseNode.test?.type === 'Literal') { name = `${caseNode.test.value}` - } else { + } else if (caseNode.test === null) { name = 'default' + } else { + name = sourceCode.text.slice(...caseNode.test.range) } return { size: rangeToDiff(caseNode.test?.range ?? caseNode.range), - node: caseNode, + node: structuredClone(caseNode), name, } }, @@ -114,21 +116,35 @@ export default createEslintRule({ lefter?.node.consequent.length === 0 && left.node.consequent.length !== 0 - let caseGroup = [left] + let isGroupContainsDefault = (group: SortingNode[]) => + group.some(currentNode => currentNode.name === 'default') + + let leftCaseGroup = [left] + let rightCaseGroup = [right] for (let i = iteration - 1; i >= 0; i--) { if (nodes.at(i)!.node.consequent.length === 0) { - caseGroup.unshift(nodes.at(i)!) + leftCaseGroup.unshift(nodes.at(i)!) } else { break } } + if (right.node.consequent.length === 0) { + for (let i = iteration + 1; i < nodes.length; i++) { + if (nodes.at(i)!.node.consequent.length === 0) { + rightCaseGroup.push(nodes.at(i)!) + } else { + rightCaseGroup.push(nodes.at(i)!) + break + } + } + } - if (left.name === 'default') { + if (isGroupContainsDefault(leftCaseGroup)) { compareValue = true - } else if (right.name === 'default') { + } else if (isGroupContainsDefault(rightCaseGroup)) { compareValue = false } else if (isCaseGrouped) { - compareValue = isPositive(compare(caseGroup[0], right, options)) + compareValue = isPositive(compare(leftCaseGroup[0], right, options)) } else { compareValue = isPositive(compare(left, right, options)) } @@ -173,8 +189,6 @@ export default createEslintRule({ return sortedGroup }) .toSorted((a, b) => { - let isGroupContainsDefault = (group: SortingNode[]) => - group.some(currentNode => currentNode.name === 'default') if (isGroupContainsDefault(a)) { return 1 } else if (isGroupContainsDefault(b)) { diff --git a/test/sort-switch-case.test.ts b/test/sort-switch-case.test.ts index e878613c..846df182 100644 --- a/test/sort-switch-case.test.ts +++ b/test/sort-switch-case.test.ts @@ -254,9 +254,71 @@ describe(ruleName, () => { }, ], }) + + ruleTester.run( + `${ruleName}(${type}): works with grouped cases with default`, + rule, + { + valid: [ + { + code: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + }, + ], + invalid: [ + { + code: dedent` + switch (operationMode) { + case yy: + case z: + return null + case wwww: + return null + case xxx: + default: + return null + } + `, + output: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + errors: [ + { + messageId: 'unexpectedSwitchCaseOrder', + data: { + left: 'z', + right: 'wwww', + }, + }, + ], + }, + ], + }, + ) }) - describe(`${ruleName}: sorts switch cases with return statements`, () => { + describe(`${ruleName}: sorting by natural order`, () => { let type = 'natural-order' let options = { @@ -492,9 +554,71 @@ describe(ruleName, () => { }, ], }) + + ruleTester.run( + `${ruleName}(${type}): works with grouped cases with default`, + rule, + { + valid: [ + { + code: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + }, + ], + invalid: [ + { + code: dedent` + switch (operationMode) { + case yy: + case z: + return null + case wwww: + return null + case xxx: + default: + return null + } + `, + output: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + errors: [ + { + messageId: 'unexpectedSwitchCaseOrder', + data: { + left: 'z', + right: 'wwww', + }, + }, + ], + }, + ], + }, + ) }) - describe(`${ruleName}: sorts switch cases with return statements`, () => { + describe(`${ruleName}: sorting by line length`, () => { let type = 'line-length-order' let options = { @@ -729,6 +853,68 @@ describe(ruleName, () => { }, ], }) + + ruleTester.run( + `${ruleName}(${type}): works with grouped cases with default`, + rule, + { + valid: [ + { + code: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + }, + ], + invalid: [ + { + code: dedent` + switch (operationMode) { + case yy: + case z: + return null + case wwww: + return null + case xxx: + default: + return null + } + `, + output: dedent` + switch (operationMode) { + case wwww: + return null + case yy: + case z: + return null + case xxx: + default: + return null + } + `, + options: [options], + errors: [ + { + messageId: 'unexpectedSwitchCaseOrder', + data: { + left: 'z', + right: 'wwww', + }, + }, + ], + }, + ], + }, + ) }) describe(`${ruleName}: misc`, () => {