Repository: azat-io/eslint-plugin-perfectionist
Pull request #485 (2025-03-09 15:40:05)

fix(sort-imports): fix explicit `fallbackSort` overriding side-effects
Fixes https://github.com/azat-io/eslint-plugin-perfectionist/issues/483

### Description

Explicitely writing `fallbackSort` in `sort-imports` will override `sideEffects` which should stay unsorted.

### Bug severity

Medium-high:
- Related to a relatively new feature (fallback sorting)
- Requires writing an explicit `fallbackSort` option, meaning that `type` should be `line-length` logically.
- Side-effects import order can break runtime.

=> I think that a hotfix is justified.

### What is the purpose of this pull request?

- [x] Bug fix


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/azat-io/eslint-plugin-perfectionist/pull/485?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azat+S.) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 100.00%. Comparing base [(`8d4ad4f`)](https://app.codecov.io/gh/azat-io/eslint-plugin-perfectionist/commit/8d4ad4f9e492c5db08524bd7657371671e439e9e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azat+S.) to head [(`59e41ac`)](https://app.codecov.io/gh/azat-io/eslint-plugin-perfectionist/commit/59e41acf3178ec068095c666e41a7f8ec0eb4911?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azat+S.).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff            @@
##              main      #485   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           94        94           
  Lines         7617      7620    +3     
  Branches      1632      1634    +2     
=========================================
+ Hits          7617      7620    +3     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/azat-io/eslint-plugin-perfectionist/pull/485?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azat+S.).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azat+S.).

<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- 📦 [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
hugop95: Hi @azat-io 👋

For this bug, I believe that deploying a hotfix is appropriate.
azat-io: Okay, I'll create release. Thank you!

Patch:
diff --git a/utils/compare.ts b/utils/compare.ts
index f2281c7..1f47091 100644
--- a/utils/compare.ts
+++ b/utils/compare.ts
@@ -30,6 +30,10 @@ export let compare = <T extends SortingNode>({
   a,
   b,
 }: CompareParameters<T>): number => {
+  if (options.type === 'unsorted') {
+    return 0
+  }
+
   let finalNodeValueGetter = nodeValueGetter ?? ((node: T) => node.name)
   let compareValue = computeCompareValue({
     nodeValueGetter: finalNodeValueGetter,


Test patch:
diff --git a/test/rules/sort-imports.test.ts b/test/rules/sort-imports.test.ts
index 6e734b8..baa2758 100644
--- a/test/rules/sort-imports.test.ts
+++ b/test/rules/sort-imports.test.ts
@@ -1829,6 +1829,31 @@ describe(ruleName, () => {
           valid: [],
         },
       )
+
+      ruleTester.run(
+        `${ruleName}(${type}): does not sort side-effects and side-effect-style even with fallback sort`,
+        rule,
+        {
+          valid: [
+            {
+              options: [
+                {
+                  groups: ['side-effect', 'side-effect-style'],
+                  fallbackSort: { type: 'alphabetical' },
+                },
+              ],
+              code: dedent`
+                import 'b';
+                import 'a';
+
+                import 'b.css';
+                import 'a.css';
+              `,
+            },
+          ],
+          invalid: [],
+        },
+      )
     })
 
     ruleTester.run(