2 * @fileoverview Rule to forbid control characters from regular expressions.
3 * @author Nicholas C. Zakas
8 const RegExpValidator = require("regexpp").RegExpValidator;
9 const collector = new (class {
12 this._controlChars = [];
13 this._validator = new RegExpValidator(this);
17 this._controlChars = [];
20 onCharacter(start, end, cp) {
24 this._source.codePointAt(start) === cp ||
25 this._source.slice(start, end).startsWith("\\x") ||
26 this._source.slice(start, end).startsWith("\\u")
29 this._controlChars.push(`\\x${`0${cp.toString(16)}`.slice(-2)}`);
33 collectControlChars(regexpStr) {
35 this._source = regexpStr;
36 this._validator.validatePattern(regexpStr); // Call onCharacter hook
39 // Ignore syntax errors in RegExp.
41 return this._controlChars;
45 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
54 description: "disallow control characters in regular expressions",
55 category: "Possible Errors",
57 url: "https://eslint.org/docs/rules/no-control-regex"
63 unexpected: "Unexpected control character(s) in regular expression: {{controlChars}}."
70 * Get the regex expression
71 * @param {ASTNode} node node to evaluate
72 * @returns {RegExp|null} Regex if found else null
75 function getRegExpPattern(node) {
77 return node.regex.pattern;
79 if (typeof node.value === "string" &&
80 (node.parent.type === "NewExpression" || node.parent.type === "CallExpression") &&
81 node.parent.callee.type === "Identifier" &&
82 node.parent.callee.name === "RegExp" &&
83 node.parent.arguments[0] === node
93 const pattern = getRegExpPattern(node);
96 const controlCharacters = collector.collectControlChars(pattern);
98 if (controlCharacters.length > 0) {
101 messageId: "unexpected",
103 controlChars: controlCharacters.join(", ")