Repository: eslint/eslint
File: lib/rules/require-unicode-regexp.js (JavaScript)

Code before:

                for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
                    const flagsNode = node.arguments[1];
                    const flags = getStringIfConstant(flagsNode, scope);

                    if (!flagsNode || (typeof flags === "string" && !flags.includes("u"))) {
                        context.report({
                            messageId: "requireUFlag",
                            node,
                            suggest: [
                                {
                                    fix(fixer) {
                                        if (flagsNode) {
                                            if (flagsNode.type === "Literal") {
                                                const flagsNodeText = sourceCode.getText(flagsNode);

                                                return fixer.replaceText(flagsNode, [
                                                    flagsNodeText.slice(0, flagsNodeText.length - 1),
                                                    flagsNodeText.slice(flagsNodeText.length - 1)
                                                ].join("u"));
                                            }

                                            return fixer.insertTextAfter(node.arguments[1], " + \"u\"");
                                        }

                                        return fixer.insertTextAfter(node.arguments[0], ", \"u\"");

                                    },
                                    messageId: "addUFlag"
                                }
                            ]
                        });
                    }
                }
            }
        };
    }
};


Review comment (bug):
An edge case where this fix would be incorrect:

```js
RegExp(("foo"));
```

After the suggestion is applied:

```js
RegExp(("foo", "u"));
```

This is how it's handled in `no-misleading-character-class`:

https://github.com/eslint/eslint/blob/1fbf1184fed57df02640aad4659afb54dc26a2e9/lib/rules/no-misleading-character-class.js#L249-L258

Code after:
            Program(node) {
                const scope = sourceCode.getScope(node);
                const tracker = new ReferenceTracker(scope);
                const trackMap = {
                    RegExp: { [CALL]: true, [CONSTRUCT]: true }
                };

                for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) {
                    const [patternNode, flagsNode] = refNode.arguments;
                    const pattern = getStringIfConstant(patternNode, scope);
                    const flags = getStringIfConstant(flagsNode, scope);

                    if (!flagsNode || (typeof flags === "string" && !flags.includes("u"))) {
                        context.report({
                            messageId: "requireUFlag",
                            node: refNode,
                            suggest: typeof pattern === "string" && isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern)
                                ? [
                                    {
                                        fix(fixer) {
                                            if (flagsNode) {
                                                if ((flagsNode.type === "Literal" && typeof flagsNode.value === "string") || flagsNode.type === "TemplateLiteral") {
                                                    const flagsNodeText = sourceCode.getText(flagsNode);

                                                    return fixer.replaceText(flagsNode, [
                                                        flagsNodeText.slice(0, flagsNodeText.length - 1),
                                                        flagsNodeText.slice(flagsNodeText.length - 1)
                                                    ].join("u"));
                                                }

                                                // We intentionally don't suggest concatenating + "u" to non-literals
                                                return null;
                                            }

                                            const penultimateToken = sourceCode.getLastToken(refNode, { skip: 1 }); // skip closing parenthesis

                                            return fixer.insertTextAfter(
                                                penultimateToken,
                                                astUtils.isCommaToken(penultimateToken)
                                                    ? ' "u",'
                                                    : ', "u"'
                                            );
                                        },
                                        messageId: "addUFlag"
                                    }
                                ]
                                : null
                        });
                    }
                }
            }