Repository: azat-io/eslint-plugin-perfectionist
Pull request #446 (2025-01-19 10:48:01)

refactor: reduces code duplication (2)
Continuation of https://github.com/azat-io/eslint-plugin-perfectionist/pull/445.

# Description

This PR further decreases code duplication by putting the error and fixes generation behind a `reportAllErrors` function.
It also creates a `shouldPartitionFunction` that checks both `partitionByComment` and `partitionByNewLine`.

# Tests updated

A couple of tests were updated:

## `sort-variables`

Some tests were making a circular dependency:

```ts
  let b = a,
  a = <any>b;
```
(`b` references `a` and `a` references `b`)

=>

```ts
  let b = 'b',
  a = <any>b;
```

Commit: [`ee0a819` (#446)](https://github.com/azat-io/eslint-plugin-perfectionist/pull/446/commits/ee0a8196a5be59f90f2002980b0618f2c07829eb#diff-f1654584a631196a4910bc61ab25073e4192b2a755673993e9f45eed2f49464d)

## `sort-objects`

There is a minor difference between how dependency errors were raised in `sort-objects` in comparison to `reportAllErrors`, leading to a few additional errors being raised. Outputs were not changed.

Commit: [`22adc71` (#446)](https://github.com/azat-io/eslint-plugin-perfectionist/pull/446/commits/22adc7168d3077e60f0143ea464614aa96752bfe#diff-b0cd59a5f8f908bc7e013e0403f96568fdfe19dd641f32083b1d5aae6db3e0ebL529)

### Explanation of the difference

#### Before in `sort-objects`

```ts
        if (
          leftIndex > rightIndex ||
          leftIndex >= indexOfRightExcludingEslintDisabled
        ) {
          firstUnorderedNodeDependentOnRight = getFirstUnorderedNodeDependentOn(
            right,
            nodes,
          )
          if (firstUnorderedNodeDependentOnRight) {
            messageIds.push('unexpectedObjectsDependencyOrder')
          } else {
            messageIds.push(
              leftNumber === rightNumber
                ? 'unexpectedObjectsOrder'
                : 'unexpectedObjectsGroupOrder',
            )
          }
        }
```

#### After in `sort-objects` (implementation of `reportAllErrors`)

```ts
          firstUnorderedNodeDependentOnRight = getFirstUnorderedNodeDependentOn(
            right,
            nodes,
          )

        if (
          firstUnorderedNodeDependentOnRight ||
          leftIndex > rightIndex ||
          leftIndex >= indexOfRightExcludingEslintDisabled
        ) {
          if (firstUnorderedNodeDependentOnRight) {
            messageIds.push('unexpectedObjectsDependencyOrder')
          } else {
            messageIds.push(
              leftNumber === rightNumber
                ? 'unexpectedObjectsOrder'
                : 'unexpectedObjectsGroupOrder',
            )
          }
        }
```

### What is the purpose of this pull request?

- [x] Other



Patch:
diff --git a/package.json b/package.json
index 590841c..ee9dcee 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "test:astro": "astro check",
     "test:css": "stylelint \"docs/**/*.{astro,svelte,css}\"",
     "test:format": "prettier --check \"**/*.{astro,svelte,js,ts,json,md,yml}\"",
-    "test:js": "eslint --flag unstable_ts_config .",
+    "test:js": "eslint --fix --flag unstable_ts_config .",
     "test:spelling": "cspell \"**/*\"",
     "test:svelte": "svelte-check",
     "test:types": "tsc --noEmit --pretty",
diff --git a/rules/sort-array-includes.ts b/rules/sort-array-includes.ts
index b6d1774..9154c5e 100644
--- a/rules/sort-array-includes.ts
+++ b/rules/sort-array-includes.ts
@@ -29,22 +29,16 @@ import { getMatchingContextOptions } from '../utils/get-matching-context-options
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 /**
  * Cache computed groups by modifiers and selectors for performance
@@ -272,16 +266,12 @@ export let sortArray = <MessageIds extends string>({
 
       let lastSortingNode = accumulator.at(-1)?.at(-1)
       if (
-        hasPartitionComment({
-          comments: getCommentsBefore({
-            node: element,
-            sourceCode,
-          }),
-          partitionByComment: options.partitionByComment,
-        }) ||
-        (options.partitionByNewLine &&
-          lastSortingNode &&
-          getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+        shouldPartition({
+          lastSortingNode,
+          sortingNode,
+          sourceCode,
+          options,
+        })
       ) {
         accumulator.push([])
       }
@@ -310,7 +300,7 @@ export let sortArray = <MessageIds extends string>({
       ),
     )
 
-    let sortNodesIgnoringEslintDisabledNodes = (
+    let sortNodesExcludingEslintDisabled = (
       ignoreEslintDisabledNodes: boolean,
     ): SortArrayIncludesSortingNode[] =>
       filteredGroupKindNodes.flatMap(groupedNodes =>
@@ -321,59 +311,13 @@ export let sortArray = <MessageIds extends string>({
         }),
       )
 
-    let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-    let sortedNodesExcludingEslintDisabled =
-      sortNodesIgnoringEslintDisabledNodes(true)
-
-    let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-    pairwise(nodes, (left, right) => {
-      let leftIndex = nodeIndexMap.get(left)!
-      let rightIndex = nodeIndexMap.get(right)!
-
-      let leftNumber = getGroupNumber(options.groups, left)
-      let rightNumber = getGroupNumber(options.groups, right)
-
-      let indexOfRightExcludingEslintDisabled =
-        sortedNodesExcludingEslintDisabled.indexOf(right)
-
-      let messageIds: MessageIds[] = []
-
-      if (
-        leftIndex > rightIndex ||
-        leftIndex >= indexOfRightExcludingEslintDisabled
-      ) {
-        messageIds.push(
-          leftNumber === rightNumber
-            ? availableMessageIds.unexpectedOrder
-            : availableMessageIds.unexpectedGroupOrder,
-        )
-      }
-
-      messageIds = [
-        ...messageIds,
-        ...getNewlinesErrors({
-          missedSpacingError: availableMessageIds.missedSpacingBetweenMembers,
-          extraSpacingError: availableMessageIds.extraSpacingBetweenMembers,
-          rightNum: rightNumber,
-          leftNum: leftNumber,
-          sourceCode,
-          options,
-          right,
-          left,
-        }),
-      ]
-
-      reportErrors({
-        sortedNodes: sortedNodesExcludingEslintDisabled,
-        sourceCode,
-        messageIds,
-        options,
-        context,
-        nodes,
-        right,
-        left,
-      })
+    reportAllErrors<MessageIds>({
+      sortNodesExcludingEslintDisabled,
+      availableMessageIds,
+      sourceCode,
+      options,
+      context,
+      nodes,
     })
   }
 }
diff --git a/rules/sort-classes.ts b/rules/sort-classes.ts
index f54dde9..3ca88eb 100644
--- a/rules/sort-classes.ts
+++ b/rules/sort-classes.ts
@@ -16,10 +16,6 @@ import {
   commonJsonSchemas,
   groupsJsonSchema,
 } from '../utils/common-json-schemas'
-import {
-  getFirstUnorderedNodeDependentOn,
-  sortNodesByDependencies,
-} from '../utils/sort-nodes-by-dependencies'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import {
@@ -31,24 +27,21 @@ import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-c
 import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { getOverloadSignatureGroups } from './sort-classes/get-overload-signature-groups'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
+import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { doesCustomGroupMatch } from './sort-classes/does-custom-group-match'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 import { matches } from '../utils/matches'
 
 /**
@@ -554,18 +547,14 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
             name,
           }
 
-          let lastMember = accumulator.at(-1)?.at(-1)
+          let lastSortingNode = accumulator.at(-1)?.at(-1)
 
           if (
-            (options.partitionByNewLine &&
-              lastMember &&
-              getLinesBetween(sourceCode, lastMember, sortingNode)) ||
-            hasPartitionComment({
-              comments: getCommentsBefore({
-                node: member,
-                sourceCode,
-              }),
-              partitionByComment: options.partitionByComment,
+            shouldPartition({
+              lastSortingNode,
+              sortingNode,
+              sourceCode,
+              options,
             })
           ) {
             accumulator.push([])
@@ -578,7 +567,7 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
         [[]],
       )
 
-      let sortNodesIgnoringEslintDisabledNodes = (
+      let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
       ): SortingNodeWithDependencies[] =>
         sortNodesByDependencies(
@@ -596,64 +585,22 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
             ignoreEslintDisabledNodes,
           },
         )
-      let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-      let sortedNodesExcludingEslintDisabled =
-        sortNodesIgnoringEslintDisabledNodes(true)
-      let nodes = formattedNodes.flat()
 
-      pairwise(nodes, (left, right) => {
-        let leftNumber = getGroupNumber(options.groups, left)
-        let rightNumber = getGroupNumber(options.groups, right)
-
-        let indexOfLeft = sortedNodes.indexOf(left)
-        let indexOfRight = sortedNodes.indexOf(right)
-        let indexOfRightExcludingEslintDisabled =
-          sortedNodesExcludingEslintDisabled.indexOf(right)
-
-        let messageIds: MESSAGE_ID[] = []
-        let firstUnorderedNodeDependentOnRight =
-          getFirstUnorderedNodeDependentOn(right, nodes)
-        if (
-          firstUnorderedNodeDependentOnRight ||
-          indexOfLeft > indexOfRight ||
-          indexOfLeft >= indexOfRightExcludingEslintDisabled
-        ) {
-          if (firstUnorderedNodeDependentOnRight) {
-            messageIds.push('unexpectedClassesDependencyOrder')
-          } else {
-            messageIds.push(
-              leftNumber === rightNumber
-                ? 'unexpectedClassesOrder'
-                : 'unexpectedClassesGroupOrder',
-            )
-          }
-        }
+      let nodes = formattedNodes.flat()
 
-        messageIds = [
-          ...messageIds,
-          ...getNewlinesErrors({
-            missedSpacingError: 'missedSpacingBetweenClassMembers',
-            extraSpacingError: 'extraSpacingBetweenClassMembers',
-            rightNum: rightNumber,
-            leftNum: leftNumber,
-            sourceCode,
-            options,
-            right,
-            left,
-          }),
-        ]
-
-        reportErrors({
-          sortedNodes: sortedNodesExcludingEslintDisabled,
-          firstUnorderedNodeDependentOnRight,
-          sourceCode,
-          messageIds,
-          options,
-          context,
-          nodes,
-          right,
-          left,
-        })
+      reportAllErrors<MESSAGE_ID>({
+        availableMessageIds: {
+          missedSpacingBetweenMembers: 'missedSpacingBetweenClassMembers',
+          extraSpacingBetweenMembers: 'extraSpacingBetweenClassMembers',
+          unexpectedDependencyOrder: 'unexpectedClassesDependencyOrder',
+          unexpectedGroupOrder: 'unexpectedClassesGroupOrder',
+          unexpectedOrder: 'unexpectedClassesOrder',
+        },
+        sortNodesExcludingEslintDisabled,
+        sourceCode,
+        options,
+        context,
+        nodes,
       })
     },
   }),
diff --git a/rules/sort-decorators.ts b/rules/sort-decorators.ts
index 9127083..5b0ceb5 100644
--- a/rules/sort-decorators.ts
+++ b/rules/sort-decorators.ts
@@ -19,21 +19,17 @@ import { validateGroupsConfiguration } from '../utils/validate-groups-configurat
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
 import { getDecoratorName } from './sort-decorators/get-decorator-name'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { getNodeDecorators } from '../utils/get-node-decorators'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 export type Options<T extends string = string> = [
   Partial<
@@ -206,18 +202,6 @@ let sortDecorators = (
 
   let formattedMembers: SortDecoratorsSortingNode[][] = decorators.reduce(
     (accumulator: SortDecoratorsSortingNode[][], decorator) => {
-      if (
-        hasPartitionComment({
-          comments: getCommentsBefore({
-            node: decorator,
-            sourceCode,
-          }),
-          partitionByComment: options.partitionByComment,
-        })
-      ) {
-        accumulator.push([])
-      }
-
       let { setCustomGroups, getGroup } = useGroups(options)
       let name = getDecoratorName(decorator)
 
@@ -231,6 +215,18 @@ let sortDecorators = (
         name,
       }
 
+      let lastSortingNode = accumulator.at(-1)?.at(-1)
+      if (
+        shouldPartition({
+          lastSortingNode,
+          sortingNode,
+          sourceCode,
+          options,
+        })
+      ) {
+        accumulator.push([])
+      }
+
       accumulator.at(-1)!.push(sortingNode)
 
       return accumulator
@@ -244,42 +240,18 @@ let sortDecorators = (
     formattedMembers.flatMap(nodes =>
       sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes }),
     )
-  let sortedNodes = sortNodesExcludingEslintDisabled(false)
-  let sortedNodesExcludingEslintDisabled =
-    sortNodesExcludingEslintDisabled(true)
-
   let nodes = formattedMembers.flat()
 
-  let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-  pairwise(nodes, (left, right) => {
-    let leftIndex = nodeIndexMap.get(left)!
-    let rightIndex = nodeIndexMap.get(right)!
-    let indexOfRightExcludingEslintDisabled =
-      sortedNodesExcludingEslintDisabled.indexOf(right)
-    if (
-      leftIndex < rightIndex &&
-      leftIndex < indexOfRightExcludingEslintDisabled
-    ) {
-      return
-    }
-    let leftNumber = getGroupNumber(options.groups, left)
-    let rightNumber = getGroupNumber(options.groups, right)
-
-    reportErrors({
-      messageIds: [
-        leftNumber === rightNumber
-          ? 'unexpectedDecoratorsOrder'
-          : 'unexpectedDecoratorsGroupOrder',
-      ],
-      sortedNodes: sortedNodesExcludingEslintDisabled,
-      ignoreFirstNodeHighestBlockComment: true,
-      sourceCode,
-      options,
-      context,
-      nodes,
-      right,
-      left,
-    })
+  reportAllErrors<MESSAGE_ID>({
+    availableMessageIds: {
+      unexpectedGroupOrder: 'unexpectedDecoratorsGroupOrder',
+      unexpectedOrder: 'unexpectedDecoratorsOrder',
+    },
+    ignoreFirstNodeHighestBlockComment: true,
+    sortNodesExcludingEslintDisabled,
+    sourceCode,
+    options,
+    context,
+    nodes,
   })
 }
diff --git a/rules/sort-enums.ts b/rules/sort-enums.ts
index 75427fd..8f209ba 100644
--- a/rules/sort-enums.ts
+++ b/rules/sort-enums.ts
@@ -13,27 +13,20 @@ import {
   buildTypeJsonSchema,
   commonJsonSchemas,
 } from '../utils/common-json-schemas'
-import {
-  getFirstUnorderedNodeDependentOn,
-  sortNodesByDependencies,
-} from '../utils/sort-nodes-by-dependencies'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
+import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getEnumMembers } from '../utils/get-enum-members'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 export type Options = [
   Partial<
@@ -149,16 +142,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
           }
 
           if (
-            hasPartitionComment({
-              comments: getCommentsBefore({
-                node: member,
-                sourceCode,
-              }),
-              partitionByComment: options.partitionByComment,
-            }) ||
-            (options.partitionByNewLine &&
-              lastSortingNode &&
-              getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+            shouldPartition({
+              lastSortingNode,
+              sortingNode,
+              sourceCode,
+              options,
+            })
           ) {
             accumulator.push([])
           }
@@ -206,7 +195,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
         order: options.order,
       }
 
-      let sortNodesIgnoringEslintDisabledNodes = (
+      let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
       ): SortEnumsSortingNode[] =>
         sortNodesByDependencies(
@@ -220,43 +209,16 @@ export default createEslintRule<Options, MESSAGE_ID>({
           },
         )
 
-      let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-      let sortedNodesExcludingEslintDisabled =
-        sortNodesIgnoringEslintDisabledNodes(true)
-
-      let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-      pairwise(nodes, (left, right) => {
-        let leftIndex = nodeIndexMap.get(left)!
-        let rightIndex = nodeIndexMap.get(right)!
-
-        let indexOfRightExcludingEslintDisabled =
-          sortedNodesExcludingEslintDisabled.indexOf(right)
-        if (
-          leftIndex < rightIndex &&
-          leftIndex < indexOfRightExcludingEslintDisabled
-        ) {
-          return
-        }
-
-        let firstUnorderedNodeDependentOnRight =
-          getFirstUnorderedNodeDependentOn(right, nodes)
-
-        reportErrors({
-          messageIds: [
-            firstUnorderedNodeDependentOnRight
-              ? 'unexpectedEnumsDependencyOrder'
-              : 'unexpectedEnumsOrder',
-          ],
-          sortedNodes: sortedNodesExcludingEslintDisabled,
-          firstUnorderedNodeDependentOnRight,
-          sourceCode,
-          options,
-          context,
-          nodes,
-          right,
-          left,
-        })
+      reportAllErrors<MESSAGE_ID>({
+        availableMessageIds: {
+          unexpectedDependencyOrder: 'unexpectedEnumsDependencyOrder',
+          unexpectedOrder: 'unexpectedEnumsOrder',
+        },
+        sortNodesExcludingEslintDisabled,
+        sourceCode,
+        options,
+        context,
+        nodes,
       })
     },
   }),
diff --git a/rules/sort-exports.ts b/rules/sort-exports.ts
index 8270063..5216c40 100644
--- a/rules/sort-exports.ts
+++ b/rules/sort-exports.ts
@@ -15,18 +15,14 @@ import {
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 type Options = [
   Partial<
@@ -68,7 +64,6 @@ export default createEslintRule<Options, MESSAGE_ID>({
     validateCustomSortConfiguration(options)
 
     let sourceCode = getSourceCode(context)
-    let partitionComment = options.partitionByComment
     let eslintDisabledLines = getEslintDisabledLines({
       ruleName: context.id,
       sourceCode,
@@ -90,21 +85,18 @@ export default createEslintRule<Options, MESSAGE_ID>({
         node,
       }
       let lastNode = parts.at(-1)?.at(-1)
+
       if (
-        (partitionComment &&
-          hasPartitionComment({
-            comments: getCommentsBefore({
-              sourceCode,
-              node,
-            }),
-            partitionByComment: options.partitionByComment,
-          })) ||
-        (options.partitionByNewLine &&
-          lastNode &&
-          getLinesBetween(sourceCode, lastNode, sortingNode))
+        shouldPartition({
+          lastSortingNode: lastNode,
+          sortingNode,
+          sourceCode,
+          options,
+        })
       ) {
         parts.push([])
       }
+
       parts.at(-1)!.push(sortingNode)
     }
 
@@ -135,35 +127,15 @@ export default createEslintRule<Options, MESSAGE_ID>({
               }),
             )
 
-          let sortedNodes = sortNodesExcludingEslintDisabled(false)
-          let sortedNodesExcludingEslintDisabled =
-            sortNodesExcludingEslintDisabled(true)
-
-          let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-          pairwise(nodes, (left, right) => {
-            let leftIndex = nodeIndexMap.get(left)!
-            let rightIndex = nodeIndexMap.get(right)!
-
-            let indexOfRightExcludingEslintDisabled =
-              sortedNodesExcludingEslintDisabled.indexOf(right)
-            if (
-              leftIndex < rightIndex &&
-              leftIndex < indexOfRightExcludingEslintDisabled
-            ) {
-              return
-            }
-
-            reportErrors({
-              sortedNodes: sortedNodesExcludingEslintDisabled,
-              messageIds: ['unexpectedExportsOrder'],
-              sourceCode,
-              options,
-              context,
-              nodes,
-              right,
-              left,
-            })
+          reportAllErrors<MESSAGE_ID>({
+            availableMessageIds: {
+              unexpectedOrder: 'unexpectedExportsOrder',
+            },
+            sortNodesExcludingEslintDisabled,
+            sourceCode,
+            options,
+            context,
+            nodes,
           })
         }
       },
diff --git a/rules/sort-heritage-clauses.ts b/rules/sort-heritage-clauses.ts
index f48d2e7..fddce00 100644
--- a/rules/sort-heritage-clauses.ts
+++ b/rules/sort-heritage-clauses.ts
@@ -14,18 +14,15 @@ import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-c
 import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 export type Options<T extends string = string> = [
   Partial<
@@ -144,41 +141,16 @@ let sortHeritageClauses = (
   ): SortingNode[] =>
     sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
 
-  let sortedNodes = sortNodesExcludingEslintDisabled(false)
-  let sortedNodesExcludingEslintDisabled =
-    sortNodesExcludingEslintDisabled(true)
-
-  let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-  pairwise(nodes, (left, right) => {
-    let leftIndex = nodeIndexMap.get(left)!
-    let rightIndex = nodeIndexMap.get(right)!
-
-    let indexOfRightExcludingEslintDisabled =
-      sortedNodesExcludingEslintDisabled.indexOf(right)
-    if (
-      leftIndex < rightIndex &&
-      leftIndex < indexOfRightExcludingEslintDisabled
-    ) {
-      return
-    }
-    let leftNumber = getGroupNumber(options.groups, left)
-    let rightNumber = getGroupNumber(options.groups, right)
-
-    reportErrors({
-      messageIds: [
-        leftNumber === rightNumber
-          ? 'unexpectedHeritageClausesOrder'
-          : 'unexpectedHeritageClausesGroupOrder',
-      ],
-      sortedNodes: sortedNodesExcludingEslintDisabled,
-      sourceCode,
-      options,
-      context,
-      nodes,
-      right,
-      left,
-    })
+  reportAllErrors<MESSAGE_ID>({
+    availableMessageIds: {
+      unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
+      unexpectedOrder: 'unexpectedHeritageClausesOrder',
+    },
+    sortNodesExcludingEslintDisabled,
+    sourceCode,
+    options,
+    context,
+    nodes,
   })
 }
 
diff --git a/rules/sort-imports.ts b/rules/sort-imports.ts
index 818f1f9..0f07fea 100644
--- a/rules/sort-imports.ts
+++ b/rules/sort-imports.ts
@@ -24,22 +24,16 @@ import { getOptionsWithCleanGroups } from '../utils/get-options-with-clean-group
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { getTypescriptImport } from './sort-imports/get-typescript-import'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 import { matches } from '../utils/matches'
 
 export type Options<T extends string = string> = [
@@ -475,16 +469,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
           let lastSortingNode = lastGroup?.at(-1)
 
           if (
-            hasPartitionComment({
-              comments: getCommentsBefore({
-                node: sortingNode.node,
-                sourceCode,
-              }),
-              partitionByComment: options.partitionByComment,
+            shouldPartition({
+              lastSortingNode,
+              sortingNode,
+              sourceCode,
+              options,
             }) ||
-            (options.partitionByNewLine &&
-              lastSortingNode &&
-              getLinesBetween(sourceCode, lastSortingNode, sortingNode)) ||
             (lastSortingNode &&
               hasContentBetweenNodes(lastSortingNode, sortingNode))
           ) {
@@ -511,65 +501,21 @@ export default createEslintRule<Options, MESSAGE_ID>({
               ignoreEslintDisabledNodes,
             })
 
-          let sortedNodes = sortNodesExcludingEslintDisabled(false)
-          let sortedNodesExcludingEslintDisabled =
-            sortNodesExcludingEslintDisabled(true)
-
-          let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-          pairwise(nodes, (left, right) => {
-            let leftNumber = getGroupNumber(options.groups, left)
-            let rightNumber = getGroupNumber(options.groups, right)
-
-            let leftIndex = nodeIndexMap.get(left)!
-            let rightIndex = nodeIndexMap.get(right)!
-
-            let indexOfRightExcludingEslintDisabled =
-              sortedNodesExcludingEslintDisabled.indexOf(right)
-
-            let messageIds: MESSAGE_ID[] = []
-
-            if (
-              leftIndex > rightIndex ||
-              leftIndex >= indexOfRightExcludingEslintDisabled
-            ) {
-              messageIds.push(
-                leftNumber === rightNumber
-                  ? 'unexpectedImportsOrder'
-                  : 'unexpectedImportsGroupOrder',
-              )
-            }
-
-            messageIds = [
-              ...messageIds,
-              ...getNewlinesErrors({
-                options: {
-                  ...options,
-                  customGroups: [],
-                },
-                missedSpacingError: 'missedSpacingBetweenImports',
-                extraSpacingError: 'extraSpacingBetweenImports',
-                rightNum: rightNumber,
-                leftNum: leftNumber,
-                sourceCode,
-                right,
-                left,
-              }),
-            ]
-
-            reportErrors({
-              options: {
-                ...options,
-                customGroups: [],
-              },
-              sortedNodes: sortedNodesExcludingEslintDisabled,
-              sourceCode,
-              messageIds,
-              context,
-              nodes,
-              right,
-              left,
-            })
+          reportAllErrors<MESSAGE_ID>({
+            availableMessageIds: {
+              missedSpacingBetweenMembers: 'missedSpacingBetweenImports',
+              extraSpacingBetweenMembers: 'extraSpacingBetweenImports',
+              unexpectedGroupOrder: 'unexpectedImportsGroupOrder',
+              unexpectedOrder: 'unexpectedImportsOrder',
+            },
+            options: {
+              ...options,
+              customGroups: [],
+            },
+            sortNodesExcludingEslintDisabled,
+            sourceCode,
+            context,
+            nodes,
           })
         }
       },
diff --git a/rules/sort-jsx-props.ts b/rules/sort-jsx-props.ts
index cbd664f..c797e3d 100644
--- a/rules/sort-jsx-props.ts
+++ b/rules/sort-jsx-props.ts
@@ -16,19 +16,15 @@ import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-c
 import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
-import { pairwise } from '../utils/pairwise'
 import { complete } from '../utils/complete'
 import { matches } from '../utils/matches'
 
@@ -141,9 +137,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
 
             let lastSortingNode = accumulator.at(-1)?.at(-1)
             if (
-              options.partitionByNewLine &&
-              lastSortingNode &&
-              getLinesBetween(sourceCode, lastSortingNode, sortingNode)
+              shouldPartition({
+                lastSortingNode,
+                sortingNode,
+                sourceCode,
+                options,
+              })
             ) {
               accumulator.push([])
             }
@@ -160,59 +159,19 @@ export default createEslintRule<Options, MESSAGE_ID>({
           ignoreEslintDisabledNodes: boolean,
         ): SortingNode[] =>
           sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
-        let sortedNodes = sortNodesExcludingEslintDisabled(false)
-        let sortedNodesExcludingEslintDisabled =
-          sortNodesExcludingEslintDisabled(true)
 
-        let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-        pairwise(nodes, (left, right) => {
-          let leftIndex = nodeIndexMap.get(left)!
-          let rightIndex = nodeIndexMap.get(right)!
-
-          let indexOfRightExcludingEslintDisabled =
-            sortedNodesExcludingEslintDisabled.indexOf(right)
-
-          let leftNumber = getGroupNumber(options.groups, left)
-          let rightNumber = getGroupNumber(options.groups, right)
-
-          let messageIds: MESSAGE_ID[] = []
-
-          if (
-            leftIndex > rightIndex ||
-            leftIndex >= indexOfRightExcludingEslintDisabled
-          ) {
-            messageIds.push(
-              leftNumber === rightNumber
-                ? 'unexpectedJSXPropsOrder'
-                : 'unexpectedJSXPropsGroupOrder',
-            )
-          }
-
-          messageIds = [
-            ...messageIds,
-            ...getNewlinesErrors({
-              missedSpacingError: 'missedSpacingBetweenJSXPropsMembers',
-              extraSpacingError: 'extraSpacingBetweenJSXPropsMembers',
-              rightNum: rightNumber,
-              leftNum: leftNumber,
-              sourceCode,
-              options,
-              right,
-              left,
-            }),
-          ]
-
-          reportErrors({
-            sortedNodes: sortedNodesExcludingEslintDisabled,
-            sourceCode,
-            messageIds,
-            options,
-            context,
-            nodes,
-            right,
-            left,
-          })
+        reportAllErrors<MESSAGE_ID>({
+          availableMessageIds: {
+            missedSpacingBetweenMembers: 'missedSpacingBetweenJSXPropsMembers',
+            extraSpacingBetweenMembers: 'extraSpacingBetweenJSXPropsMembers',
+            unexpectedGroupOrder: 'unexpectedJSXPropsGroupOrder',
+            unexpectedOrder: 'unexpectedJSXPropsOrder',
+          },
+          sortNodesExcludingEslintDisabled,
+          sourceCode,
+          options,
+          context,
+          nodes,
         })
       }
     },
diff --git a/rules/sort-maps.ts b/rules/sort-maps.ts
index bebc505..5a96371 100644
--- a/rules/sort-maps.ts
+++ b/rules/sort-maps.ts
@@ -22,23 +22,17 @@ 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'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { singleCustomGroupJsonSchema } from './sort-maps/types'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 type MESSAGE_ID =
   | 'missedSpacingBetweenMapElementsMembers'
@@ -160,16 +154,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
           }
 
           if (
-            hasPartitionComment({
-              comments: getCommentsBefore({
-                node: element,
-                sourceCode,
-              }),
-              partitionByComment: options.partitionByComment,
-            }) ||
-            (options.partitionByNewLine &&
-              lastSortingNode &&
-              getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+            shouldPartition({
+              lastSortingNode,
+              sortingNode,
+              sourceCode,
+              options,
+            })
           ) {
             formattedMembers.push([])
           }
@@ -186,59 +176,21 @@ export default createEslintRule<Options, MESSAGE_ID>({
                 getCustomGroupsCompareOptions(options, groupNumber),
               ignoreEslintDisabledNodes,
             })
-          let sortedNodes = sortNodesExcludingEslintDisabled(false)
-          let sortedNodesExcludingEslintDisabled =
-            sortNodesExcludingEslintDisabled(true)
-
-          let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-          pairwise(nodes, (left, right) => {
-            let leftIndex = nodeIndexMap.get(left)!
-            let rightIndex = nodeIndexMap.get(right)!
 
-            let leftNumber = getGroupNumber(options.groups, left)
-            let rightNumber = getGroupNumber(options.groups, right)
-
-            let indexOfRightExcludingEslintDisabled =
-              sortedNodesExcludingEslintDisabled.indexOf(right)
-
-            let messageIds: MESSAGE_ID[] = []
-
-            if (
-              leftIndex > rightIndex ||
-              leftIndex >= indexOfRightExcludingEslintDisabled
-            ) {
-              messageIds.push(
-                leftNumber === rightNumber
-                  ? 'unexpectedMapElementsOrder'
-                  : 'unexpectedMapElementsGroupOrder',
-              )
-            }
-
-            messageIds = [
-              ...messageIds,
-              ...getNewlinesErrors({
-                missedSpacingError: 'missedSpacingBetweenMapElementsMembers',
-                extraSpacingError: 'extraSpacingBetweenMapElementsMembers',
-                rightNum: rightNumber,
-                leftNum: leftNumber,
-                sourceCode,
-                options,
-                right,
-                left,
-              }),
-            ]
-
-            reportErrors({
-              sortedNodes: sortedNodesExcludingEslintDisabled,
-              sourceCode,
-              messageIds,
-              options,
-              context,
-              nodes,
-              right,
-              left,
-            })
+          reportAllErrors<MESSAGE_ID>({
+            availableMessageIds: {
+              missedSpacingBetweenMembers:
+                'missedSpacingBetweenMapElementsMembers',
+              extraSpacingBetweenMembers:
+                'extraSpacingBetweenMapElementsMembers',
+              unexpectedGroupOrder: 'unexpectedMapElementsGroupOrder',
+              unexpectedOrder: 'unexpectedMapElementsOrder',
+            },
+            sortNodesExcludingEslintDisabled,
+            sourceCode,
+            options,
+            context,
+            nodes,
           })
         }
       }
diff --git a/rules/sort-modules.ts b/rules/sort-modules.ts
index 483581b..a56b1cd 100644
--- a/rules/sort-modules.ts
+++ b/rules/sort-modules.ts
@@ -19,10 +19,6 @@ import {
   commonJsonSchemas,
   groupsJsonSchema,
 } from '../utils/common-json-schemas'
-import {
-  getFirstUnorderedNodeDependentOn,
-  sortNodesByDependencies,
-} from '../utils/sort-nodes-by-dependencies'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import {
@@ -33,27 +29,23 @@ import {
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
+import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { doesCustomGroupMatch } from './sort-modules/does-custom-group-match'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { getNodeDecorators } from '../utils/get-node-decorators'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getEnumMembers } from '../utils/get-enum-members'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 /**
  * Cache computed groups by modifiers and selectors for performance
@@ -338,25 +330,23 @@ let analyzeModule = ({
       name,
       node,
     }
+
     let lastSortingNode = formattedNodes.at(-1)?.at(-1)
     if (
-      (options.partitionByNewLine &&
-        lastSortingNode &&
-        getLinesBetween(sourceCode, lastSortingNode, sortingNode)) ||
-      hasPartitionComment({
-        comments: getCommentsBefore({
-          sourceCode,
-          node,
-        }),
-        partitionByComment: options.partitionByComment,
+      shouldPartition({
+        lastSortingNode,
+        sortingNode,
+        sourceCode,
+        options,
       })
     ) {
       formattedNodes.push([])
     }
+
     formattedNodes.at(-1)?.push(sortingNode)
   }
 
-  let sortNodesIgnoringEslintDisabledNodes = (
+  let sortNodesExcludingEslintDisabled = (
     ignoreEslintDisabledNodes: boolean,
   ): SortingNodeWithDependencies[] =>
     sortNodesByDependencies(
@@ -374,69 +364,21 @@ let analyzeModule = ({
         ignoreEslintDisabledNodes,
       },
     )
-  let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-  let sortedNodesExcludingEslintDisabled =
-    sortNodesIgnoringEslintDisabledNodes(true)
   let nodes = formattedNodes.flat()
 
-  let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-  pairwise(nodes, (left, right) => {
-    let leftNumber = getGroupNumber(options.groups, left)
-    let rightNumber = getGroupNumber(options.groups, right)
-
-    let leftIndex = nodeIndexMap.get(left)!
-    let rightIndex = nodeIndexMap.get(right)!
-
-    let indexOfRightExcludingEslintDisabled =
-      sortedNodesExcludingEslintDisabled.indexOf(right)
-
-    let messageIds: MESSAGE_ID[] = []
-    let firstUnorderedNodeDependentOnRight = getFirstUnorderedNodeDependentOn(
-      right,
-      nodes,
-    )
-    if (
-      firstUnorderedNodeDependentOnRight ||
-      leftIndex > rightIndex ||
-      leftIndex >= indexOfRightExcludingEslintDisabled
-    ) {
-      if (firstUnorderedNodeDependentOnRight) {
-        messageIds.push('unexpectedModulesDependencyOrder')
-      } else {
-        messageIds.push(
-          leftNumber === rightNumber
-            ? 'unexpectedModulesOrder'
-            : 'unexpectedModulesGroupOrder',
-        )
-      }
-    }
-
-    messageIds = [
-      ...messageIds,
-      ...getNewlinesErrors({
-        missedSpacingError: 'missedSpacingBetweenModulesMembers',
-        extraSpacingError: 'extraSpacingBetweenModulesMembers',
-        rightNum: rightNumber,
-        leftNum: leftNumber,
-        sourceCode,
-        options,
-        right,
-        left,
-      }),
-    ]
-
-    reportErrors({
-      sortedNodes: sortedNodesExcludingEslintDisabled,
-      firstUnorderedNodeDependentOnRight,
-      sourceCode,
-      messageIds,
-      options,
-      context,
-      nodes,
-      right,
-      left,
-    })
+  reportAllErrors<MESSAGE_ID>({
+    availableMessageIds: {
+      missedSpacingBetweenMembers: 'missedSpacingBetweenModulesMembers',
+      extraSpacingBetweenMembers: 'extraSpacingBetweenModulesMembers',
+      unexpectedDependencyOrder: 'unexpectedModulesDependencyOrder',
+      unexpectedGroupOrder: 'unexpectedModulesGroupOrder',
+      unexpectedOrder: 'unexpectedModulesOrder',
+    },
+    sortNodesExcludingEslintDisabled,
+    sourceCode,
+    options,
+    context,
+    nodes,
   })
 }
 
diff --git a/rules/sort-named-exports.ts b/rules/sort-named-exports.ts
index eb6c824..5c6bee7 100644
--- a/rules/sort-named-exports.ts
+++ b/rules/sort-named-exports.ts
@@ -15,19 +15,15 @@ import {
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 type Options = [
   Partial<
@@ -100,17 +96,14 @@ export default createEslintRule<Options, MESSAGE_ID>({
           groupKind,
           name,
         }
+
         if (
-          hasPartitionComment({
-            comments: getCommentsBefore({
-              node: specifier,
-              sourceCode,
-            }),
-            partitionByComment: options.partitionByComment,
-          }) ||
-          (options.partitionByNewLine &&
-            lastSortingNode &&
-            getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+          shouldPartition({
+            lastSortingNode,
+            sortingNode,
+            sourceCode,
+            options,
+          })
         ) {
           formattedMembers.push([])
         }
@@ -143,35 +136,15 @@ export default createEslintRule<Options, MESSAGE_ID>({
             }),
           )
 
-        let sortedNodes = sortNodesExcludingEslintDisabled(false)
-        let sortedNodesExcludingEslintDisabled =
-          sortNodesExcludingEslintDisabled(true)
-
-        let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-        pairwise(nodes, (left, right) => {
-          let leftIndex = nodeIndexMap.get(left)!
-          let rightIndex = nodeIndexMap.get(right)!
-
-          let indexOfRightExcludingEslintDisabled =
-            sortedNodesExcludingEslintDisabled.indexOf(right)
-          if (
-            leftIndex < rightIndex &&
-            leftIndex < indexOfRightExcludingEslintDisabled
-          ) {
-            return
-          }
-
-          reportErrors({
-            sortedNodes: sortedNodesExcludingEslintDisabled,
-            messageIds: ['unexpectedNamedExportsOrder'],
-            sourceCode,
-            options,
-            context,
-            nodes,
-            right,
-            left,
-          })
+        reportAllErrors<MESSAGE_ID>({
+          availableMessageIds: {
+            unexpectedOrder: 'unexpectedNamedExportsOrder',
+          },
+          sortNodesExcludingEslintDisabled,
+          sourceCode,
+          options,
+          context,
+          nodes,
         })
       }
     },
diff --git a/rules/sort-named-imports.ts b/rules/sort-named-imports.ts
index 5fd350a..ce213da 100644
--- a/rules/sort-named-imports.ts
+++ b/rules/sort-named-imports.ts
@@ -15,19 +15,15 @@ import {
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 type Options = [
   Partial<
@@ -110,16 +106,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
         }
 
         if (
-          hasPartitionComment({
-            comments: getCommentsBefore({
-              node: specifier,
-              sourceCode,
-            }),
-            partitionByComment: options.partitionByComment,
-          }) ||
-          (options.partitionByNewLine &&
-            lastSortingNode &&
-            getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+          shouldPartition({
+            lastSortingNode,
+            sortingNode,
+            sourceCode,
+            options,
+          })
         ) {
           formattedMembers.push([])
         }
@@ -152,35 +144,15 @@ export default createEslintRule<Options, MESSAGE_ID>({
             }),
           )
 
-        let sortedNodes = sortNodesExcludingEslintDisabled(false)
-        let sortedNodesExcludingEslintDisabled =
-          sortNodesExcludingEslintDisabled(true)
-
-        let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-        pairwise(nodes, (left, right) => {
-          let leftIndex = nodeIndexMap.get(left)!
-          let rightIndex = nodeIndexMap.get(right)!
-
-          let indexOfRightExcludingEslintDisabled =
-            sortedNodesExcludingEslintDisabled.indexOf(right)
-          if (
-            leftIndex < rightIndex &&
-            leftIndex < indexOfRightExcludingEslintDisabled
-          ) {
-            return
-          }
-
-          reportErrors({
-            sortedNodes: sortedNodesExcludingEslintDisabled,
-            messageIds: ['unexpectedNamedImportsOrder'],
-            sourceCode,
-            options,
-            context,
-            nodes,
-            right,
-            left,
-          })
+        reportAllErrors<MESSAGE_ID>({
+          availableMessageIds: {
+            unexpectedOrder: 'unexpectedNamedImportsOrder',
+          },
+          sortNodesExcludingEslintDisabled,
+          sourceCode,
+          options,
+          context,
+          nodes,
         })
       }
     },
diff --git a/rules/sort-object-types.ts b/rules/sort-object-types.ts
index d020924..bc7d35e 100644
--- a/rules/sort-object-types.ts
+++ b/rules/sort-object-types.ts
@@ -32,23 +32,17 @@ import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isMemberOptional } from './sort-object-types/is-member-optional'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
 import { isNodeFunctionType } from '../utils/is-node-function-type'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 import { matches } from '../utils/matches'
 
 /**
@@ -340,17 +334,12 @@ export let sortObjectTypeElements = <MessageIds extends string>({
       }
 
       if (
-        (options.partitionByComment &&
-          hasPartitionComment({
-            comments: getCommentsBefore({
-              node: typeElement,
-              sourceCode,
-            }),
-            partitionByComment: options.partitionByComment,
-          })) ||
-        (options.partitionByNewLine &&
-          lastSortingNode &&
-          getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+        shouldPartition({
+          lastSortingNode,
+          sortingNode,
+          sourceCode,
+          options,
+        })
       ) {
         lastGroup = []
         accumulator.push(lastGroup)
@@ -388,59 +377,14 @@ export let sortObjectTypeElements = <MessageIds extends string>({
           ignoreEslintDisabledNodes,
         }),
       )
-    let sortedNodes = sortNodesExcludingEslintDisabled(false)
-    let sortedNodesExcludingEslintDisabled =
-      sortNodesExcludingEslintDisabled(true)
-
-    let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-    pairwise(nodes, (left, right) => {
-      let leftNumber = getGroupNumber(options.groups, left)
-      let rightNumber = getGroupNumber(options.groups, right)
 
-      let leftIndex = nodeIndexMap.get(left)!
-      let rightIndex = nodeIndexMap.get(right)!
-
-      let indexOfRightExcludingEslintDisabled =
-        sortedNodesExcludingEslintDisabled.indexOf(right)
-
-      let messageIds: MessageIds[] = []
-
-      if (
-        leftIndex > rightIndex ||
-        leftIndex >= indexOfRightExcludingEslintDisabled
-      ) {
-        messageIds.push(
-          leftNumber === rightNumber
-            ? availableMessageIds.unexpectedOrder
-            : availableMessageIds.unexpectedGroupOrder,
-        )
-      }
-
-      messageIds = [
-        ...messageIds,
-        ...getNewlinesErrors({
-          missedSpacingError: availableMessageIds.missedSpacingBetweenMembers,
-          extraSpacingError: availableMessageIds.extraSpacingBetweenMembers,
-          rightNum: rightNumber,
-          leftNum: leftNumber,
-          sourceCode,
-          options,
-          right,
-          left,
-        }),
-      ]
-
-      reportErrors({
-        sortedNodes: sortedNodesExcludingEslintDisabled,
-        messageIds,
-        sourceCode,
-        options,
-        context,
-        nodes,
-        right,
-        left,
-      })
+    reportAllErrors<MessageIds>({
+      sortNodesExcludingEslintDisabled,
+      availableMessageIds,
+      sourceCode,
+      options,
+      context,
+      nodes,
     })
   }
 }
diff --git a/rules/sort-objects.ts b/rules/sort-objects.ts
index 07deda0..3b3fe64 100644
--- a/rules/sort-objects.ts
+++ b/rules/sort-objects.ts
@@ -15,10 +15,6 @@ import {
   commonJsonSchemas,
   groupsJsonSchema,
 } from '../utils/common-json-schemas'
-import {
-  getFirstUnorderedNodeDependentOn,
-  sortNodesByDependencies,
-} from '../utils/sort-nodes-by-dependencies'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
@@ -26,28 +22,23 @@ import { getFirstNodeParentWithType } from './sort-objects/get-first-node-parent
 import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
+import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { doesCustomGroupMatch } from './sort-objects/does-custom-group-match'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { singleCustomGroupJsonSchema } from './sort-objects/types'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
 import { allModifiers, allSelectors } from './sort-objects/types'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { useGroups } from '../utils/use-groups'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 import { matches } from '../utils/matches'
 
 /**
@@ -309,7 +300,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
               return accumulator
             }
 
-            let lastProperty = accumulator.at(-1)?.at(-1)
+            let lastSortingNode = accumulator.at(-1)?.at(-1)
 
             let dependencies: string[] = []
 
@@ -379,7 +370,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
               })
             }
 
-            let propertySortingNode: SortingNodeWithDependencies = {
+            let sortingNode: SortingNodeWithDependencies = {
               isEslintDisabled: isNodeEslintDisabled(
                 property,
                 eslintDisabledLines,
@@ -392,25 +383,17 @@ export default createEslintRule<Options, MESSAGE_ID>({
             }
 
             if (
-              (options.partitionByNewLine &&
-                lastProperty &&
-                getLinesBetween(
-                  sourceCode,
-                  lastProperty,
-                  propertySortingNode,
-                )) ||
-              hasPartitionComment({
-                comments: getCommentsBefore({
-                  node: property,
-                  sourceCode,
-                }),
-                partitionByComment: options.partitionByComment,
+              shouldPartition({
+                lastSortingNode,
+                sortingNode,
+                sourceCode,
+                options,
               })
             ) {
               accumulator.push([])
             }
 
-            accumulator.at(-1)!.push(propertySortingNode)
+            accumulator.at(-1)!.push(sortingNode)
 
             return accumulator
           },
@@ -424,7 +407,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
         !options.destructuredObjects.groups
           ? sortNodes
           : sortNodesByGroups
-      let sortNodesIgnoringEslintDisabledNodes = (
+      let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
       ): SortingNodeWithDependencies[] =>
         sortNodesByDependencies(
@@ -439,73 +422,21 @@ export default createEslintRule<Options, MESSAGE_ID>({
             ignoreEslintDisabledNodes,
           },
         )
-      let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-      let sortedNodesExcludingEslintDisabled =
-        sortNodesIgnoringEslintDisabledNodes(true)
-
       let nodes = formattedMembers.flat()
 
-      let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-      pairwise(nodes, (left, right) => {
-        let leftNumber = getGroupNumber(options.groups, left)
-        let rightNumber = getGroupNumber(options.groups, right)
-
-        let leftIndex = nodeIndexMap.get(left)!
-        let rightIndex = nodeIndexMap.get(right)!
-
-        let indexOfRightExcludingEslintDisabled =
-          sortedNodesExcludingEslintDisabled.indexOf(right)
-
-        let messageIds: MESSAGE_ID[] = []
-        let firstUnorderedNodeDependentOnRight:
-          | SortingNodeWithDependencies
-          | undefined
-
-        if (
-          leftIndex > rightIndex ||
-          leftIndex >= indexOfRightExcludingEslintDisabled
-        ) {
-          firstUnorderedNodeDependentOnRight = getFirstUnorderedNodeDependentOn(
-            right,
-            nodes,
-          )
-          if (firstUnorderedNodeDependentOnRight) {
-            messageIds.push('unexpectedObjectsDependencyOrder')
-          } else {
-            messageIds.push(
-              leftNumber === rightNumber
-                ? 'unexpectedObjectsOrder'
-                : 'unexpectedObjectsGroupOrder',
-            )
-          }
-        }
-
-        messageIds = [
-          ...messageIds,
-          ...getNewlinesErrors({
-            missedSpacingError: 'missedSpacingBetweenObjectMembers',
-            extraSpacingError: 'extraSpacingBetweenObjectMembers',
-            rightNum: rightNumber,
-            leftNum: leftNumber,
-            sourceCode,
-            options,
-            right,
-            left,
-          }),
-        ]
-
-        reportErrors({
-          sortedNodes: sortedNodesExcludingEslintDisabled,
-          firstUnorderedNodeDependentOnRight,
-          messageIds,
-          sourceCode,
-          options,
-          context,
-          nodes,
-          right,
-          left,
-        })
+      reportAllErrors<MESSAGE_ID>({
+        availableMessageIds: {
+          missedSpacingBetweenMembers: 'missedSpacingBetweenObjectMembers',
+          extraSpacingBetweenMembers: 'extraSpacingBetweenObjectMembers',
+          unexpectedDependencyOrder: 'unexpectedObjectsDependencyOrder',
+          unexpectedGroupOrder: 'unexpectedObjectsGroupOrder',
+          unexpectedOrder: 'unexpectedObjectsOrder',
+        },
+        sortNodesExcludingEslintDisabled,
+        sourceCode,
+        options,
+        context,
+        nodes,
       })
     }
 
diff --git a/rules/sort-union-types.ts b/rules/sort-union-types.ts
index 3c3d1a6..77796e7 100644
--- a/rules/sort-union-types.ts
+++ b/rules/sort-union-types.ts
@@ -22,21 +22,15 @@ import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-c
 import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
-import { getCommentsBefore } from '../utils/get-comments-before'
-import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
-import { getGroupNumber } from '../utils/get-group-number'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { useGroups } from '../utils/use-groups'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 export type Options = [
   Partial<
@@ -255,18 +249,15 @@ export let sortUnionOrIntersectionTypes = <MessageIds extends string>({
         group: getGroup(),
         node: type,
       }
+
       if (
-        hasPartitionComment({
-          comments: getCommentsBefore({
-            tokenValueToIgnoreBefore,
-            node: type,
-            sourceCode,
-          }),
-          partitionByComment: options.partitionByComment,
-        }) ||
-        (options.partitionByNewLine &&
-          lastSortingNode &&
-          getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+        shouldPartition({
+          tokenValueToIgnoreBefore,
+          lastSortingNode,
+          sortingNode,
+          sourceCode,
+          options,
+        })
       ) {
         lastGroup = []
         accumulator.push(lastGroup)
@@ -283,59 +274,14 @@ export let sortUnionOrIntersectionTypes = <MessageIds extends string>({
       ignoreEslintDisabledNodes: boolean,
     ): SortingNode[] =>
       sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
-    let sortedNodes = sortNodesExcludingEslintDisabled(false)
-    let sortedNodesExcludingEslintDisabled =
-      sortNodesExcludingEslintDisabled(true)
-
-    let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-    pairwise(nodes, (left, right) => {
-      let leftNumber = getGroupNumber(options.groups, left)
-      let rightNumber = getGroupNumber(options.groups, right)
 
-      let leftIndex = nodeIndexMap.get(left)!
-      let rightIndex = nodeIndexMap.get(right)!
-
-      let indexOfRightExcludingEslintDisabled =
-        sortedNodesExcludingEslintDisabled.indexOf(right)
-
-      let messageIds: MessageIds[] = []
-
-      if (
-        leftIndex > rightIndex ||
-        leftIndex >= indexOfRightExcludingEslintDisabled
-      ) {
-        messageIds.push(
-          leftNumber === rightNumber
-            ? availableMessageIds.unexpectedOrder
-            : availableMessageIds.unexpectedGroupOrder,
-        )
-      }
-
-      messageIds = [
-        ...messageIds,
-        ...getNewlinesErrors({
-          missedSpacingError: availableMessageIds.missedSpacingBetweenMembers,
-          extraSpacingError: availableMessageIds.extraSpacingBetweenMembers,
-          rightNum: rightNumber,
-          leftNum: leftNumber,
-          sourceCode,
-          options,
-          right,
-          left,
-        }),
-      ]
-
-      reportErrors({
-        sortedNodes: sortedNodesExcludingEslintDisabled,
-        messageIds,
-        sourceCode,
-        options,
-        context,
-        nodes,
-        right,
-        left,
-      })
+    reportAllErrors<MessageIds>({
+      sortNodesExcludingEslintDisabled,
+      availableMessageIds,
+      sourceCode,
+      options,
+      context,
+      nodes,
     })
   }
 }
diff --git a/rules/sort-variable-declarations.ts b/rules/sort-variable-declarations.ts
index b42c6b9..1b9bdaf 100644
--- a/rules/sort-variable-declarations.ts
+++ b/rules/sort-variable-declarations.ts
@@ -12,26 +12,19 @@ import {
   buildTypeJsonSchema,
   commonJsonSchemas,
 } from '../utils/common-json-schemas'
-import {
-  getFirstUnorderedNodeDependentOn,
-  sortNodesByDependencies,
-} from '../utils/sort-nodes-by-dependencies'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
+import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { hasPartitionComment } from '../utils/has-partition-comment'
-import { createNodeIndexMap } from '../utils/create-node-index-map'
-import { getCommentsBefore } from '../utils/get-comments-before'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { getLinesBetween } from '../utils/get-lines-between'
+import { reportAllErrors } from '../utils/report-all-errors'
+import { shouldPartition } from '../utils/should-partition'
 import { getSourceCode } from '../utils/get-source-code'
-import { reportErrors } from '../utils/report-errors'
 import { rangeToDiff } from '../utils/range-to-diff'
 import { getSettings } from '../utils/get-settings'
 import { isSortable } from '../utils/is-sortable'
 import { sortNodes } from '../utils/sort-nodes'
 import { complete } from '../utils/complete'
-import { pairwise } from '../utils/pairwise'
 
 type Options = [
   Partial<
@@ -196,17 +189,14 @@ export default createEslintRule<Options, MESSAGE_ID>({
             dependencies,
             name,
           }
+
           if (
-            hasPartitionComment({
-              comments: getCommentsBefore({
-                node: declaration,
-                sourceCode,
-              }),
-              partitionByComment: options.partitionByComment,
-            }) ||
-            (options.partitionByNewLine &&
-              lastSortingNode &&
-              getLinesBetween(sourceCode, lastSortingNode, sortingNode))
+            shouldPartition({
+              lastSortingNode,
+              sortingNode,
+              sourceCode,
+              options,
+            })
           ) {
             accumulator.push([])
           }
@@ -218,7 +208,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
         [[]],
       )
 
-      let sortNodesIgnoringEslintDisabledNodes = (
+      let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
       ): SortingNodeWithDependencies[] =>
         sortNodesByDependencies(
@@ -231,45 +221,20 @@ export default createEslintRule<Options, MESSAGE_ID>({
             ignoreEslintDisabledNodes,
           },
         )
-      let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
-      let sortedNodesExcludingEslintDisabled =
-        sortNodesIgnoringEslintDisabledNodes(true)
 
       let nodes = formattedMembers.flat()
 
-      let nodeIndexMap = createNodeIndexMap(sortedNodes)
-
-      pairwise(nodes, (left, right) => {
-        let leftIndex = nodeIndexMap.get(left)!
-        let rightIndex = nodeIndexMap.get(right)!
-
-        let indexOfRightExcludingEslintDisabled =
-          sortedNodesExcludingEslintDisabled.indexOf(right)
-        if (
-          leftIndex < rightIndex &&
-          leftIndex < indexOfRightExcludingEslintDisabled
-        ) {
-          return
-        }
-
-        let firstUnorderedNodeDependentOnRight =
-          getFirstUnorderedNodeDependentOn(right, nodes)
-
-        reportErrors({
-          messageIds: [
-            firstUnorderedNodeDependentOnRight
-              ? 'unexpectedVariableDeclarationsDependencyOrder'
-              : 'unexpectedVariableDeclarationsOrder',
-          ],
-          sortedNodes: sortedNodesExcludingEslintDisabled,
-          firstUnorderedNodeDependentOnRight,
-          sourceCode,
-          options,
-          context,
-          nodes,
-          right,
-          left,
-        })
+      reportAllErrors<MESSAGE_ID>({
+        availableMessageIds: {
+          unexpectedDependencyOrder:
+            'unexpectedVariableDeclarationsDependencyOrder',
+          unexpectedOrder: 'unexpectedVariableDeclarationsOrder',
+        },
+        sortNodesExcludingEslintDisabled,
+        sourceCode,
+        options,
+        context,
+        nodes,
       })
     },
   }),
diff --git a/utils/get-custom-groups-compare-options.ts b/utils/get-custom-groups-compare-options.ts
index dcdabcc..ffd4036 100644
--- a/utils/get-custom-groups-compare-options.ts
+++ b/utils/get-custom-groups-compare-options.ts
@@ -1,16 +1,13 @@
+import type { GroupsOptions } from '../types/common-options'
 import type { SortingNode } from '../types/sorting-node'
 import type { CompareOptions } from './compare'
 
 interface Options {
-  groups: (
-    | { newlinesBetween: 'ignore' | 'always' | 'never' }
-    | string[]
-    | string
-  )[]
   customGroups: Record<string, string[] | string> | CustomGroup[]
   type: 'alphabetical' | 'line-length' | 'natural' | 'custom'
   specialCharacters: 'remove' | 'trim' | 'keep'
   locales: NonNullable<Intl.LocalesArgument>
+  groups: GroupsOptions<string>
   order: 'desc' | 'asc'
   ignoreCase: boolean
   alphabet: string
@@ -40,7 +37,7 @@ type CustomGroup = (
  * if the group should not be sorted.
  */
 export let getCustomGroupsCompareOptions = <T extends SortingNode>(
-  options: Required<Options>,
+  options: Options,
   groupNumber: number,
 ): CompareOptions<T> | null => {
   if (!Array.isArray(options.customGroups)) {
diff --git a/utils/get-newlines-between-option.ts b/utils/get-newlines-between-option.ts
index 39fe522..d418335 100644
--- a/utils/get-newlines-between-option.ts
+++ b/utils/get-newlines-between-option.ts
@@ -1,3 +1,4 @@
+import type { GroupsOptions } from '../types/common-options'
 import type { SortingNode } from '../types/sorting-node'
 
 import { getGroupNumber } from './get-group-number'
@@ -9,13 +10,9 @@ export interface GetNewlinesBetweenOptionParameters {
 }
 
 interface Options {
-  groups: (
-    | { newlinesBetween: 'ignore' | 'always' | 'never' }
-    | string[]
-    | string
-  )[]
   customGroups?: Record<string, string[] | string> | CustomGroup[]
   newlinesBetween: 'ignore' | 'always' | 'never'
+  groups: GroupsOptions<string>
 }
 
 interface CustomGroup {
diff --git a/utils/report-all-errors.ts b/utils/report-all-errors.ts
new file mode 100644
index 0000000..771274f
--- /dev/null
+++ b/utils/report-all-errors.ts
@@ -0,0 +1,128 @@
+import type { TSESLint } from '@typescript-eslint/utils'
+
+import type { SortingNodeWithDependencies } from './sort-nodes-by-dependencies'
+import type { GroupsOptions } from '../types/common-options'
+import type { SortingNode } from '../types/sorting-node'
+import type { MakeFixesParameters } from './make-fixes'
+
+import { getFirstUnorderedNodeDependentOn } from './sort-nodes-by-dependencies'
+import { createNodeIndexMap } from './create-node-index-map'
+import { getNewlinesErrors } from './get-newlines-errors'
+import { getGroupNumber } from './get-group-number'
+import { reportErrors } from './report-errors'
+import { pairwise } from './pairwise'
+
+interface ReportAllErrorsParameters<MessageIds extends string> {
+  availableMessageIds: {
+    missedSpacingBetweenMembers?: MessageIds
+    extraSpacingBetweenMembers?: MessageIds
+    unexpectedDependencyOrder?: MessageIds
+    unexpectedGroupOrder?: MessageIds
+    unexpectedOrder: MessageIds
+  }
+  sortNodesExcludingEslintDisabled(
+    ignoreEslintDisabledNodes: boolean,
+  ): SortingNode[]
+  options?: {
+    groups?: GroupsOptions<string>
+  } & MakeFixesParameters['options']
+  context: TSESLint.RuleContext<MessageIds, unknown[]>
+  ignoreFirstNodeHighestBlockComment?: boolean
+  sourceCode: TSESLint.SourceCode
+  nodes: SortingNode[]
+}
+
+export let reportAllErrors = <MessageIds extends string>({
+  ignoreFirstNodeHighestBlockComment,
+  sortNodesExcludingEslintDisabled,
+  availableMessageIds,
+  sourceCode,
+  context,
+  options,
+  nodes,
+}: ReportAllErrorsParameters<MessageIds>): void => {
+  let sortedNodes = sortNodesExcludingEslintDisabled(false)
+  let sortedNodesExcludingEslintDisabled =
+    sortNodesExcludingEslintDisabled(true)
+  let nodeIndexMap = createNodeIndexMap(sortedNodes)
+
+  pairwise(nodes, (left, right) => {
+    let leftNumber = options?.groups ? getGroupNumber(options.groups, left) : 0
+    let rightNumber = options?.groups
+      ? getGroupNumber(options.groups, right)
+      : 0
+
+    let leftIndex = nodeIndexMap.get(left)!
+    let rightIndex = nodeIndexMap.get(right)!
+
+    let indexOfRightExcludingEslintDisabled =
+      sortedNodesExcludingEslintDisabled.indexOf(right)
+
+    let messageIds: MessageIds[] = []
+
+    let firstUnorderedNodeDependentOnRight:
+      | SortingNodeWithDependencies
+      | undefined
+    if (availableMessageIds.unexpectedDependencyOrder) {
+      firstUnorderedNodeDependentOnRight = getFirstUnorderedNodeDependentOn(
+        right as SortingNodeWithDependencies,
+        nodes as SortingNodeWithDependencies[],
+      )
+    }
+
+    if (
+      firstUnorderedNodeDependentOnRight ||
+      leftIndex > rightIndex ||
+      leftIndex >= indexOfRightExcludingEslintDisabled
+    ) {
+      if (firstUnorderedNodeDependentOnRight) {
+        messageIds.push(availableMessageIds.unexpectedDependencyOrder!)
+      } else {
+        messageIds.push(
+          leftNumber === rightNumber ||
+            !availableMessageIds.unexpectedGroupOrder
+            ? availableMessageIds.unexpectedOrder
+            : availableMessageIds.unexpectedGroupOrder,
+        )
+      }
+    }
+
+    if (
+      options?.newlinesBetween &&
+      options.groups &&
+      availableMessageIds.missedSpacingBetweenMembers &&
+      availableMessageIds.extraSpacingBetweenMembers
+    ) {
+      messageIds = [
+        ...messageIds,
+        ...getNewlinesErrors({
+          options: {
+            ...options,
+            newlinesBetween: options.newlinesBetween,
+            groups: options.groups,
+          },
+          missedSpacingError: availableMessageIds.missedSpacingBetweenMembers,
+          extraSpacingError: availableMessageIds.extraSpacingBetweenMembers,
+          rightNum: rightNumber,
+          leftNum: leftNumber,
+          sourceCode,
+          right,
+          left,
+        }),
+      ]
+    }
+
+    reportErrors({
+      sortedNodes: sortedNodesExcludingEslintDisabled,
+      ignoreFirstNodeHighestBlockComment,
+      firstUnorderedNodeDependentOnRight,
+      messageIds,
+      sourceCode,
+      options,
+      context,
+      nodes,
+      right,
+      left,
+    })
+  })
+}
diff --git a/utils/should-partition.ts b/utils/should-partition.ts
new file mode 100644
index 0000000..a1b09d6
--- /dev/null
+++ b/utils/should-partition.ts
@@ -0,0 +1,47 @@
+import type { TSESLint } from '@typescript-eslint/utils'
+
+import type { PartitionByCommentOption } from '../types/common-options'
+import type { SortingNode } from '../types/sorting-node'
+
+import { hasPartitionComment } from './has-partition-comment'
+import { getCommentsBefore } from './get-comments-before'
+import { getLinesBetween } from './get-lines-between'
+
+interface ShouldPartitionParameters {
+  options: {
+    partitionByComment?: PartitionByCommentOption
+    partitionByNewLine?: boolean
+  }
+  lastSortingNode: SortingNode | undefined
+  tokenValueToIgnoreBefore?: string
+  sourceCode: TSESLint.SourceCode
+  sortingNode: SortingNode
+}
+
+export let shouldPartition = ({
+  tokenValueToIgnoreBefore,
+  lastSortingNode,
+  sortingNode,
+  sourceCode,
+  options,
+}: ShouldPartitionParameters): boolean => {
+  let shouldPartitionByComment =
+    options.partitionByComment &&
+    hasPartitionComment({
+      comments: getCommentsBefore({
+        tokenValueToIgnoreBefore,
+        node: sortingNode.node,
+        sourceCode,
+      }),
+      partitionByComment: options.partitionByComment,
+    })
+  if (shouldPartitionByComment) {
+    return true
+  }
+
+  return !!(
+    options.partitionByNewLine &&
+    lastSortingNode &&
+    getLinesBetween(sourceCode, lastSortingNode, sortingNode)
+  )
+}
diff --git a/utils/sort-nodes-by-groups.ts b/utils/sort-nodes-by-groups.ts
index 7d4a833..3476cfa 100644
--- a/utils/sort-nodes-by-groups.ts
+++ b/utils/sort-nodes-by-groups.ts
@@ -1,3 +1,4 @@
+import type { GroupsOptions } from '../types/common-options'
 import type { SortingNode } from '../types/sorting-node'
 import type { CompareOptions } from './compare'
 
@@ -14,17 +15,13 @@ interface ExtraOptions<T extends SortingNode> {
   isNodeIgnored?(node: T): boolean
 }
 
-interface GroupsOptions {
-  groups: (
-    | { newlinesBetween: 'ignore' | 'always' | 'never' }
-    | string[]
-    | string
-  )[]
+interface GroupsOption {
+  groups: GroupsOptions<string>
 }
 
 export let sortNodesByGroups = <T extends SortingNode>(
   nodes: T[],
-  options: CompareOptions<T> & GroupsOptions,
+  options: CompareOptions<T> & GroupsOption,
   extraOptions?: ExtraOptions<T>,
 ): T[] => {
   let nodesByNonIgnoredGroupNumber: Record<number, T[]> = {}
diff --git a/utils/validate-newlines-and-partition-configuration.ts b/utils/validate-newlines-and-partition-configuration.ts
index 9bca8cd..fb4138e 100644
--- a/utils/validate-newlines-and-partition-configuration.ts
+++ b/utils/validate-newlines-and-partition-configuration.ts
@@ -1,10 +1,8 @@
+import type { GroupsOptions } from '../types/common-options'
+
 interface Options {
-  groups: (
-    | { newlinesBetween: 'ignore' | 'always' | 'never' }
-    | string[]
-    | string
-  )[]
   newlinesBetween: 'ignore' | 'always' | 'never'
+  groups: GroupsOptions<string>
   partitionByNewLine: boolean
 }
 


Test patch:
diff --git a/test/rules/sort-objects.test.ts b/test/rules/sort-objects.test.ts
index 933c11c..db47b62 100644
--- a/test/rules/sort-objects.test.ts
+++ b/test/rules/sort-objects.test.ts
@@ -529,6 +529,13 @@ describe(ruleName, () => {
                   },
                   messageId: 'unexpectedObjectsDependencyOrder',
                 },
+                {
+                  data: {
+                    nodeDependentOnRight: 'b',
+                    right: 'd',
+                  },
+                  messageId: 'unexpectedObjectsDependencyOrder',
+                },
               ],
               output: dedent`
                 let Func = ({
@@ -593,6 +600,13 @@ describe(ruleName, () => {
                   },
                   messageId: 'unexpectedObjectsDependencyOrder',
                 },
+                {
+                  data: {
+                    nodeDependentOnRight: 'b',
+                    right: 'd',
+                  },
+                  messageId: 'unexpectedObjectsDependencyOrder',
+                },
               ],
               output: dedent`
                 let Func = ({
@@ -1029,7 +1043,7 @@ describe(ruleName, () => {
             {
               code: dedent`
                 let Func = ({
-                  b = a,
+                  b = 'b',
                   a = b as any,
                 }) => {
                   // ...
@@ -1054,7 +1068,7 @@ describe(ruleName, () => {
             {
               code: dedent`
                 let Func = ({
-                  b = a,
+                  b = 'b',
                   a = <any>b,
                 }) => {
                   // ...
@@ -1079,7 +1093,7 @@ describe(ruleName, () => {
             {
               code: dedent`
                 let Func = ({
-                  b = a,
+                  b = 'b',
                   a = \`\${b}\`,
                 }) => {
                   // ...
@@ -3555,6 +3569,13 @@ describe(ruleName, () => {
                 },
                 messageId: 'unexpectedObjectsDependencyOrder',
               },
+              {
+                data: {
+                  nodeDependentOnRight: 'b',
+                  right: 'd',
+                },
+                messageId: 'unexpectedObjectsDependencyOrder',
+              },
             ],
             output: dedent`
               let Func = ({
@@ -3619,6 +3640,13 @@ describe(ruleName, () => {
                 },
                 messageId: 'unexpectedObjectsDependencyOrder',
               },
+              {
+                data: {
+                  nodeDependentOnRight: 'b',
+                  right: 'd',
+                },
+                messageId: 'unexpectedObjectsDependencyOrder',
+              },
             ],
             output: dedent`
               let Func = ({
@@ -4453,6 +4481,13 @@ describe(ruleName, () => {
                 },
                 messageId: 'unexpectedObjectsDependencyOrder',
               },
+              {
+                data: {
+                  nodeDependentOnRight: 'b',
+                  right: 'd',
+                },
+                messageId: 'unexpectedObjectsDependencyOrder',
+              },
             ],
             output: dedent`
               let Func = ({
@@ -4517,6 +4552,13 @@ describe(ruleName, () => {
                 },
                 messageId: 'unexpectedObjectsDependencyOrder',
               },
+              {
+                data: {
+                  nodeDependentOnRight: 'b',
+                  right: 'd',
+                },
+                messageId: 'unexpectedObjectsDependencyOrder',
+              },
             ],
             output: dedent`
               let Func = ({
diff --git a/test/rules/sort-variable-declarations.test.ts b/test/rules/sort-variable-declarations.test.ts
index ad05926..920225a 100644
--- a/test/rules/sort-variable-declarations.test.ts
+++ b/test/rules/sort-variable-declarations.test.ts
@@ -561,7 +561,7 @@ describe(ruleName, () => {
               },
             ],
             code: dedent`
-              let b = a,
+              let b = 'b',
               a = b as any;
             `,
           },
@@ -582,7 +582,7 @@ describe(ruleName, () => {
               },
             ],
             code: dedent`
-              let b = a,
+              let b = 'b',
               a = <any>b;
             `,
           },
@@ -603,7 +603,7 @@ describe(ruleName, () => {
               },
             ],
             code: dedent`
-              let b = a,
+              let b = 'b',
               a = \`\${b}\`
             `,
           },