Repository: ota-meshi/eslint-plugin-regexp
Pull request #248 (2021-06-13 19:12:54)

Changes `regexp/strict` to suggest octal fixes
While testing the rule on Prism, I found that it auto-fixes octal escapes. This can be a problem because they might be incorrectly used backreferences. `regexp/no-octal` also only suggests for this reason.

This changes the `regexp/strict` rule to only suggest octal escape fixes.


Patch:
diff --git a/lib/rules/strict.ts b/lib/rules/strict.ts
index 0e7cc4c..5656ecd 100644
--- a/lib/rules/strict.ts
+++ b/lib/rules/strict.ts
@@ -67,6 +67,10 @@ export default createRule("strict", {
 
             // validator
             regexMessage: "{{message}}.",
+
+            // suggestions
+            hexEscapeSuggestion:
+                "Replace the octal escape with a hexadecimal escape.",
         },
         type: "suggestion",
     },
@@ -97,19 +101,36 @@ export default createRule("strict", {
             function report(
                 messageId: string,
                 element: Element,
-                fix?: string | null,
+                fix?: string | null | { fix: string; messageId: string },
             ): void {
                 reported = true
 
-                context.report({
-                    node,
-                    loc: getRegexpLocation(element),
-                    messageId,
-                    data: {
-                        expr: element.raw,
-                    },
-                    fix: fix ? fixReplaceNode(element, fix) : null,
-                })
+                if (fix && typeof fix === "object") {
+                    context.report({
+                        node,
+                        loc: getRegexpLocation(element),
+                        messageId,
+                        data: {
+                            expr: element.raw,
+                        },
+                        suggest: [
+                            {
+                                messageId: fix.messageId,
+                                fix: fixReplaceNode(element, fix.fix),
+                            },
+                        ],
+                    })
+                } else {
+                    context.report({
+                        node,
+                        loc: getRegexpLocation(element),
+                        messageId,
+                        data: {
+                            expr: element.raw,
+                        },
+                        fix: fix ? fixReplaceNode(element, fix) : null,
+                    })
+                }
             }
 
             return {
@@ -131,12 +152,16 @@ export default createRule("strict", {
                         return
                     }
                     if (cNode.value !== 0 && isOctalEscape(cNode.raw)) {
-                        // e.g. \023
-                        report(
-                            "octalEscape",
-                            cNode,
-                            `\\x${cNode.value.toString(16).padStart(2, "0")}`,
-                        )
+                        // e.g. \023, \34
+
+                        // this could be confused with a backreference
+                        // use a suggestion instead of a fix
+                        report("octalEscape", cNode, {
+                            fix: `\\x${cNode.value
+                                .toString(16)
+                                .padStart(2, "0")}`,
+                            messageId: "hexEscapeSuggestion",
+                        })
                         return
                     }
 


Test patch:
diff --git a/tests/lib/rules/strict.ts b/tests/lib/rules/strict.ts
index aea2f7a..861dcbe 100644
--- a/tests/lib/rules/strict.ts
+++ b/tests/lib/rules/strict.ts
@@ -133,12 +133,37 @@ tester.run("strict", rule as any, {
         },
         {
             code: "/\\012/",
-            output: "/\\x0a/",
+            output: null,
             errors: [
                 {
                     message:
                         "Invalid legacy octal escape sequence '\\012'. Use a hexadecimal escape instead.",
                     column: 2,
+                    suggestions: [
+                        {
+                            output: "/\\x0a/",
+                            desc:
+                                "Replace the octal escape with a hexadecimal escape.",
+                        },
+                    ],
+                },
+            ],
+        },
+        {
+            code: "/\\12/",
+            output: null,
+            errors: [
+                {
+                    message:
+                        "Invalid legacy octal escape sequence '\\12'. Use a hexadecimal escape instead.",
+                    column: 2,
+                    suggestions: [
+                        {
+                            output: "/\\x0a/",
+                            desc:
+                                "Replace the octal escape with a hexadecimal escape.",
+                        },
+                    ],
                 },
             ],
         },