Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Improve ending commas/semicolon behavior #337

Draft
wants to merge 18 commits into
base: next
Choose a base branch
from

Conversation

hugop95
Copy link
Contributor

@hugop95 hugop95 commented Oct 23, 2024

Fixes #336.

Very little code changes outside of tests:
image

Affected rules

  • sort-classes
  • sort-interfaces
  • sort-object-types
  • sort-imports
  • sort-exports

Description

Today, the way commas and semicolons are handled for a given node actually depends on multiple factors:

  • It depends on the rule.
    • A node in sort-objects will never include ,, while a node in sort-interfaces will. This is how the AST parser works. This means that rules that natively ignore commas and semicolons are not affected (sort-enums for example).
    • In sort-object-types and sort-interfaces, nodes will include ; and ,.
    • In sort-object-types, commas and semicolons are ignored for computing the length of a node with the line-length sorting type, but not in sort-interfaces.
      let endsWithComma = raw.endsWith(';') || raw.endsWith(',')
      let endSize = endsWithComma ? 1 : 0
      let sortingNode: SortObjectTypesSortingNode = {
      size: rangeToDiff(member.range) - endSize,
      group: getGroup(),
      node: member,
      name,
      }
  • To determine if a given node will move with its associated semicolon/comma (if it has one), we check the token after that semicolon/comma. If it exists and is on the same line as the node, the semicolon/comma associated to the node will not move.

The last point is problematic, because it fixes a problem in very specific cases (and not the one mentioned in the issue, for example).

Proposal

This PR does the following:

  • Make the line-length sorting type always ignore ending semicolons and commas for all rules, similarly to what sort-object-types does today.
  • Adds a semicolon to nodes that would potentially require one during inline sorting (see the logic below).

How to know if we need to add a semicolon to a node after sorting

Let's say that a node B needs to take the place of a node A after sorting.

First, B should indicate whether it requires an ending semicolon if inline with a following node.
In sort-classes for example, properties require an ending semicolon if inline, while non-abstract methods don't.

If B requires an ending semicolon, we should check whether if ends with a semicolon (or a comma) or not (as that semicolon will be brought with it when moving).

If B does not end with a semicolon/comma, check whether A (the place that B will take) has at least one inline token (other than a semicolon/comma) after it. If it does, this means that we should add a semicolon after B for safety.

There are cases where this process adds a semicolon when it is not actually necessary, but this does not break compilation and doesn't affect runtime. Furthermore, this is likely to be autocorrected by another ESLint rule and is easy to implement, so that's a quick-win in my book.

Also, let's not forget that although these bugs can be very problematic (breaking compilation/runtime), they are not likely to be reproduced that often in reality due to all the conditions required for those bugs to appear, so let's keep it not too complicated!

sort-classes: Types of nodes and whether they require an ending semicolon or not when inline with a following node

  • Methods:
    • If abstract: ✅
    • Else: ❌
  • Properties/Accessors: ✅ (including function properties!)
  • TS Index signature: ✅
  • Static block: ❌

Examples

Example 1

abstract class Class {
    myFunction(){}static{}abstract myAbstractFunction()
}

abstract class Class {
    static{}abstract myAbstractFunction();myFunction(){}
}

Example 2

abstract class Class {
    constructor(){}[key: string]: string
}

abstract class Class {
    [key: string]: string;constructor(){}
}

Consequences

  • Only one test (duplicated 2 times, for a different sorting type) in sort-object-types had its output fixed (See commit n°2)!

Additional changes

  • [Refactor] Uses sourceCode.getText() rather than slicing.
  • Avoids making a permutation autofix when a node is already at its expected place.

Remaining to do

Add inline tests for all rules! (even the ones not affected by #336)

  • sort-array-includes
  • sort-classes
  • sort-decorators No separator
  • sort-enums
  • sort-exports
  • sort-heritage-clauses
  • sort-imports
  • sort-interfaces
  • sort-intersection-types
  • sort-jsx-props No separator
  • sort-named-exports
  • sort-named-imports
  • sort-object-types
  • sort-objects
  • sort-sets
  • sort-switch-case (Not sure about that one)
  • sort-union-types
  • sort-variable-declarations

What is the purpose of this pull request?

  • Bug fix

@hugop95 hugop95 changed the title fix: makes sorting ignore , and ; fix: makes sorting ignore ending , and ; Oct 23, 2024
@hugop95 hugop95 changed the title fix: makes sorting ignore ending , and ; fix: makes most sorting nodes ignore trailing , and ; Oct 23, 2024
@hugop95 hugop95 force-pushed the fix/inline-fixes branch 2 times, most recently from 60220d9 to f463d51 Compare October 23, 2024 22:03
@hugop95 hugop95 changed the title fix: makes most sorting nodes ignore trailing , and ; fix: Improve ending commas/semicolon behavior Oct 23, 2024
@hugop95 hugop95 force-pushed the fix/inline-fixes branch 9 times, most recently from 19060b2 to 69acd61 Compare October 24, 2024 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant