Skip to content

feat: implement autofix for no-unnormalized-keys#151

Open
lumirlumir wants to merge 13 commits intomainfrom
feat-support-autofix-for-no-unnormalized-keys
Open

feat: implement autofix for no-unnormalized-keys#151
lumirlumir wants to merge 13 commits intomainfrom
feat-support-autofix-for-no-unnormalized-keys

Conversation

@lumirlumir
Copy link
Member

@lumirlumir lumirlumir commented Sep 20, 2025

Prerequisites checklist

What is the purpose of this pull request?

In this PR, I've implemented an autofix for no-unnormalized-keys.

This PR closes #141.

What changes did you make? (Give an overview)

In this PR, I've implemented an autofix for no-unnormalized-keys.

Related Issues

Closes: #141

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

N/A

@eslintbot eslintbot added this to Triage Sep 20, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in Triage Sep 20, 2025
@lumirlumir lumirlumir force-pushed the feat-support-autofix-for-no-unnormalized-keys branch from dccd118 to 42c637a Compare September 20, 2025 13:56
@lumirlumir lumirlumir force-pushed the feat-support-autofix-for-no-unnormalized-keys branch from 7177f2f to 78c0ce5 Compare September 20, 2025 14:10
@lumirlumir lumirlumir marked this pull request as ready for review September 20, 2025 14:34
@lumirlumir lumirlumir requested a review from a team September 20, 2025 14:34
@mdjermanovic mdjermanovic moved this from Needs Triage to Implementing in Triage Sep 22, 2025
@lumirlumir lumirlumir marked this pull request as draft September 24, 2025 06:25
@lumirlumir lumirlumir marked this pull request as ready for review October 15, 2025 10:53
nzakas
nzakas previously approved these changes Oct 21, 2025
Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

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

LGTM. Would like @mdjermanovic to review before merging.

@nzakas nzakas moved this from Implementing to Second Review Needed in Triage Oct 21, 2025
Comment on lines 73 to 80
fix(fixer) {
return fixer.replaceTextRange(
name.type === "String"
? [name.range[0] + 1, name.range[1] - 1]
: name.range,
normalizedKey,
);
},
Copy link
Member

Choose a reason for hiding this comment

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

This would produce incorrect fix if there are escape sequences, e.g., \n:

/* eslint json/no-unnormalized-keys: [2, { form: "NFD" }] */

{
    "\u1E9B\u0323\n": 42
}

Fixed to invalid JSON:

/* eslint json/no-unnormalized-keys: [2, { form: "NFD" }] */

{
    "ẛ̣
": 42
}

Also, I'm not sure if autofixing \u1E9B\u0323 to ẛ̣ instead of a sequence with \uXXXX would be desirable.

Copy link
Member Author

Choose a reason for hiding this comment

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

Your suggestion also makes sense to me, but if that's the case, I have two questions:

  1. Should data.key be updated accordingly?

    It seems data.key is displayed the same way:
    image

  2. Is there a JavaScript (or other) rule I can refer to?

    I don't have much experience with JSON (and JavaScript) rules, so I think I'm missing some edge cases while implementing the rule. Do you have any recommendations I could refer to when implementing the rule? If so, that would be very helpful.

Copy link
Member

Choose a reason for hiding this comment

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

  1. Should data.key be updated accordingly?

I think it would be better to show the raw key representation (i.e., as it appears in the linted source code) in the error message.

Copy link
Member

Choose a reason for hiding this comment

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

2. Is there a JavaScript (or other) rule I can refer to?

I think the most similar thing we have in JS rules is a utility that parses string literals:

https://github.com/eslint/eslint/blob/main/lib/rules/utils/char-source.js

So we could try making something similar for JSON and use it to check how individual characters were represented in the original key and then try preserving the same form (a character directly inserted into the source code or an escape sequence) in the fixed key. A problem that might be difficult to solve in this particular rule is how to map characters from the fixed key to characters in the original key since the normalizations produce strings with different lengths.

Another option is to limit the autofix to keys that don't have escape sequences only.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry for the delay. Your reference was very helpful, but because of the difficulty of handling edge cases, I've chosen a simpler approach: "Another option is to limit the autofix to keys that don't have escape sequences only".

I've addressed all suggestions here.

@lumirlumir lumirlumir marked this pull request as draft October 23, 2025 11:46
@lumirlumir lumirlumir marked this pull request as ready for review October 23, 2025 11:57
@lumirlumir lumirlumir marked this pull request as draft October 30, 2025 11:47
@lumirlumir lumirlumir marked this pull request as ready for review February 16, 2026 08:31
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements autofix functionality for the no-unnormalized-keys rule, which checks that JSON object keys are properly normalized according to Unicode normalization forms (NFC, NFD, NFKC, or NFKD). The implementation automatically fixes unnormalized keys by replacing them with their normalized equivalents, but intelligently skips autofix when escape sequences are present in the raw key to avoid breaking JSON syntax.

Changes:

  • Added fixable: "code" metadata and fix function to the no-unnormalized-keys rule
  • Modified error reporting to use raw key text for better clarity when escape sequences are present
  • Added comprehensive test coverage for autofix with different quote types and normalization forms, plus tests verifying no autofix occurs when escape sequences are present

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/rules/no-unnormalized-keys.js Implemented autofix logic with escape sequence detection, imported getRawKey utility, and updated error message to show raw keys
tests/rules/no-unnormalized-keys.test.js Added output expectations for fixable cases, new valid test cases for escaped forms, and invalid test cases verifying escape sequences prevent autofix

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Second Review Needed

Development

Successfully merging this pull request may close these issues.

Rule Change: Support auto-fix for no-unnormalized-keys

3 participants