Skip to content

Commit

Permalink
feat: report duplicate allowed flags in no-invalid-regexp (#18754)
Browse files Browse the repository at this point in the history
* fix: duplicate allowed flags

* apply suggestions

* fix: error message

* keep duplicate flags in error message

* apply suggestion
  • Loading branch information
Tanujkanti4441 authored Aug 31, 2024
1 parent a20c870 commit c69b406
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 18 deletions.
47 changes: 29 additions & 18 deletions lib/rules/no-invalid-regexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator;
const validator = new RegExpValidator();
const validFlags = /[dgimsuvy]/gu;
const validFlags = "dgimsuvy";
const undefined1 = void 0;

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -49,13 +49,13 @@ module.exports = {
create(context) {

const options = context.options[0];
let allowedFlags = null;
let allowedFlags = [];

if (options && options.allowConstructorFlags) {
const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
const temp = options.allowConstructorFlags.join("").replace(new RegExp(`[${validFlags}]`, "gu"), "");

if (temp) {
allowedFlags = new RegExp(`[${temp}]`, "gu");
allowedFlags = [...new Set(temp)];
}
}

Expand Down Expand Up @@ -125,27 +125,34 @@ module.exports = {
/**
* Check syntax error in a given flags.
* @param {string|null} flags The RegExp flags to validate.
* @param {string|null} flagsToCheck The RegExp invalid flags.
* @returns {string|null} The syntax error.
*/
function validateRegExpFlags(flags) {
if (!flags) {
return null;
}
try {
validator.validateFlags(flags);
} catch {
return `Invalid flags supplied to RegExp constructor '${flags}'`;
function validateRegExpFlags(flags, flagsToCheck) {
const flagsToReport = [];

if (typeof flags === "string") {
for (const flag of flags) {
if (flagsToCheck.includes(flag)) {
flagsToReport.push(flag);
}
}
}

/*
* `regexpp` checks the combination of `u` and `v` flags when parsing `Pattern` according to `ecma262`,
* but this rule may check only the flag when the pattern is unidentifiable, so check it here.
* https://tc39.es/ecma262/multipage/text-processing.html#sec-parsepattern
*/
if (flags.includes("u") && flags.includes("v")) {
if (flags && flags.includes("u") && flags.includes("v")) {
return "Regex 'u' and 'v' flags cannot be used together";
}
return null;

if (!flagsToCheck) {
return null;
}

return `Invalid flags supplied to RegExp constructor '${flagsToReport.join("")}'`;
}

return {
Expand All @@ -154,13 +161,17 @@ module.exports = {
return;
}

let flags = getFlags(node);
const flags = getFlags(node);
let flagsToCheck = flags;
const allFlags = allowedFlags.length > 0 ? validFlags.split("").concat(allowedFlags) : validFlags.split("");

if (flags && allowedFlags) {
flags = flags.replace(allowedFlags, "");
if (flags) {
allFlags.forEach(flag => {
flagsToCheck = flagsToCheck.replace(flag, "");
});
}

let message = validateRegExpFlags(flags);
let message = validateRegExpFlags(flags, flagsToCheck);

if (message) {
report(node, message);
Expand Down
63 changes: 63 additions & 0 deletions tests/lib/rules/no-invalid-regexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,69 @@ ruleTester.run("no-invalid-regexp", rule, {
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'aa');",
options: [{ allowConstructorFlags: ["a"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'aa'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'aa');",
options: [{ allowConstructorFlags: ["a", "a"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'aa'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'aA');",
options: [{ allowConstructorFlags: ["a"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'A'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'aaz');",
options: [{ allowConstructorFlags: ["a", "z"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'aa'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'azz');",
options: [{ allowConstructorFlags: ["a", "z"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'zz'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'aga');",
options: [{ allowConstructorFlags: ["a"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'aa'" },
type: "NewExpression"
}]
},
{
code: "new RegExp('.', 'uu');",
options: [{ allowConstructorFlags: ["u"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'uu'" },
type: "NewExpression"
}]
},
{
code: "new RegExp(')');",
errors: [{
Expand Down

0 comments on commit c69b406

Please sign in to comment.