eslint-plugin-perfectionist icon indicating copy to clipboard operation
eslint-plugin-perfectionist copied to clipboard

Feature: `sort-classes` Improved custom group system

Open hugop95 opened this issue 6 months ago • 3 comments

What rule do you want to change?

sort-classes

Describe the problem

The objective is to extend the custom grouping system of the sort-classes rule in order to respond to the following points

  • Extend custom group definitions to more than just pattern matching the name of an element. (see issue #165).
  • Allow users to explicitly define a custom group priority over other custom groups.
  • Allow users to override official groups priorities if they want.

For the sake of simplicity, I suppose that we are adding a advancedCustomGroups option to the list of existing options for this rule, but nothing prevents from using the existing customGroups option as well.

advancedCustomGroups could be an array of AdvancedCustomGroup, which follows the following interface:

interface SortClassesAdvancedCustomGroup {
  decoratorNamePattern?: string
  elementNamePattern?: string
  valueTypePattern?: string
  typeDeclarationPattern?: string
  modifiers?: string[]
  groupName: string
  selector: string
}

This interface is easily extensible if additional features need to be added later on.

  • groupName: The group's name. Today in customGroups, this is one key of the object.
  • selector: Filter on the selector of the element.
  • modifiers: Filter on the modifiers of the element. (All the modifiers of the element must be present in that list)
  • elementNamePattern: If entered, will check that the name of the element matches the pattern entered. Today in customGroups, this is the value associated to a key of the object.
  • decoratorNamePattern: If entered, will check that at least one decorator matches the pattern entered. (solves #165)
  • valueTypePattern: If entered, will check that the value type of the element matches the pattern entered. (can solve #189 with ArrowFunctionExpression and FunctionExpression, but I don't see other use cases for that otherwise)

I had in mind to have and conditions between selector, modifiers, decoratorNamePattern, valueTypePattern, etc... in order to match an element successfully.

Because advancedCustomGroups is a list of custom groups and not an object like it is the case with customGroups, this allows the user to properly define an order in which each advanced custom group should be used. Like customGroups, advancedCustomGroups would take priority over official groups if a match is found.

This system also allows users to replicate official groups by only using the selector and modifiers options. This allows them to still make sure that some official groups do not get overridden by other advanced custom groups by placing the official group replica first in the advancedCustomGroups list.

The same groupName can be used multiple times if needed. Official group names can be used as well.

Code example

Here is the simplified configuration that solves #165:

  {
            "groups": [
              "input",
              "output"
            ],
            "advancedCustomGroups": [
              {
                "groupName": "input",
                "decoratorNamePattern": "Input"
              },
              {
                "groupName": "output",
                "decoratorNamePattern": "Output"
              }
            ]
          }

Here is a simplified configuration that can solve #189:

{
            "groups": [
              [
                "public-method",
                "public-function-property"
              ],
              [
                "protected-method",
                "protected-function-property"
              ],
              [
                "private-method",
              ]
            ],
            "advancedCustomGroups": [
              {
                "groupName": "public-function-property",
                "selector": "property",
                "modifiers": ["public"],
                "valueTypePattern": "ArrowFunctionExpression"
              },
              {
                "groupName": "public-function-property",
                "selector": "property",
                "modifiers": ["public"],
                "valueTypePattern": "FunctionExpression"
              },
              {
                "groupName": "protected-function-property",
                "selector": "property",
                "modifiers": ["protected"],
                "valueTypePattern": "ArrowFunctionExpression" // Maybe it is possible to group both `FunctionExpression` and `ArrowFunctionExpression` at the same time with `minimatch`, I haven't looked it up.
              },
              {
                "groupName": "protected-function-property",
                "selector": "property",
                "modifiers": ["protected"],
                "valueTypePattern": "FunctionExpression"
              },
              {
                "groupName": "private-method", // Can even directly write `private-method` if we want
                "selector": "property",
                "modifiers": ["private"],
                "valueTypePattern": "ArrowFunctionExpression"
              },
              {
                "groupName": "private-method",
                "selector": "property",
                "modifiers": ["private"],
                "valueTypePattern": "FunctionExpression"
              }
            ]
          }

Validations

  • [X] Read the docs.
  • [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

hugop95 avatar Aug 09 '24 05:08 hugop95