Repository: azat-io/eslint-plugin-perfectionist
Pull request #425 (2024-12-20 16:46:10)

refactor: improve folder structure
### Description

Updated the project file structure.

### Additional context

#417.

---

### What is the purpose of this pull request? <!-- (put an "X" next to an item) -->

- [ ] Bug fix
- [ ] New Feature
- [ ] Documentation update
- [x] Other

### Before submitting the PR, please make sure you do the following

- [x] Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
- [x] Provide a description in this PR that addresses **what** the PR is solving, or reference the issue that it solves (e.g. `fixes #123`).
- [x] Ideally, include relevant tests that fail without this PR but pass with it.
- [x] Read [contribution guidelines](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/contributing.md).


azat-io: Everything is currently working correctly except for one test in:
`test/rules/sort-imports/read-closest-ts-config-by-path.test.ts`
azat-io: Branch tree:
https://github.com/azat-io/eslint-plugin-perfectionist/tree/refactor/structure
hugop95: @azat-io Fix for the test can be found here: https://github.com/azat-io/eslint-plugin-perfectionist/pull/426.
azat-io: @hugop95 Nice, thank you!

Ready for review.
azat-io: @hugop95 I don't have a clear opinion on this. There are no `index.ts` files in the utilities folders for rules (`rules/sort-array-includes`), it seems logical to me that there is no `index.ts` in `utils`.
hugop95: @azat-io There is one in `types`, this is why I was asking 🙂. No big difference for me.
azat-io: Or we could remove `index.ts` from `types/`
hugop95: @azat-io 

> Or we could remove index.ts from types/

Fine by me as well 👍
azat-io: Done!

Patch:
diff --git a/rules/sort-array-includes.ts b/rules/sort-array-includes.ts
index eb9ec70..ae2ee04 100644
--- a/rules/sort-array-includes.ts
+++ b/rules/sort-array-includes.ts
@@ -3,8 +3,8 @@ import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
 import type { TSESTree } from '@typescript-eslint/types'
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { Selector, Options } from './sort-array-includes.types'
-import type { SortingNode } from '../typings'
+import type { Selector, Options } from './sort-array-includes/types'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   buildUseConfigurationIfJsonSchema,
@@ -20,20 +20,22 @@ import {
   orderJsonSchema,
 } from '../utils/common-json-schemas'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
+import {
+  singleCustomGroupJsonSchema,
+  allSelectors,
+} from './sort-array-includes/types'
 import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
+import { doesCustomGroupMatch } from './sort-array-includes/does-custom-group-match'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
-import { singleCustomGroupJsonSchema } from './sort-array-includes.types'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
 import { hasPartitionComment } from '../utils/is-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 { customGroupMatches } from './sort-array-includes-utils'
 import { createEslintRule } from '../utils/create-eslint-rule'
 import { getLinesBetween } from '../utils/get-lines-between'
-import { allSelectors } from './sort-array-includes.types'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getSourceCode } from '../utils/get-source-code'
 import { toSingleLine } from '../utils/to-single-line'
@@ -235,7 +237,7 @@ export let sortArray = <MessageIds extends string>({
       let name = getNodeName({ sourceCode, element })
       for (let customGroup of options.customGroups) {
         if (
-          customGroupMatches({
+          doesCustomGroupMatch({
             selectors: [selector],
             elementName: name,
             customGroup,
diff --git a/rules/sort-array-includes-utils.ts b/rules/sort-array-includes/does-custom-group-match.ts
similarity index 69%
rename from rules/sort-array-includes-utils.ts
rename to rules/sort-array-includes/does-custom-group-match.ts
index 349e517..801df37 100644
--- a/rules/sort-array-includes-utils.ts
+++ b/rules/sort-array-includes/does-custom-group-match.ts
@@ -1,12 +1,8 @@
-import type {
-  SingleCustomGroup,
-  AnyOfCustomGroup,
-  Selector,
-} from './sort-array-includes.types'
+import type { SingleCustomGroup, AnyOfCustomGroup, Selector } from './types'
 
-import { matches } from '../utils/matches'
+import { matches } from '../../utils/matches'
 
-interface CustomGroupMatchesProps {
+interface DoesCustomGroupMatchProps {
   customGroup: SingleCustomGroup | AnyOfCustomGroup
   selectors: Selector[]
   elementName: string
@@ -14,16 +10,18 @@ interface CustomGroupMatchesProps {
 
 /**
  * Determines whether a custom group matches the given properties.
- * @param {CustomGroupMatchesProps} props - The properties to compare with the
+ * @param {DoesCustomGroupMatchProps} props - The properties to compare with the
  * custom group, including selectors, modifiers, and element name.
  * @returns {boolean} `true` if the custom group matches the properties;
  * otherwise, `false`.
  */
-export let customGroupMatches = (props: CustomGroupMatchesProps): boolean => {
+export let doesCustomGroupMatch = (
+  props: DoesCustomGroupMatchProps,
+): boolean => {
   if ('anyOf' in props.customGroup) {
     // At least one subgroup must match
     return props.customGroup.anyOf.some(subgroup =>
-      customGroupMatches({ ...props, customGroup: subgroup }),
+      doesCustomGroupMatch({ ...props, customGroup: subgroup }),
     )
   }
   if (
diff --git a/rules/sort-array-includes.types.ts b/rules/sort-array-includes/types.ts
similarity index 97%
rename from rules/sort-array-includes.types.ts
rename to rules/sort-array-includes/types.ts
index 4ffd62c..05f60ac 100644
--- a/rules/sort-array-includes.types.ts
+++ b/rules/sort-array-includes/types.ts
@@ -3,7 +3,7 @@ import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'
 import {
   buildCustomGroupSelectorJsonSchema,
   elementNamePatternJsonSchema,
-} from '../utils/common-json-schemas'
+} from '../../utils/common-json-schemas'
 
 export type Options = Partial<{
   type: 'alphabetical' | 'line-length' | 'unsorted' | 'natural' | 'custom'
diff --git a/rules/sort-classes-utils.ts b/rules/sort-classes-utils.ts
deleted file mode 100644
index 58010cb..0000000
--- a/rules/sort-classes-utils.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import type { TSESTree } from '@typescript-eslint/utils'
-
-import type {
-  SingleCustomGroup,
-  AnyOfCustomGroup,
-  Modifier,
-  Selector,
-} from './sort-classes.types'
-
-import { isSortable } from '../utils/is-sortable'
-import { matches } from '../utils/matches'
-
-interface CustomGroupMatchesProps {
-  customGroup: SingleCustomGroup | AnyOfCustomGroup
-  elementValue: undefined | string
-  selectors: Selector[]
-  modifiers: Modifier[]
-  decorators: string[]
-  elementName: string
-}
-
-/**
- * Returns a list of groups of overload signatures.
- * @param {TSESTree.ClassElement[]} members - The class elements to process.
- * @returns {TSESTree.ClassElement[][]} An array of groups of overload
- * signatures.
- */
-export let getOverloadSignatureGroups = (
-  members: TSESTree.ClassElement[],
-): TSESTree.ClassElement[][] => {
-  let methods = members
-    .filter(
-      member =>
-        member.type === 'MethodDefinition' ||
-        member.type === 'TSAbstractMethodDefinition',
-    )
-    .filter(member => member.kind === 'method')
-  // Static and non-static overload signatures can coexist with the same name
-  let staticOverloadSignaturesByName = new Map<
-    string,
-    TSESTree.ClassElement[]
-  >()
-  let overloadSignaturesByName = new Map<string, TSESTree.ClassElement[]>()
-  for (let method of methods) {
-    if (method.key.type !== 'Identifier') {
-      continue
-    }
-    let { name } = method.key
-    let mapToUse = method.static
-      ? staticOverloadSignaturesByName
-      : overloadSignaturesByName
-    let signatureOverloadsGroup = mapToUse.get(name)
-    if (!signatureOverloadsGroup) {
-      signatureOverloadsGroup = []
-      mapToUse.set(name, signatureOverloadsGroup)
-    }
-    signatureOverloadsGroup.push(method)
-  }
-  // Ignore groups that only have one method
-  return [
-    ...overloadSignaturesByName.values(),
-    ...staticOverloadSignaturesByName.values(),
-  ].filter(isSortable)
-}
-
-/**
- * Determines whether a custom group matches the given properties.
- * @param {CustomGroupMatchesProps} props - The properties to match against the
- * custom group, including selectors, modifiers, decorators, and element names.
- * @returns {boolean} `true` if the custom group matches the properties;
- * otherwise, `false`.
- */
-export let customGroupMatches = (props: CustomGroupMatchesProps): boolean => {
-  if ('anyOf' in props.customGroup) {
-    // At least one subgroup must match
-    return props.customGroup.anyOf.some(subgroup =>
-      customGroupMatches({ ...props, customGroup: subgroup }),
-    )
-  }
-  if (
-    props.customGroup.selector &&
-    !props.selectors.includes(props.customGroup.selector)
-  ) {
-    return false
-  }
-
-  if (props.customGroup.modifiers) {
-    for (let modifier of props.customGroup.modifiers) {
-      if (!props.modifiers.includes(modifier)) {
-        return false
-      }
-    }
-  }
-
-  if (
-    'elementNamePattern' in props.customGroup &&
-    props.customGroup.elementNamePattern
-  ) {
-    let matchesElementNamePattern: boolean = matches(
-      props.elementName,
-      props.customGroup.elementNamePattern,
-    )
-    if (!matchesElementNamePattern) {
-      return false
-    }
-  }
-
-  if (
-    'elementValuePattern' in props.customGroup &&
-    props.customGroup.elementValuePattern
-  ) {
-    let matchesElementValuePattern: boolean = matches(
-      props.elementValue ?? '',
-      props.customGroup.elementValuePattern,
-    )
-    if (!matchesElementValuePattern) {
-      return false
-    }
-  }
-
-  if (
-    'decoratorNamePattern' in props.customGroup &&
-    props.customGroup.decoratorNamePattern
-  ) {
-    let decoratorPattern = props.customGroup.decoratorNamePattern
-    let matchesDecoratorNamePattern: boolean = props.decorators.some(
-      decorator => matches(decorator, decoratorPattern),
-    )
-    if (!matchesDecoratorNamePattern) {
-      return false
-    }
-  }
-
-  return true
-}
diff --git a/rules/sort-classes.ts b/rules/sort-classes.ts
index 663b279..fd51eea 100644
--- a/rules/sort-classes.ts
+++ b/rules/sort-classes.ts
@@ -5,7 +5,7 @@ import type {
   SortClassesOptions,
   Modifier,
   Selector,
-} from './sort-classes.types'
+} from './sort-classes/types'
 import type { SortingNodeWithDependencies } from '../utils/sort-nodes-by-dependencies'
 
 import {
@@ -31,14 +31,12 @@ import {
   singleCustomGroupJsonSchema,
   allModifiers,
   allSelectors,
-} from './sort-classes.types'
+} from './sort-classes/types'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import {
-  getOverloadSignatureGroups,
-  customGroupMatches,
-} from './sort-classes-utils'
 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 { 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/is-partition-comment'
@@ -506,7 +504,7 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
 
           for (let customGroup of options.customGroups) {
             if (
-              customGroupMatches({
+              doesCustomGroupMatch({
                 elementValue: memberValue,
                 elementName: name,
                 customGroup,
diff --git a/rules/sort-classes/does-custom-group-match.ts b/rules/sort-classes/does-custom-group-match.ts
new file mode 100644
index 0000000..11a576a
--- /dev/null
+++ b/rules/sort-classes/does-custom-group-match.ts
@@ -0,0 +1,91 @@
+import type {
+  SingleCustomGroup,
+  AnyOfCustomGroup,
+  Modifier,
+  Selector,
+} from './types'
+
+import { matches } from '../../utils/matches'
+
+interface DoesCustomGroupMatchProps {
+  customGroup: SingleCustomGroup | AnyOfCustomGroup
+  elementValue: undefined | string
+  selectors: Selector[]
+  modifiers: Modifier[]
+  decorators: string[]
+  elementName: string
+}
+
+/**
+ * Determines whether a custom group matches the given properties.
+ * @param {DoesCustomGroupMatchProps} props - The properties to match against
+ * the custom group, including selectors, modifiers, decorators, and element
+ * names.
+ * @returns {boolean} `true` if the custom group matches the properties;
+ * otherwise, `false`.
+ */
+export let doesCustomGroupMatch = (
+  props: DoesCustomGroupMatchProps,
+): boolean => {
+  if ('anyOf' in props.customGroup) {
+    // At least one subgroup must match
+    return props.customGroup.anyOf.some(subgroup =>
+      doesCustomGroupMatch({ ...props, customGroup: subgroup }),
+    )
+  }
+  if (
+    props.customGroup.selector &&
+    !props.selectors.includes(props.customGroup.selector)
+  ) {
+    return false
+  }
+
+  if (props.customGroup.modifiers) {
+    for (let modifier of props.customGroup.modifiers) {
+      if (!props.modifiers.includes(modifier)) {
+        return false
+      }
+    }
+  }
+
+  if (
+    'elementNamePattern' in props.customGroup &&
+    props.customGroup.elementNamePattern
+  ) {
+    let matchesElementNamePattern: boolean = matches(
+      props.elementName,
+      props.customGroup.elementNamePattern,
+    )
+    if (!matchesElementNamePattern) {
+      return false
+    }
+  }
+
+  if (
+    'elementValuePattern' in props.customGroup &&
+    props.customGroup.elementValuePattern
+  ) {
+    let matchesElementValuePattern: boolean = matches(
+      props.elementValue ?? '',
+      props.customGroup.elementValuePattern,
+    )
+    if (!matchesElementValuePattern) {
+      return false
+    }
+  }
+
+  if (
+    'decoratorNamePattern' in props.customGroup &&
+    props.customGroup.decoratorNamePattern
+  ) {
+    let decoratorPattern = props.customGroup.decoratorNamePattern
+    let matchesDecoratorNamePattern: boolean = props.decorators.some(
+      decorator => matches(decorator, decoratorPattern),
+    )
+    if (!matchesDecoratorNamePattern) {
+      return false
+    }
+  }
+
+  return true
+}
diff --git a/rules/sort-classes/get-overload-signature-groups.ts b/rules/sort-classes/get-overload-signature-groups.ts
new file mode 100644
index 0000000..0a559bc
--- /dev/null
+++ b/rules/sort-classes/get-overload-signature-groups.ts
@@ -0,0 +1,47 @@
+import type { TSESTree } from '@typescript-eslint/utils'
+
+import { isSortable } from '../../utils/is-sortable'
+
+/**
+ * Returns a list of groups of overload signatures.
+ * @param {TSESTree.ClassElement[]} members - The class elements to process.
+ * @returns {TSESTree.ClassElement[][]} An array of groups of overload
+ * signatures.
+ */
+export let getOverloadSignatureGroups = (
+  members: TSESTree.ClassElement[],
+): TSESTree.ClassElement[][] => {
+  let methods = members
+    .filter(
+      member =>
+        member.type === 'MethodDefinition' ||
+        member.type === 'TSAbstractMethodDefinition',
+    )
+    .filter(member => member.kind === 'method')
+  // Static and non-static overload signatures can coexist with the same name
+  let staticOverloadSignaturesByName = new Map<
+    string,
+    TSESTree.ClassElement[]
+  >()
+  let overloadSignaturesByName = new Map<string, TSESTree.ClassElement[]>()
+  for (let method of methods) {
+    if (method.key.type !== 'Identifier') {
+      continue
+    }
+    let { name } = method.key
+    let mapToUse = method.static
+      ? staticOverloadSignaturesByName
+      : overloadSignaturesByName
+    let signatureOverloadsGroup = mapToUse.get(name)
+    if (!signatureOverloadsGroup) {
+      signatureOverloadsGroup = []
+      mapToUse.set(name, signatureOverloadsGroup)
+    }
+    signatureOverloadsGroup.push(method)
+  }
+  // Ignore groups that only have one method
+  return [
+    ...overloadSignaturesByName.values(),
+    ...staticOverloadSignaturesByName.values(),
+  ].filter(isSortable)
+}
diff --git a/rules/sort-classes.types.ts b/rules/sort-classes/types.ts
similarity index 98%
rename from rules/sort-classes.types.ts
rename to rules/sort-classes/types.ts
index 78839c1..624e07c 100644
--- a/rules/sort-classes.types.ts
+++ b/rules/sort-classes/types.ts
@@ -1,12 +1,12 @@
 import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'
 
-import type { JoinWithDash } from '../typings'
+import type { JoinWithDash } from '../../types/join-with-dash'
 
 import {
   buildCustomGroupModifiersJsonSchema,
   buildCustomGroupSelectorJsonSchema,
   elementNamePatternJsonSchema,
-} from '../utils/common-json-schemas'
+} from '../../utils/common-json-schemas'
 
 export type SortClassesOptions = [
   Partial<{
diff --git a/rules/sort-decorators.ts b/rules/sort-decorators.ts
index b55e9e4..a78919c 100644
--- a/rules/sort-decorators.ts
+++ b/rules/sort-decorators.ts
@@ -1,7 +1,7 @@
 import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
@@ -18,13 +18,13 @@ 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 { getDecoratorName } from './sort-decorators/get-decorator-name'
 import { hasPartitionComment } from '../utils/is-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 { getDecoratorName } from '../utils/get-decorator-name'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getSourceCode } from '../utils/get-source-code'
 import { toSingleLine } from '../utils/to-single-line'
diff --git a/utils/get-decorator-name.ts b/rules/sort-decorators/get-decorator-name.ts
similarity index 100%
rename from utils/get-decorator-name.ts
rename to rules/sort-decorators/get-decorator-name.ts
diff --git a/rules/sort-exports.ts b/rules/sort-exports.ts
index ca5325a..d412861 100644
--- a/rules/sort-exports.ts
+++ b/rules/sort-exports.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/rules/sort-heritage-clauses.ts b/rules/sort-heritage-clauses.ts
index 2cf18a7..0ab6200 100644
--- a/rules/sort-heritage-clauses.ts
+++ b/rules/sort-heritage-clauses.ts
@@ -1,7 +1,7 @@
 import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   specialCharactersJsonSchema,
diff --git a/rules/sort-imports.ts b/rules/sort-imports.ts
index 4513c88..513cf09 100644
--- a/rules/sort-imports.ts
+++ b/rules/sort-imports.ts
@@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/types'
 
 import { builtinModules } from 'node:module'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
@@ -18,12 +18,12 @@ import {
 } from '../utils/common-json-schemas'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
+import { readClosestTsConfigByPath } from './sort-imports/read-closest-ts-config-by-path'
 import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
-import { readClosestTsConfigByPath } from '../utils/read-closest-ts-config-by-path'
 import { getOptionsWithCleanGroups } from '../utils/get-options-with-clean-groups'
 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 { getTypescriptImport } from '../utils/get-typescript-import'
 import { createNodeIndexMap } from '../utils/create-node-index-map'
 import { hasPartitionComment } from '../utils/is-partition-comment'
 import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
diff --git a/utils/get-typescript-import.ts b/rules/sort-imports/get-typescript-import.ts
similarity index 100%
rename from utils/get-typescript-import.ts
rename to rules/sort-imports/get-typescript-import.ts
diff --git a/utils/read-closest-ts-config-by-path.ts b/rules/sort-imports/read-closest-ts-config-by-path.ts
similarity index 100%
rename from utils/read-closest-ts-config-by-path.ts
rename to rules/sort-imports/read-closest-ts-config-by-path.ts
diff --git a/rules/sort-interfaces.ts b/rules/sort-interfaces.ts
index 9a33ea4..1aba4c4 100644
--- a/rules/sort-interfaces.ts
+++ b/rules/sort-interfaces.ts
@@ -1,4 +1,4 @@
-import type { Options as SortObjectTypesOptions } from './sort-object-types.types'
+import type { Options as SortObjectTypesOptions } from './sort-object-types/types'
 
 import { sortObjectTypeElements, jsonSchema } from './sort-object-types'
 import { createEslintRule } from '../utils/create-eslint-rule'
diff --git a/rules/sort-intersection-types.ts b/rules/sort-intersection-types.ts
index 068618d..547d637 100644
--- a/rules/sort-intersection-types.ts
+++ b/rules/sort-intersection-types.ts
@@ -1,4 +1,4 @@
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/rules/sort-jsx-props.ts b/rules/sort-jsx-props.ts
index e71351b..63dae54 100644
--- a/rules/sort-jsx-props.ts
+++ b/rules/sort-jsx-props.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   specialCharactersJsonSchema,
diff --git a/rules/sort-maps.ts b/rules/sort-maps.ts
index bff24e9..bb6996e 100644
--- a/rules/sort-maps.ts
+++ b/rules/sort-maps.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/rules/sort-modules.ts b/rules/sort-modules.ts
index 867c0a3..c5aa1a7 100644
--- a/rules/sort-modules.ts
+++ b/rules/sort-modules.ts
@@ -7,7 +7,7 @@ import type {
   SortModulesOptions,
   Modifier,
   Selector,
-} from './sort-modules.types'
+} from './sort-modules/types'
 import type { SortingNodeWithDependencies } from '../utils/sort-nodes-by-dependencies'
 
 import {
@@ -33,10 +33,11 @@ import {
   singleCustomGroupJsonSchema,
   allModifiers,
   allSelectors,
-} from './sort-modules.types'
+} from './sort-modules/types'
 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 { 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 { createNodeIndexMap } from '../utils/create-node-index-map'
@@ -50,7 +51,6 @@ import { createEslintRule } from '../utils/create-eslint-rule'
 import { getLinesBetween } from '../utils/get-lines-between'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getEnumMembers } from '../utils/get-enum-members'
-import { customGroupMatches } from './sort-modules-utils'
 import { getSourceCode } from '../utils/get-source-code'
 import { toSingleLine } from '../utils/to-single-line'
 import { rangeToDiff } from '../utils/range-to-diff'
@@ -324,7 +324,7 @@ let analyzeModule = ({
     }
     for (let customGroup of options.customGroups) {
       if (
-        customGroupMatches({
+        doesCustomGroupMatch({
           selectors: [selector],
           elementName: name,
           customGroup,
diff --git a/rules/sort-modules-utils.ts b/rules/sort-modules/does-custom-group-match.ts
similarity index 82%
rename from rules/sort-modules-utils.ts
rename to rules/sort-modules/does-custom-group-match.ts
index ed45f4a..05506f1 100644
--- a/rules/sort-modules-utils.ts
+++ b/rules/sort-modules/does-custom-group-match.ts
@@ -3,11 +3,11 @@ import type {
   AnyOfCustomGroup,
   Modifier,
   Selector,
-} from './sort-modules.types'
+} from './types'
 
-import { matches } from '../utils/matches'
+import { matches } from '../../utils/matches'
 
-interface CustomGroupMatchesProps {
+interface DoesCustomGroupMatchProps {
   customGroup: SingleCustomGroup | AnyOfCustomGroup
   selectors: Selector[]
   modifiers: Modifier[]
@@ -17,16 +17,18 @@ interface CustomGroupMatchesProps {
 
 /**
  * Determines whether a custom group matches the given properties.
- * @param {CustomGroupMatchesProps} props - The properties to compare with the
+ * @param {DoesCustomGroupMatchProps} props - The properties to compare with the
  * custom group, including selectors, modifiers, decorators, and element name.
  * @returns {boolean} `true` if the custom group matches the properties;
  * otherwise, `false`.
  */
-export let customGroupMatches = (props: CustomGroupMatchesProps): boolean => {
+export let doesCustomGroupMatch = (
+  props: DoesCustomGroupMatchProps,
+): boolean => {
   if ('anyOf' in props.customGroup) {
     // At least one subgroup must match
     return props.customGroup.anyOf.some(subgroup =>
-      customGroupMatches({ ...props, customGroup: subgroup }),
+      doesCustomGroupMatch({ ...props, customGroup: subgroup }),
     )
   }
   if (
diff --git a/rules/sort-modules.types.ts b/rules/sort-modules/types.ts
similarity index 97%
rename from rules/sort-modules.types.ts
rename to rules/sort-modules/types.ts
index fa1af6b..d4872fc 100644
--- a/rules/sort-modules.types.ts
+++ b/rules/sort-modules/types.ts
@@ -1,12 +1,12 @@
 import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'
 
-import type { JoinWithDash } from '../typings'
+import type { JoinWithDash } from '../../types/join-with-dash'
 
 import {
   buildCustomGroupModifiersJsonSchema,
   buildCustomGroupSelectorJsonSchema,
   elementNamePatternJsonSchema,
-} from '../utils/common-json-schemas'
+} from '../../utils/common-json-schemas'
 
 export type SortModulesOptions = [
   Partial<{
diff --git a/rules/sort-named-exports.ts b/rules/sort-named-exports.ts
index f8a20b3..0f459c7 100644
--- a/rules/sort-named-exports.ts
+++ b/rules/sort-named-exports.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/rules/sort-named-imports.ts b/rules/sort-named-imports.ts
index 2aaa68b..fa765c6 100644
--- a/rules/sort-named-imports.ts
+++ b/rules/sort-named-imports.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/rules/sort-object-types.ts b/rules/sort-object-types.ts
index 199ae0e..c04d950 100644
--- a/rules/sort-object-types.ts
+++ b/rules/sort-object-types.ts
@@ -3,8 +3,8 @@ import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'
 import type { TSESTree } from '@typescript-eslint/types'
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { Modifier, Selector, Options } from './sort-object-types.types'
-import type { SortingNode } from '../typings'
+import type { Modifier, Selector, Options } from './sort-object-types/types'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   buildUseConfigurationIfJsonSchema,
@@ -22,15 +22,20 @@ import {
   orderJsonSchema,
 } from '../utils/common-json-schemas'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import {
+  singleCustomGroupJsonSchema,
+  allModifiers,
+  allSelectors,
+} from './sort-object-types/types'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
+import { doesCustomGroupMatch } from './sort-object-types/does-custom-group-match'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
-import { singleCustomGroupJsonSchema } from './sort-object-types.types'
+import { isMemberOptional } from './sort-object-types/is-member-optional'
 import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
-import { allModifiers, allSelectors } from './sort-object-types.types'
 import { hasPartitionComment } from '../utils/is-partition-comment'
 import { isNodeFunctionType } from '../utils/is-node-function-type'
 import { createNodeIndexMap } from '../utils/create-node-index-map'
@@ -39,8 +44,6 @@ import { getCommentsBefore } from '../utils/get-comments-before'
 import { makeNewlinesFixes } from '../utils/make-newlines-fixes'
 import { getNewlinesErrors } from '../utils/get-newlines-errors'
 import { createEslintRule } from '../utils/create-eslint-rule'
-import { isMemberOptional } from '../utils/is-member-optional'
-import { customGroupMatches } from './sort-object-types-utils'
 import { getLinesBetween } from '../utils/get-lines-between'
 import { getGroupNumber } from '../utils/get-group-number'
 import { getSourceCode } from '../utils/get-source-code'
@@ -314,7 +317,7 @@ export let sortObjectTypeElements = <MessageIds extends string>({
       if (Array.isArray(options.customGroups)) {
         for (let customGroup of options.customGroups) {
           if (
-            customGroupMatches({
+            doesCustomGroupMatch({
               elementName: name,
               customGroup,
               selectors,
diff --git a/rules/sort-object-types-utils.ts b/rules/sort-object-types/does-custom-group-match.ts
similarity index 78%
rename from rules/sort-object-types-utils.ts
rename to rules/sort-object-types/does-custom-group-match.ts
index 0dd7bd1..dc45207 100644
--- a/rules/sort-object-types-utils.ts
+++ b/rules/sort-object-types/does-custom-group-match.ts
@@ -3,11 +3,11 @@ import type {
   AnyOfCustomGroup,
   Modifier,
   Selector,
-} from './sort-object-types.types'
+} from './types'
 
-import { matches } from '../utils/matches'
+import { matches } from '../../utils/matches'
 
-interface CustomGroupMatchesProps {
+interface DoesCustomGroupMatchProps {
   customGroup: SingleCustomGroup | AnyOfCustomGroup
   selectors: Selector[]
   modifiers: Modifier[]
@@ -16,16 +16,18 @@ interface CustomGroupMatchesProps {
 
 /**
  * Determines whether a custom group matches the given properties.
- * @param {CustomGroupMatchesProps} props - The properties to compare with the
+ * @param {DoesCustomGroupMatchProps} props - The properties to compare with the
  * custom group, including selectors, modifiers, and element name.
  * @returns {boolean} `true` if the custom group matches the properties;
  * otherwise, `false`.
  */
-export let customGroupMatches = (props: CustomGroupMatchesProps): boolean => {
+export let doesCustomGroupMatch = (
+  props: DoesCustomGroupMatchProps,
+): boolean => {
   if ('anyOf' in props.customGroup) {
     // At least one subgroup must match
     return props.customGroup.anyOf.some(subgroup =>
-      customGroupMatches({ ...props, customGroup: subgroup }),
+      doesCustomGroupMatch({ ...props, customGroup: subgroup }),
     )
   }
   if (
diff --git a/utils/is-member-optional.ts b/rules/sort-object-types/is-member-optional.ts
similarity index 100%
rename from utils/is-member-optional.ts
rename to rules/sort-object-types/is-member-optional.ts
diff --git a/rules/sort-object-types.types.ts b/rules/sort-object-types/types.ts
similarity index 97%
rename from rules/sort-object-types.types.ts
rename to rules/sort-object-types/types.ts
index ed61ad0..3d0b2c6 100644
--- a/rules/sort-object-types.types.ts
+++ b/rules/sort-object-types/types.ts
@@ -1,12 +1,12 @@
 import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'
 
-import type { JoinWithDash } from '../typings'
+import type { JoinWithDash } from '../../types/join-with-dash'
 
 import {
   buildCustomGroupModifiersJsonSchema,
   buildCustomGroupSelectorJsonSchema,
   elementNamePatternJsonSchema,
-} from '../utils/common-json-schemas'
+} from '../../utils/common-json-schemas'
 
 export type Options = Partial<{
   useConfigurationIf: {
diff --git a/rules/sort-objects.ts b/rules/sort-objects.ts
index ebe0d04..ee75d30 100644
--- a/rules/sort-objects.ts
+++ b/rules/sort-objects.ts
@@ -22,7 +22,7 @@ import {
 } from '../utils/sort-nodes-by-dependencies'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import { getFirstNodeParentWithType } from '../utils/get-first-node-parent-with-type'
+import { getFirstNodeParentWithType } from './sort-objects/get-first-node-parent-with-type'
 import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
diff --git a/utils/get-first-node-parent-with-type.ts b/rules/sort-objects/get-first-node-parent-with-type.ts
similarity index 100%
rename from utils/get-first-node-parent-with-type.ts
rename to rules/sort-objects/get-first-node-parent-with-type.ts
diff --git a/rules/sort-sets.ts b/rules/sort-sets.ts
index cdfcd18..531f2e7 100644
--- a/rules/sort-sets.ts
+++ b/rules/sort-sets.ts
@@ -1,4 +1,4 @@
-import type { Options } from './sort-array-includes.types'
+import type { Options } from './sort-array-includes/types'
 
 import { defaultOptions, jsonSchema, sortArray } from './sort-array-includes'
 import { createEslintRule } from '../utils/create-eslint-rule'
diff --git a/rules/sort-switch-case.ts b/rules/sort-switch-case.ts
index 69fd50d..7f166d4 100644
--- a/rules/sort-switch-case.ts
+++ b/rules/sort-switch-case.ts
@@ -1,7 +1,7 @@
 import type { TSESTree } from '@typescript-eslint/types'
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   specialCharactersJsonSchema,
diff --git a/rules/sort-union-types.ts b/rules/sort-union-types.ts
index d7521fa..8e66902 100644
--- a/rules/sort-union-types.ts
+++ b/rules/sort-union-types.ts
@@ -1,4 +1,4 @@
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import {
   partitionByCommentJsonSchema,
diff --git a/typings/eslint-plugin-eslint-plugin.d.ts b/types/eslint-plugin-eslint-plugin.d.ts
similarity index 100%
rename from typings/eslint-plugin-eslint-plugin.d.ts
rename to types/eslint-plugin-eslint-plugin.d.ts
diff --git a/typings/join-with-dash.ts b/types/join-with-dash.ts
similarity index 100%
rename from typings/join-with-dash.ts
rename to types/join-with-dash.ts
diff --git a/typings/join.ts b/types/join.ts
similarity index 100%
rename from typings/join.ts
rename to types/join.ts
diff --git a/typings/sorting-node.ts b/types/sorting-node.ts
similarity index 100%
rename from typings/sorting-node.ts
rename to types/sorting-node.ts
diff --git a/typings/index.ts b/typings/index.ts
deleted file mode 100644
index 6beb32c..0000000
--- a/typings/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export type { JoinWithDash } from './join-with-dash'
-export type { SortingNode } from './sorting-node'
diff --git a/utils/compare.ts b/utils/compare.ts
index ed43d9e..a32b6db 100644
--- a/utils/compare.ts
+++ b/utils/compare.ts
@@ -1,6 +1,6 @@
 import { compare as createNaturalCompare } from 'natural-orderby'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import { convertBooleanToSign } from './convert-boolean-to-sign'
 
diff --git a/utils/create-node-index-map.ts b/utils/create-node-index-map.ts
index f606f57..3b5ec1e 100644
--- a/utils/create-node-index-map.ts
+++ b/utils/create-node-index-map.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 export let createNodeIndexMap = <Node extends TSESTree.Node>(
   nodes: SortingNode<Node>[],
diff --git a/utils/get-custom-groups-compare-options.ts b/utils/get-custom-groups-compare-options.ts
index ad765ca..1b7244b 100644
--- a/utils/get-custom-groups-compare-options.ts
+++ b/utils/get-custom-groups-compare-options.ts
@@ -1,5 +1,5 @@
+import type { SortingNode } from '../types/sorting-node'
 import type { CompareOptions } from './compare'
-import type { SortingNode } from '../typings'
 
 interface Options {
   customGroups: Record<string, string[] | string> | CustomGroup[]
diff --git a/utils/get-group-number.ts b/utils/get-group-number.ts
index e3ac728..d5b2f54 100644
--- a/utils/get-group-number.ts
+++ b/utils/get-group-number.ts
@@ -1,4 +1,4 @@
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 export let getGroupNumber = (
   groups: (string[] | string)[],
diff --git a/utils/get-lines-between.ts b/utils/get-lines-between.ts
index 744b2c9..0052f98 100644
--- a/utils/get-lines-between.ts
+++ b/utils/get-lines-between.ts
@@ -1,6 +1,6 @@
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 export let getLinesBetween = (
   source: TSESLint.SourceCode,
diff --git a/utils/get-newlines-errors.ts b/utils/get-newlines-errors.ts
index 35a3f0b..17bfea2 100644
--- a/utils/get-newlines-errors.ts
+++ b/utils/get-newlines-errors.ts
@@ -1,6 +1,6 @@
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import { getLinesBetween } from './get-lines-between'
 
diff --git a/utils/make-fixes.ts b/utils/make-fixes.ts
index 1136907..61c1dfe 100644
--- a/utils/make-fixes.ts
+++ b/utils/make-fixes.ts
@@ -1,6 +1,6 @@
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import { makeCommentAfterFixes } from './make-comment-after-fixes'
 import { getNodeRange } from './get-node-range'
diff --git a/utils/make-newlines-fixes.ts b/utils/make-newlines-fixes.ts
index 95af5de..2a7f08f 100644
--- a/utils/make-newlines-fixes.ts
+++ b/utils/make-newlines-fixes.ts
@@ -1,6 +1,6 @@
 import type { TSESLint } from '@typescript-eslint/utils'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 import { getLinesBetween } from './get-lines-between'
 import { getGroupNumber } from './get-group-number'
diff --git a/utils/sort-nodes-by-dependencies.ts b/utils/sort-nodes-by-dependencies.ts
index 5915454..b6cdb0b 100644
--- a/utils/sort-nodes-by-dependencies.ts
+++ b/utils/sort-nodes-by-dependencies.ts
@@ -1,6 +1,6 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../types/sorting-node'
 
 export interface SortingNodeWithDependencies<
   Node extends TSESTree.Node = TSESTree.Node,
diff --git a/utils/sort-nodes-by-groups.ts b/utils/sort-nodes-by-groups.ts
index 72ce9e7..c32dcd8 100644
--- a/utils/sort-nodes-by-groups.ts
+++ b/utils/sort-nodes-by-groups.ts
@@ -1,5 +1,5 @@
+import type { SortingNode } from '../types/sorting-node'
 import type { CompareOptions } from './compare'
-import type { SortingNode } from '../typings'
 
 import { getGroupNumber } from './get-group-number'
 import { sortNodes } from './sort-nodes'
diff --git a/utils/sort-nodes.ts b/utils/sort-nodes.ts
index 9d591dd..655cda8 100644
--- a/utils/sort-nodes.ts
+++ b/utils/sort-nodes.ts
@@ -1,5 +1,5 @@
+import type { SortingNode } from '../types/sorting-node'
 import type { CompareOptions } from './compare'
-import type { SortingNode } from '../typings'
 
 import { compare } from './compare'
 
diff --git a/vite.config.ts b/vite.config.ts
index 040661b..9d93819 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -98,7 +98,7 @@ export default defineConfig({
       },
       include: [
         path.join(__dirname, 'index.ts'),
-        path.join(__dirname, 'typings'),
+        path.join(__dirname, 'types'),
         path.join(__dirname, 'rules'),
         path.join(__dirname, 'utils'),
       ],


Test patch:
diff --git a/test/fixtures/tsconfig.json b/test/fixtures/tsconfig.json
index cb938d7..fe8f1d6 100644
--- a/test/fixtures/tsconfig.json
+++ b/test/fixtures/tsconfig.json
@@ -8,5 +8,11 @@
     "target": "es5",
     "strict": true
   },
-  "include": ["file.svelte", "file.astro", "react.tsx", "file.vue", "file.ts"]
+  "include": [
+    "../fixtures/file.svelte",
+    "../fixtures/file.astro",
+    "../fixtures/react.tsx",
+    "../fixtures/file.vue",
+    "../fixtures/file.ts"
+  ]
 }
diff --git a/test/sort-array-includes.test.ts b/test/rules/sort-array-includes.test.ts
similarity index 99%
rename from test/sort-array-includes.test.ts
rename to test/rules/sort-array-includes.test.ts
index b90c430..1a341ce 100644
--- a/test/sort-array-includes.test.ts
+++ b/test/rules/sort-array-includes.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-array-includes'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-array-includes'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-array-includes'
 
diff --git a/test/sort-classes.test.ts b/test/rules/sort-classes.test.ts
similarity index 98%
rename from test/sort-classes.test.ts
rename to test/rules/sort-classes.test.ts
index 2f7e7ed..2b97c94 100644
--- a/test/sort-classes.test.ts
+++ b/test/rules/sort-classes.test.ts
@@ -1,23 +1,12 @@
 import type { Rule } from 'eslint'
 
-import { expectTypeOf, afterAll, describe, it } from 'vitest'
 import { RuleTester } from '@typescript-eslint/rule-tester'
 import { RuleTester as EslintRuleTester } from 'eslint'
+import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import type {
-  GetMethodOrSetMethodGroup,
-  NonDeclarePropertyGroup,
-  FunctionPropertyGroup,
-  AccessorPropertyGroup,
-  DeclarePropertyGroup,
-  IndexSignatureGroup,
-  ConstructorGroup,
-  MethodGroup,
-} from '../rules/sort-classes.types'
-
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-classes'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-classes'
 
 let ruleName = 'sort-classes'
 
@@ -8759,78 +8748,4 @@ describe(ruleName, () => {
       },
     )
   })
-
-  describe(`${ruleName}: test types`, () => {
-    it('test get method or set method group type', () => {
-      expectTypeOf(
-        'get-method' as const,
-      ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
-
-      expectTypeOf(
-        'set-method' as const,
-      ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
-
-      expectTypeOf(
-        'protected-get-method' as const,
-      ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
-
-      expectTypeOf(
-        'public-decorated-get-method' as const,
-      ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
-    })
-
-    it('test non declare property group type', () => {
-      expectTypeOf(
-        'public-static-override-property' as const,
-      ).toMatchTypeOf<NonDeclarePropertyGroup>()
-    })
-
-    it('test function property group type', () => {
-      expectTypeOf(
-        'private-static-function-property' as const,
-      ).toMatchTypeOf<FunctionPropertyGroup>()
-    })
-
-    it('test accessor property group type', () => {
-      expectTypeOf(
-        'static-accessor-property' as const,
-      ).toMatchTypeOf<AccessorPropertyGroup>()
-
-      expectTypeOf(
-        'protected-static-accessor-property' as const,
-      ).toMatchTypeOf<AccessorPropertyGroup>()
-
-      expectTypeOf(
-        'accessor-property' as const,
-      ).toMatchTypeOf<AccessorPropertyGroup>()
-
-      expectTypeOf(
-        'protected-accessor-property' as const,
-      ).toMatchTypeOf<AccessorPropertyGroup>()
-    })
-
-    it('test declare property group type', () => {
-      expectTypeOf(
-        'declare-protected-static-readonly-property' as const,
-      ).toMatchTypeOf<DeclarePropertyGroup>()
-    })
-
-    it('test declare method group type', () => {
-      expectTypeOf('public-method' as const).toMatchTypeOf<MethodGroup>()
-
-      expectTypeOf('protected-method' as const).toMatchTypeOf<MethodGroup>()
-
-      expectTypeOf('private-method' as const).toMatchTypeOf<MethodGroup>()
-    })
-
-    it('test constructor group type', () => {
-      expectTypeOf('constructor' as const).toMatchTypeOf<ConstructorGroup>()
-    })
-
-    it('test index signature group type', () => {
-      expectTypeOf(
-        'index-signature' as const,
-      ).toMatchTypeOf<IndexSignatureGroup>()
-    })
-  })
 })
diff --git a/test/rules/sort-classes/type.test.ts b/test/rules/sort-classes/type.test.ts
new file mode 100644
index 0000000..cf40dba
--- /dev/null
+++ b/test/rules/sort-classes/type.test.ts
@@ -0,0 +1,88 @@
+import { expectTypeOf, describe, it } from 'vitest'
+
+import type {
+  GetMethodOrSetMethodGroup,
+  NonDeclarePropertyGroup,
+  FunctionPropertyGroup,
+  AccessorPropertyGroup,
+  DeclarePropertyGroup,
+  IndexSignatureGroup,
+  ConstructorGroup,
+  MethodGroup,
+} from '../../../rules/sort-classes/types'
+
+let ruleName = 'sort-classes'
+
+describe(`${ruleName}: test types`, () => {
+  it('test get method or set method group type', () => {
+    expectTypeOf(
+      'get-method' as const,
+    ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
+
+    expectTypeOf(
+      'set-method' as const,
+    ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
+
+    expectTypeOf(
+      'protected-get-method' as const,
+    ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
+
+    expectTypeOf(
+      'public-decorated-get-method' as const,
+    ).toMatchTypeOf<GetMethodOrSetMethodGroup>()
+  })
+
+  it('test non declare property group type', () => {
+    expectTypeOf(
+      'public-static-override-property' as const,
+    ).toMatchTypeOf<NonDeclarePropertyGroup>()
+  })
+
+  it('test function property group type', () => {
+    expectTypeOf(
+      'private-static-function-property' as const,
+    ).toMatchTypeOf<FunctionPropertyGroup>()
+  })
+
+  it('test accessor property group type', () => {
+    expectTypeOf(
+      'static-accessor-property' as const,
+    ).toMatchTypeOf<AccessorPropertyGroup>()
+
+    expectTypeOf(
+      'protected-static-accessor-property' as const,
+    ).toMatchTypeOf<AccessorPropertyGroup>()
+
+    expectTypeOf(
+      'accessor-property' as const,
+    ).toMatchTypeOf<AccessorPropertyGroup>()
+
+    expectTypeOf(
+      'protected-accessor-property' as const,
+    ).toMatchTypeOf<AccessorPropertyGroup>()
+  })
+
+  it('test declare property group type', () => {
+    expectTypeOf(
+      'declare-protected-static-readonly-property' as const,
+    ).toMatchTypeOf<DeclarePropertyGroup>()
+  })
+
+  it('test declare method group type', () => {
+    expectTypeOf('public-method' as const).toMatchTypeOf<MethodGroup>()
+
+    expectTypeOf('protected-method' as const).toMatchTypeOf<MethodGroup>()
+
+    expectTypeOf('private-method' as const).toMatchTypeOf<MethodGroup>()
+  })
+
+  it('test constructor group type', () => {
+    expectTypeOf('constructor' as const).toMatchTypeOf<ConstructorGroup>()
+  })
+
+  it('test index signature group type', () => {
+    expectTypeOf(
+      'index-signature' as const,
+    ).toMatchTypeOf<IndexSignatureGroup>()
+  })
+})
diff --git a/test/sort-decorators.test.ts b/test/rules/sort-decorators.test.ts
similarity index 99%
rename from test/sort-decorators.test.ts
rename to test/rules/sort-decorators.test.ts
index 2d66c17..54ab7e9 100644
--- a/test/sort-decorators.test.ts
+++ b/test/rules/sort-decorators.test.ts
@@ -6,8 +6,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-decorators'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-decorators'
 
 let ruleName = 'sort-decorators'
 
diff --git a/test/get-decorator-name.test.ts b/test/rules/sort-decorators/get-decorator-name.test.ts
similarity index 95%
rename from test/get-decorator-name.test.ts
rename to test/rules/sort-decorators/get-decorator-name.test.ts
index 8ff6a17..9cabc7c 100644
--- a/test/get-decorator-name.test.ts
+++ b/test/rules/sort-decorators/get-decorator-name.test.ts
@@ -3,7 +3,7 @@ import type { TSESTree } from '@typescript-eslint/types'
 import { AST_NODE_TYPES } from '@typescript-eslint/types'
 import { describe, expect, it } from 'vitest'
 
-import { getDecoratorName } from '../utils/get-decorator-name'
+import { getDecoratorName } from '../../../rules/sort-decorators/get-decorator-name'
 
 describe('get-decorator-name', () => {
   describe('call expressions', () => {
diff --git a/test/sort-enums.test.ts b/test/rules/sort-enums.test.ts
similarity index 99%
rename from test/sort-enums.test.ts
rename to test/rules/sort-enums.test.ts
index ca7ffc1..13a18de 100644
--- a/test/sort-enums.test.ts
+++ b/test/rules/sort-enums.test.ts
@@ -2,10 +2,10 @@ import { RuleTester } from '@typescript-eslint/rule-tester'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import type { Options } from '../rules/sort-enums'
+import type { Options } from '../../rules/sort-enums'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-enums'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-enums'
 
 let ruleName = 'sort-enums'
 
diff --git a/test/sort-exports.test.ts b/test/rules/sort-exports.test.ts
similarity index 99%
rename from test/sort-exports.test.ts
rename to test/rules/sort-exports.test.ts
index 004600b..b23fb93 100644
--- a/test/sort-exports.test.ts
+++ b/test/rules/sort-exports.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-exports'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-exports'
 
 let ruleName = 'sort-exports'
 
diff --git a/test/sort-heritage-clauses.test.ts b/test/rules/sort-heritage-clauses.test.ts
similarity index 99%
rename from test/sort-heritage-clauses.test.ts
rename to test/rules/sort-heritage-clauses.test.ts
index 32659ca..b752fcf 100644
--- a/test/sort-heritage-clauses.test.ts
+++ b/test/rules/sort-heritage-clauses.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-heritage-clauses'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-heritage-clauses'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-heritage-clauses'
 
diff --git a/test/sort-imports.test.ts b/test/rules/sort-imports.test.ts
similarity index 99%
rename from test/sort-imports.test.ts
rename to test/rules/sort-imports.test.ts
index e2f672a..e24640f 100644
--- a/test/sort-imports.test.ts
+++ b/test/rules/sort-imports.test.ts
@@ -11,12 +11,12 @@ import { createModuleResolutionCache } from 'typescript'
 import { RuleTester as EslintRuleTester } from 'eslint'
 import { dedent } from 'ts-dedent'
 
-import type { MESSAGE_ID, Options } from '../rules/sort-imports'
+import type { MESSAGE_ID, Options } from '../../rules/sort-imports'
 
-import * as readClosestTsConfigUtils from '../utils/read-closest-ts-config-by-path'
-import * as getTypescriptImportUtils from '../utils/get-typescript-import'
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-imports'
+import * as readClosestTsConfigUtils from '../../rules/sort-imports/read-closest-ts-config-by-path'
+import * as getTypescriptImportUtils from '../../rules/sort-imports/get-typescript-import'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-imports'
 
 let ruleName = 'sort-imports'
 
diff --git a/test/get-typescript-import.test.ts b/test/rules/sort-imports/get-typescript-import.test.ts
similarity index 85%
rename from test/get-typescript-import.test.ts
rename to test/rules/sort-imports/get-typescript-import.test.ts
index 089e698..5d38e14 100644
--- a/test/get-typescript-import.test.ts
+++ b/test/rules/sort-imports/get-typescript-import.test.ts
@@ -3,7 +3,7 @@ import type { Mock } from 'vitest'
 import { beforeEach, describe, expect, it, vi } from 'vitest'
 import * as ts from 'typescript'
 
-import type { getTypescriptImport as testedFunction } from '../utils/get-typescript-import'
+import type { getTypescriptImport as testedFunction } from '../../../rules/sort-imports/get-typescript-import'
 
 let mockCreateRequire: Mock<() => typeof ts> = vi.fn()
 
@@ -15,7 +15,9 @@ describe('getTypescriptImport', () => {
   let getTypescriptImport: typeof testedFunction
 
   beforeEach(async () => {
-    ;({ getTypescriptImport } = await import('../utils/get-typescript-import'))
+    ;({ getTypescriptImport } = await import(
+      '../../../rules/sort-imports/get-typescript-import'
+    ))
     vi.clearAllMocks()
     vi.resetModules()
   })
diff --git a/test/read-closest-ts-config-by-path.test.ts b/test/rules/sort-imports/read-closest-ts-config-by-path.test.ts
similarity index 88%
rename from test/read-closest-ts-config-by-path.test.ts
rename to test/rules/sort-imports/read-closest-ts-config-by-path.test.ts
index f036222..d3ed590 100644
--- a/test/read-closest-ts-config-by-path.test.ts
+++ b/test/rules/sort-imports/read-closest-ts-config-by-path.test.ts
@@ -7,9 +7,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
 import path from 'node:path'
 import ts from 'typescript'
 
-import type { readClosestTsConfigByPath as testedFunction } from '../utils/read-closest-ts-config-by-path'
-
-// Heavily inspired from https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-estree/tests/lib/getProjectConfigFiles.test.ts
+import type { readClosestTsConfigByPath as testedFunction } from '../../../rules/sort-imports/read-closest-ts-config-by-path'
 
 let mockExistsSync: Mock<(filePath: string) => boolean> = vi.fn()
 
@@ -42,14 +40,14 @@ vi.mock('node:module', _ => ({
 
 let mockGetTypescriptImport: Mock<() => null> = vi.fn()
 
-vi.mock('../utils/get-typescript-import', () => ({
+vi.mock('../../../rules/sort-imports/get-typescript-import', () => ({
   getTypescriptImport: () => mockGetTypescriptImport(),
 }))
 
 let testInput = {
-  filePath: './repos/repo/packages/package/file.ts',
-  tsconfigRootDir: './repos/repo',
-  contextCwd: './',
+  filePath: '../../repos/repo/packages/package/file.ts',
+  tsconfigRootDir: '../../repos/repo',
+  contextCwd: '../../../',
 }
 
 let tsConfigContent = {
@@ -67,7 +65,7 @@ describe('readClosestTsConfigByPath', () => {
 
   beforeEach(async () => {
     ;({ readClosestTsConfigByPath } = await import(
-      '../utils/read-closest-ts-config-by-path'
+      '../../../rules/sort-imports/read-closest-ts-config-by-path'
     ))
     vi.clearAllMocks()
     vi.resetModules()
@@ -85,7 +83,7 @@ describe('readClosestTsConfigByPath', () => {
   describe('with typescript present', () => {
     beforeEach(async () => {
       let actualGetTypescriptImport = await vi.importActual(
-        '../utils/get-typescript-import',
+        '../../../rules/sort-imports/get-typescript-import',
       )
       mockGetTypescriptImport.mockImplementation(
         actualGetTypescriptImport.getTypescriptImport as never,
@@ -150,11 +148,13 @@ describe('readClosestTsConfigByPath', () => {
         readClosestTsConfigByPath({
           filePath: './a/b/c/d.ts',
           tsconfigRootDir: './a',
-          contextCwd: './',
+          contextCwd: '../../',
         })
 
-        // This should call to fs.existsSync once: e
-        // Then it should retrieve c from cache, pointing to a
+        /**
+         * This should call to fs.existsSync once: e
+         * Then it should retrieve c from cache, pointing to a
+         */
         let actual = readClosestTsConfigByPath({
           filePath: './a/b/c/e/f.ts',
           tsconfigRootDir: './a',
@@ -175,19 +175,23 @@ describe('readClosestTsConfigByPath', () => {
         mockParseJsonConfigFileContentReturnValue()
         mockConvertCompilerOptionsFromJsonReturnValue()
 
-        // This should call to fs.existsSync 4 times: d, c, b, a
+        /**
+         * This should call to fs.existsSync 4 times: d, c, b, a
+         */
         readClosestTsConfigByPath({
           filePath: './a/b/c/d/e.ts',
           tsconfigRootDir: './a',
-          contextCwd: './',
+          contextCwd: '../../',
         })
 
-        // This should call to fs.existsSync 2: g, f
-        // Then it should retrieve b from cache, pointing to a
+        /**
+         * This should call to fs.existsSync 2: g, f
+         * Then it should retrieve b from cache, pointing to a
+         */
         let actual = readClosestTsConfigByPath({
           filePath: './a/b/f/g/h.ts',
           tsconfigRootDir: './a',
-          contextCwd: './',
+          contextCwd: '../../',
         })
 
         expect(actual?.compilerOptions).toEqual(
@@ -213,7 +217,8 @@ describe('readClosestTsConfigByPath', () => {
 
       it('returns a parent tsconfig.json when matched', () => {
         mockExistsSync.mockImplementation(
-          filePath => filePath === path.normalize('repos/repo/tsconfig.json'),
+          filePath =>
+            filePath === path.normalize('../../repos/repo/tsconfig.json'),
         )
         mockReadConfigFileReturnValue()
         mockParseJsonConfigFileContentReturnValue()
@@ -234,7 +239,7 @@ describe('readClosestTsConfigByPath', () => {
         expect(() =>
           readClosestTsConfigByPath(testInput),
         ).toThrowErrorMatchingInlineSnapshot(
-          `[Error: Couldn't find any tsconfig.json relative to './repos/repo/packages/package/file.ts' within './repos/repo'.]`,
+          `[Error: Couldn't find any tsconfig.json relative to '../../repos/repo/packages/package/file.ts' within '../../repos/repo'.]`,
         )
       })
 
@@ -246,7 +251,7 @@ describe('readClosestTsConfigByPath', () => {
         expect(() =>
           readClosestTsConfigByPath({ ...testInput, tsconfigRootDir: '/' }),
         ).toThrowErrorMatchingInlineSnapshot(
-          `[Error: Couldn't find any tsconfig.json relative to './repos/repo/packages/package/file.ts' within '/'.]`,
+          `[Error: Couldn't find any tsconfig.json relative to '../../repos/repo/packages/package/file.ts' within '/'.]`,
         )
       })
     })
diff --git a/test/sort-interfaces.test.ts b/test/rules/sort-interfaces.test.ts
similarity index 99%
rename from test/sort-interfaces.test.ts
rename to test/rules/sort-interfaces.test.ts
index 34f82a5..a983f47 100644
--- a/test/sort-interfaces.test.ts
+++ b/test/rules/sort-interfaces.test.ts
@@ -2,10 +2,10 @@ import { RuleTester } from '@typescript-eslint/rule-tester'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import type { Options } from '../rules/sort-interfaces'
+import type { Options } from '../../rules/sort-interfaces'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-interfaces'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-interfaces'
 
 let ruleName = 'sort-interfaces'
 
diff --git a/test/sort-intersection-types.test.ts b/test/rules/sort-intersection-types.test.ts
similarity index 99%
rename from test/sort-intersection-types.test.ts
rename to test/rules/sort-intersection-types.test.ts
index d1cadbb..7c6a16e 100644
--- a/test/sort-intersection-types.test.ts
+++ b/test/rules/sort-intersection-types.test.ts
@@ -2,8 +2,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-intersection-types'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-intersection-types'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-intersection-types'
 
diff --git a/test/sort-jsx-props.test.ts b/test/rules/sort-jsx-props.test.ts
similarity index 99%
rename from test/sort-jsx-props.test.ts
rename to test/rules/sort-jsx-props.test.ts
index 675d994..85a6ff8 100644
--- a/test/sort-jsx-props.test.ts
+++ b/test/rules/sort-jsx-props.test.ts
@@ -4,8 +4,8 @@ import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 import path from 'node:path'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-jsx-props'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-jsx-props'
 
 let ruleName = 'sort-jsx-props'
 
@@ -20,7 +20,7 @@ describe(ruleName, () => {
   let ruleTester = new RuleTester({
     languageOptions: {
       parserOptions: {
-        tsconfigRootDir: path.join(__dirname, './fixtures'),
+        tsconfigRootDir: path.join(__dirname, '../fixtures'),
         extraFileExtensions: ['.svelte', '.astro', '.vue'],
         ecmaFeatures: {
           jsx: true,
diff --git a/test/sort-maps.test.ts b/test/rules/sort-maps.test.ts
similarity index 99%
rename from test/sort-maps.test.ts
rename to test/rules/sort-maps.test.ts
index 5d2ef75..821fb34 100644
--- a/test/sort-maps.test.ts
+++ b/test/rules/sort-maps.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-maps'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-maps'
 
 let ruleName = 'sort-maps'
 
diff --git a/test/sort-modules.test.ts b/test/rules/sort-modules.test.ts
similarity index 99%
rename from test/sort-modules.test.ts
rename to test/rules/sort-modules.test.ts
index caaf580..ef2698f 100644
--- a/test/sort-modules.test.ts
+++ b/test/rules/sort-modules.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-modules'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-modules'
 
 let ruleName = 'sort-modules'
 
diff --git a/test/sort-named-exports.test.ts b/test/rules/sort-named-exports.test.ts
similarity index 99%
rename from test/sort-named-exports.test.ts
rename to test/rules/sort-named-exports.test.ts
index a80e609..85acd23 100644
--- a/test/sort-named-exports.test.ts
+++ b/test/rules/sort-named-exports.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-named-exports'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-named-exports'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-named-exports'
 
diff --git a/test/sort-named-imports.test.ts b/test/rules/sort-named-imports.test.ts
similarity index 99%
rename from test/sort-named-imports.test.ts
rename to test/rules/sort-named-imports.test.ts
index a54c281..6f83ec1 100644
--- a/test/sort-named-imports.test.ts
+++ b/test/rules/sort-named-imports.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-named-imports'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-named-imports'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-named-imports'
 
diff --git a/test/sort-object-types.test.ts b/test/rules/sort-object-types.test.ts
similarity index 99%
rename from test/sort-object-types.test.ts
rename to test/rules/sort-object-types.test.ts
index 3f9ded1..d05124c 100644
--- a/test/sort-object-types.test.ts
+++ b/test/rules/sort-object-types.test.ts
@@ -2,8 +2,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-object-types'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-object-types'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-object-types'
 
diff --git a/test/sort-objects.test.ts b/test/rules/sort-objects.test.ts
similarity index 99%
rename from test/sort-objects.test.ts
rename to test/rules/sort-objects.test.ts
index 4b6d8df..d9fb440 100644
--- a/test/sort-objects.test.ts
+++ b/test/rules/sort-objects.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-objects'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-objects'
 
 let ruleName = 'sort-objects'
 
diff --git a/test/sort-sets.test.ts b/test/rules/sort-sets.test.ts
similarity index 99%
rename from test/sort-sets.test.ts
rename to test/rules/sort-sets.test.ts
index 6d9f66d..9560a1b 100644
--- a/test/sort-sets.test.ts
+++ b/test/rules/sort-sets.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import { Alphabet } from '../utils/alphabet'
-import rule from '../rules/sort-sets'
+import { Alphabet } from '../../utils/alphabet'
+import rule from '../../rules/sort-sets'
 
 let ruleName = 'sort-sets'
 
diff --git a/test/sort-switch-case.test.ts b/test/rules/sort-switch-case.test.ts
similarity index 99%
rename from test/sort-switch-case.test.ts
rename to test/rules/sort-switch-case.test.ts
index 61d6343..dbffee1 100644
--- a/test/sort-switch-case.test.ts
+++ b/test/rules/sort-switch-case.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-switch-case'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-switch-case'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-switch-case'
 
diff --git a/test/sort-union-types.test.ts b/test/rules/sort-union-types.test.ts
similarity index 99%
rename from test/sort-union-types.test.ts
rename to test/rules/sort-union-types.test.ts
index 49129ad..671d3bf 100644
--- a/test/sort-union-types.test.ts
+++ b/test/rules/sort-union-types.test.ts
@@ -2,8 +2,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-union-types'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-union-types'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-union-types'
 
diff --git a/test/sort-variable-declarations.test.ts b/test/rules/sort-variable-declarations.test.ts
similarity index 99%
rename from test/sort-variable-declarations.test.ts
rename to test/rules/sort-variable-declarations.test.ts
index 686726d..ec43356 100644
--- a/test/sort-variable-declarations.test.ts
+++ b/test/rules/sort-variable-declarations.test.ts
@@ -5,8 +5,8 @@ import { RuleTester as EslintRuleTester } from 'eslint'
 import { afterAll, describe, it } from 'vitest'
 import { dedent } from 'ts-dedent'
 
-import rule from '../rules/sort-variable-declarations'
-import { Alphabet } from '../utils/alphabet'
+import rule from '../../rules/sort-variable-declarations'
+import { Alphabet } from '../../utils/alphabet'
 
 let ruleName = 'sort-variable-declarations'
 
diff --git a/test/alphabet.test.ts b/test/utils/alphabet.test.ts
similarity index 99%
rename from test/alphabet.test.ts
rename to test/utils/alphabet.test.ts
index ecc1846..86f5c24 100644
--- a/test/alphabet.test.ts
+++ b/test/utils/alphabet.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { Alphabet } from '../utils/alphabet'
+import { Alphabet } from '../../utils/alphabet'
 
 describe('alphabet', () => {
   describe('generators', () => {
diff --git a/test/compare.test.ts b/test/utils/compare.test.ts
similarity index 97%
rename from test/compare.test.ts
rename to test/utils/compare.test.ts
index f34d74b..1384f15 100644
--- a/test/compare.test.ts
+++ b/test/utils/compare.test.ts
@@ -1,9 +1,9 @@
 import { describe, expect, it } from 'vitest'
 
-import type { SortingNode } from '../typings'
+import type { SortingNode } from '../../types/sorting-node'
 
-import { Alphabet } from '../utils/alphabet'
-import { compare } from '../utils/compare'
+import { Alphabet } from '../../utils/alphabet'
+import { compare } from '../../utils/compare'
 
 describe('compare', () => {
   describe('alphabetical', () => {
diff --git a/test/generate-predefined-groups.test.ts b/test/utils/generate-predefined-groups.test.ts
similarity index 94%
rename from test/generate-predefined-groups.test.ts
rename to test/utils/generate-predefined-groups.test.ts
index 9f52901..d20ae74 100644
--- a/test/generate-predefined-groups.test.ts
+++ b/test/utils/generate-predefined-groups.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
+import { generatePredefinedGroups } from '../../utils/generate-predefined-groups'
 
 describe('generate-predefined-groups', () => {
   it('should generate official groups', () => {
diff --git a/test/get-array-combinations.test.ts b/test/utils/get-array-combinations.test.ts
similarity index 80%
rename from test/get-array-combinations.test.ts
rename to test/utils/get-array-combinations.test.ts
index b3e74b6..22fd52f 100644
--- a/test/get-array-combinations.test.ts
+++ b/test/utils/get-array-combinations.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { getArrayCombinations } from '../utils/get-array-combinations'
+import { getArrayCombinations } from '../../utils/get-array-combinations'
 
 describe('get-array-combinations', () => {
   it('gets array combinations', () => {
diff --git a/test/get-eslint-disabled-rules.test.ts b/test/utils/get-eslint-disabled-rules.test.ts
similarity index 92%
rename from test/get-eslint-disabled-rules.test.ts
rename to test/utils/get-eslint-disabled-rules.test.ts
index 815e679..9a1c8ab 100644
--- a/test/get-eslint-disabled-rules.test.ts
+++ b/test/utils/get-eslint-disabled-rules.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { getEslintDisabledRules } from '../utils/get-eslint-disabled-rules'
+import { getEslintDisabledRules } from '../../utils/get-eslint-disabled-rules'
 
 let eslintDisableDirectives = [
   'eslint-disable',
diff --git a/test/get-matching-context-options.test.ts b/test/utils/get-matching-context-options.test.ts
similarity index 94%
rename from test/get-matching-context-options.test.ts
rename to test/utils/get-matching-context-options.test.ts
index e6ea050..70fb3e7 100644
--- a/test/get-matching-context-options.test.ts
+++ b/test/utils/get-matching-context-options.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { getMatchingContextOptions } from '../utils/get-matching-context-options'
+import { getMatchingContextOptions } from '../../utils/get-matching-context-options'
 
 describe('get-matching-context-options', () => {
   describe('`allNamesMatchPattern`', () => {
diff --git a/test/clean-groups-option.test.ts b/test/utils/get-options-with-clean-groups.test.ts
similarity index 85%
rename from test/clean-groups-option.test.ts
rename to test/utils/get-options-with-clean-groups.test.ts
index 9da819c..a0bc86b 100644
--- a/test/clean-groups-option.test.ts
+++ b/test/utils/get-options-with-clean-groups.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { getOptionsWithCleanGroups } from '../utils/get-options-with-clean-groups'
+import { getOptionsWithCleanGroups } from '../../utils/get-options-with-clean-groups'
 
 describe('get-options-with-cleaned-groups', () => {
   it('get options with cleaned groups', () => {
diff --git a/test/get-settings.test.ts b/test/utils/get-settings.test.ts
similarity index 88%
rename from test/get-settings.test.ts
rename to test/utils/get-settings.test.ts
index 98a7a65..f3f899f 100644
--- a/test/get-settings.test.ts
+++ b/test/utils/get-settings.test.ts
@@ -1,8 +1,8 @@
 import { describe, expect, it } from 'vitest'
 
-import type { Settings } from '../utils/get-settings'
+import type { Settings } from '../../utils/get-settings'
 
-import { getSettings } from '../utils/get-settings'
+import { getSettings } from '../../utils/get-settings'
 
 describe('get-settings', () => {
   it('throws an error when an invalid setting is provided', () => {
diff --git a/test/validate-custom-sort-configuration.test.ts b/test/utils/validate-custom-sort-configuration.test.ts
similarity index 86%
rename from test/validate-custom-sort-configuration.test.ts
rename to test/utils/validate-custom-sort-configuration.test.ts
index aa2587c..9efb5b7 100644
--- a/test/validate-custom-sort-configuration.test.ts
+++ b/test/utils/validate-custom-sort-configuration.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
+import { validateCustomSortConfiguration } from '../../utils/validate-custom-sort-configuration'
 
 describe('validate-custom-sort-configuration', () => {
   it('accepts empty alphabet when type is not `custom`', () => {
diff --git a/test/validate-generated-groups-configuration.test.ts b/test/utils/validate-generated-groups-configuration.test.ts
similarity index 90%
rename from test/validate-generated-groups-configuration.test.ts
rename to test/utils/validate-generated-groups-configuration.test.ts
index e4d38c2..2266263 100644
--- a/test/validate-generated-groups-configuration.test.ts
+++ b/test/utils/validate-generated-groups-configuration.test.ts
@@ -1,8 +1,8 @@
 import { describe, expect, it } from 'vitest'
 
-import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
-import { allModifiers, allSelectors } from '../rules/sort-classes.types'
-import { getArrayCombinations } from '../utils/get-array-combinations'
+import { validateGeneratedGroupsConfiguration } from '../../utils/validate-generated-groups-configuration'
+import { allModifiers, allSelectors } from '../../rules/sort-classes/types'
+import { getArrayCombinations } from '../../utils/get-array-combinations'
 
 describe('validate-generated-groups-configuration', () => {
   it('allows predefined groups', () => {
diff --git a/test/validate-groups-configuration.test.ts b/test/utils/validate-groups-configuration.test.ts
similarity index 92%
rename from test/validate-groups-configuration.test.ts
rename to test/utils/validate-groups-configuration.test.ts
index 7456e71..404a23e 100644
--- a/test/validate-groups-configuration.test.ts
+++ b/test/utils/validate-groups-configuration.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
+import { validateGroupsConfiguration } from '../../utils/validate-groups-configuration'
 
 /**
  * It is currently not possible to test rules that throw errors
diff --git a/test/validate-newlines-and-partition-configuration.test.ts b/test/utils/validate-newlines-and-partition-configuration.test.ts
similarity index 93%
rename from test/validate-newlines-and-partition-configuration.test.ts
rename to test/utils/validate-newlines-and-partition-configuration.test.ts
index fd85098..e760d67 100644
--- a/test/validate-newlines-and-partition-configuration.test.ts
+++ b/test/utils/validate-newlines-and-partition-configuration.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 
-import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import { validateNewlinesAndPartitionConfiguration } from '../../utils/validate-newlines-and-partition-configuration'
 
 describe('validate-newlines-and-partition-configuration', () => {
   let partitionByCommentValues: (string[] | boolean | string)[] = [