Skip to content

Commit

Permalink
tools: refactor deprecated format in no-unescaped-regexp-dot
Browse files Browse the repository at this point in the history
PR-URL: nodejs/node#44763
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
  • Loading branch information
sonimadhuri authored and guangwong committed Jan 3, 2023
1 parent 5cbb6a8 commit 6ec5ef6
Showing 1 changed file with 98 additions and 95 deletions.
193 changes: 98 additions & 95 deletions tools/eslint-rules/no-unescaped-regexp-dot.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,123 +8,126 @@
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {
const sourceCode = context.getSourceCode();
const regexpStack = [];
let regexpBuffer = [];
let inRegExp = false;
module.exports = {
create(context) {
const sourceCode = context.getSourceCode();
const regexpStack = [];
let regexpBuffer = [];
let inRegExp = false;

function report(node, startOffset) {
const indexOfDot = sourceCode.getIndexFromLoc(node.loc.start) + startOffset;
context.report({
node,
loc: sourceCode.getLocFromIndex(indexOfDot),
message: 'Unescaped dot character in regular expression'
});
}
function report(node, startOffset) {
const indexOfDot = sourceCode.getIndexFromLoc(node.loc.start) + startOffset;
context.report({
node,
loc: sourceCode.getLocFromIndex(indexOfDot),
message: 'Unescaped dot character in regular expression'
});
}
const allowedModifiers = ['+', '*', '?', '{'];

const allowedModifiers = ['+', '*', '?', '{'];
function checkRegExp(nodes) {
let escaping = false;
let inCharClass = false;
for (let n = 0; n < nodes.length; ++n) {
const pair = nodes[n];
const node = pair[0];
const str = pair[1];
for (let i = 0; i < str.length; ++i) {
switch (str[i]) {
case '[':
if (!escaping)
inCharClass = true;
else
escaping = false;
break;
case ']':
if (!escaping) {
if (inCharClass)
inCharClass = false;
} else {
escaping = false;
}
break;
case '\\':
escaping = !escaping;
break;
case '.':
if (!escaping) {
if (!inCharClass &&
function checkRegExp(nodes) {
let escaping = false;
let inCharClass = false;
for (let n = 0; n < nodes.length; ++n) {
const pair = nodes[n];
const node = pair[0];
const str = pair[1];
for (let i = 0; i < str.length; ++i) {
switch (str[i]) {
case '[':
if (!escaping)
inCharClass = true;
else
escaping = false;
break;
case ']':
if (!escaping) {
if (inCharClass)
inCharClass = false;
} else {
escaping = false;
}
break;
case '\\':
escaping = !escaping;
break;
case '.':
if (!escaping) {
if (!inCharClass &&
((i + 1) === str.length ||
allowedModifiers.indexOf(str[i + 1]) === -1)) {
report(node, i);
report(node, i);
}
} else {
escaping = false;
}
} else {
escaping = false;
}
break;
default:
if (escaping)
escaping = false;
break;
default:
if (escaping)
escaping = false;
}
}
}
}
}

function checkRegExpStart(node) {
if (node.callee && node.callee.name === 'RegExp') {
if (inRegExp) {
regexpStack.push(regexpBuffer);
regexpBuffer = [];
function checkRegExpStart(node) {
if (node.callee && node.callee.name === 'RegExp') {
if (inRegExp) {
regexpStack.push(regexpBuffer);
regexpBuffer = [];
}
inRegExp = true;
}
inRegExp = true;
}
}

function checkRegExpEnd(node) {
if (node.callee && node.callee.name === 'RegExp') {
checkRegExp(regexpBuffer);
if (regexpStack.length) {
regexpBuffer = regexpStack.pop();
} else {
inRegExp = false;
regexpBuffer = [];
function checkRegExpEnd(node) {
if (node.callee && node.callee.name === 'RegExp') {
checkRegExp(regexpBuffer);
if (regexpStack.length) {
regexpBuffer = regexpStack.pop();
} else {
inRegExp = false;
regexpBuffer = [];
}
}
}
}

function checkLiteral(node) {
const isTemplate = (node.type === 'TemplateLiteral' && node.quasis &&
function checkLiteral(node) {
const isTemplate = (node.type === 'TemplateLiteral' && node.quasis &&
node.quasis.length);
if (inRegExp &&
if (inRegExp &&
(isTemplate || (typeof node.value === 'string' && node.value.length))) {
let p = node.parent;
while (p && p.type === 'BinaryExpression') {
p = p.parent;
}
if (p && (p.type === 'NewExpression' || p.type === 'CallExpression') &&
let p = node.parent;
while (p && p.type === 'BinaryExpression') {
p = p.parent;
}
if (p && (p.type === 'NewExpression' || p.type === 'CallExpression') &&
p.callee && p.callee.type === 'Identifier' &&
p.callee.name === 'RegExp') {
if (isTemplate) {
const quasis = node.quasis;
for (let i = 0; i < quasis.length; ++i) {
const el = quasis[i];
if (el.type === 'TemplateElement' && el.value && el.value.cooked)
regexpBuffer.push([el, el.value.cooked]);
if (isTemplate) {
const quasis = node.quasis;
for (let i = 0; i < quasis.length; ++i) {
const el = quasis[i];
if (el.type === 'TemplateElement' && el.value && el.value.cooked)
regexpBuffer.push([el, el.value.cooked]);
}
} else {
regexpBuffer.push([node, node.value]);
}
} else {
regexpBuffer.push([node, node.value]);
}
} else if (node.regex) {
checkRegExp([[node, node.regex.pattern]]);
}
} else if (node.regex) {
checkRegExp([[node, node.regex.pattern]]);
}
}

return {
'TemplateLiteral': checkLiteral,
'Literal': checkLiteral,
'CallExpression': checkRegExpStart,
'NewExpression': checkRegExpStart,
'CallExpression:exit': checkRegExpEnd,
'NewExpression:exit': checkRegExpEnd
};

return {
'TemplateLiteral': checkLiteral,
'Literal': checkLiteral,
'CallExpression': checkRegExpStart,
'NewExpression': checkRegExpStart,
'CallExpression:exit': checkRegExpEnd,
'NewExpression:exit': checkRegExpEnd
};
}
};

0 comments on commit 6ec5ef6

Please sign in to comment.