Skip to content

feat: implement autofix for sort-keys#216

Open
sethamus wants to merge 1 commit intoeslint:mainfrom
sethamus:sort-keys-autofix
Open

feat: implement autofix for sort-keys#216
sethamus wants to merge 1 commit intoeslint:mainfrom
sethamus:sort-keys-autofix

Conversation

@sethamus
Copy link
Contributor

Prerequisites checklist

AI acknowledgment

  • I did not use AI to generate this PR.
  • (If the above is not checked) I have reviewed the AI-generated content before submitting.

What is the purpose of this pull request?

This PR adds autofix support to sort-keys so eslint can automatically reorder object keys, while avoiding fixes that could detach/misplace comments.

What changes did you make? (Give an overview)

  • Marked sort-keys as fixable and implemented a fixer that swaps out-of-order adjacent members.
  • Updated/added tests to assert autofix output across existing invalid cases

Related Issues

Fixes #122

Is there anything you'd like reviewers to focus on?


return {
Object(node) {
const hasUnsafeComments =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable hasUnsafeComments should be moved inside the fix as it is only needed then and it should be specific to the members being swapped.
In the following example it is safe to swap "b" and "c":

{
  // Comment for a
  "a": true,
  "c": false,
  "b": false
}.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this case as well, but reliably detecting only safe cases like this requires non-trivial comment association logic, and it’s easy to get wrong. So I’m not sure it’s worth adding that complexity.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use sourceCode.getTokenBefore/After with includeComments: true for each property and then do not fix if one of the four tokens is a comment (for getTokenAfter make sure that you skip commas with a filter):

const commentTypes = new Set(['LineComment', 'BlockComment']);

function hasComment(member, sourceCode) {
	const before = sourceCode.getTokenBefore(member, { includeComments: true });
	const after = sourceCode.getTokenAfter(member, { includeComments: true, filter: ({ type }) => type === ',');
	
	return commentTypes.has(before.type) || commentTypes.has(after.type);
}

for (const member of node.members) {
const thisName = getKey(member);
const thisRawName = getRawKey(member, sourceCode);
const prevMemberNode = prevMember;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This alias (prevMemberNode = prevMember) is unnecessary as fixes are eagerly executed (you can replace the references of prevMemberNode with just prevMember).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That alias is intentional. Without it, ESLint reports a no-loop-func error (Function declared in a loop contains unsafe references to variable(s) 'prevMember')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh okay, personally I would prefer an eslint-ignore as this is a workaround which trips up developers reading the code.
I don't feel strongly either way but can you please add a comment explaining why the alias exists?

@lumirlumir lumirlumir moved this from Needs Triage to Implementing in Triage Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Implementing

Development

Successfully merging this pull request may close these issues.

Rule Change: make sort-keys rule fixable

3 participants