mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
3c31bfff65
In preparation for a linting rule, use consistent quotation for properties in objects. PR-URL: https://github.com/nodejs/node/pull/19156 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Teddy Katz <teddy.katz@gmail.com> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Roman Reiss <me@silverwind.io>
131 lines
3.6 KiB
JavaScript
131 lines
3.6 KiB
JavaScript
/**
|
|
* @fileoverview Look for unescaped "literal" dots in regular expressions
|
|
* @author Brian White
|
|
*/
|
|
'use strict';
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
module.exports = function(context) {
|
|
const sourceCode = context.getSourceCode();
|
|
const regexpStack = [];
|
|
var regexpBuffer = [];
|
|
var 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'
|
|
});
|
|
}
|
|
|
|
const allowedModifiers = ['+', '*', '?', '{'];
|
|
function checkRegExp(nodes) {
|
|
var escaping = false;
|
|
var inCharClass = false;
|
|
for (var n = 0; n < nodes.length; ++n) {
|
|
const pair = nodes[n];
|
|
const node = pair[0];
|
|
const str = pair[1];
|
|
for (var 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);
|
|
}
|
|
} else {
|
|
escaping = false;
|
|
}
|
|
break;
|
|
default:
|
|
if (escaping)
|
|
escaping = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRegExpStart(node) {
|
|
if (node.callee && node.callee.name === 'RegExp') {
|
|
if (inRegExp) {
|
|
regexpStack.push(regexpBuffer);
|
|
regexpBuffer = [];
|
|
}
|
|
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 checkLiteral(node) {
|
|
const isTemplate = (node.type === 'TemplateLiteral' && node.quasis &&
|
|
node.quasis.length);
|
|
if (inRegExp &&
|
|
(isTemplate || (typeof node.value === 'string' && node.value.length))) {
|
|
var 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 (var 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 if (node.regex) {
|
|
checkRegExp([[node, node.regex.pattern]]);
|
|
}
|
|
}
|
|
|
|
return {
|
|
'TemplateLiteral': checkLiteral,
|
|
'Literal': checkLiteral,
|
|
'CallExpression': checkRegExpStart,
|
|
'NewExpression': checkRegExpStart,
|
|
'CallExpression:exit': checkRegExpEnd,
|
|
'NewExpression:exit': checkRegExpEnd
|
|
};
|
|
};
|