mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.1 KiB
162 lines
4.1 KiB
/**
|
|
* @fileoverview Look for useless escapes in strings and regexes
|
|
* @author Onur Temizkan
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
const VALID_STRING_ESCAPES = [
|
|
"\\",
|
|
"n",
|
|
"r",
|
|
"v",
|
|
"t",
|
|
"b",
|
|
"f",
|
|
"u",
|
|
"x",
|
|
"\n",
|
|
"\r"
|
|
];
|
|
|
|
const VALID_REGEX_ESCAPES = [
|
|
"\\",
|
|
".",
|
|
"-",
|
|
"^",
|
|
"$",
|
|
"*",
|
|
"+",
|
|
"?",
|
|
"{",
|
|
"}",
|
|
"[",
|
|
"]",
|
|
"|",
|
|
"(",
|
|
")",
|
|
"b",
|
|
"B",
|
|
"c",
|
|
"d",
|
|
"D",
|
|
"f",
|
|
"n",
|
|
"r",
|
|
"s",
|
|
"S",
|
|
"t",
|
|
"v",
|
|
"w",
|
|
"W",
|
|
"x",
|
|
"u"
|
|
];
|
|
|
|
module.exports = {
|
|
meta: {
|
|
docs: {
|
|
description: "disallow unnecessary escape characters",
|
|
category: "Best Practices",
|
|
recommended: false
|
|
},
|
|
|
|
schema: []
|
|
},
|
|
|
|
create(context) {
|
|
|
|
/**
|
|
* Checks if the escape character in given slice is unnecessary.
|
|
*
|
|
* @private
|
|
* @param {string[]} escapes - list of valid escapes
|
|
* @param {ASTNode} node - node to validate.
|
|
* @param {string} match - string slice to validate.
|
|
* @returns {void}
|
|
*/
|
|
function validate(escapes, node, match) {
|
|
const isTemplateElement = node.type === "TemplateElement";
|
|
const escapedChar = match[0][1];
|
|
let isUnnecessaryEscape = escapes.indexOf(escapedChar) === -1;
|
|
let isQuoteEscape;
|
|
|
|
if (isTemplateElement) {
|
|
isQuoteEscape = escapedChar === "`";
|
|
|
|
if (escapedChar === "$") {
|
|
|
|
// Warn if `\$` is not followed by `{`
|
|
isUnnecessaryEscape = match.input[match.index + 2] !== "{";
|
|
} else if (escapedChar === "{") {
|
|
|
|
/* Warn if `\{` is not preceded by `$`. If preceded by `$`, escaping
|
|
* is necessary and the rule should not warn. If preceded by `/$`, the rule
|
|
* will warn for the `/$` instead, as it is the first unnecessarily escaped character.
|
|
*/
|
|
isUnnecessaryEscape = match.input[match.index - 1] !== "$";
|
|
}
|
|
} else {
|
|
isQuoteEscape = escapedChar === node.raw[0];
|
|
}
|
|
|
|
if (isUnnecessaryEscape && !isQuoteEscape) {
|
|
context.report({
|
|
node,
|
|
loc: {
|
|
line: node.loc.start.line,
|
|
column: node.loc.start.column + match.index
|
|
},
|
|
message: "Unnecessary escape character: {{character}}.",
|
|
data: {
|
|
character: match[0]
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if a node has an escape.
|
|
*
|
|
* @param {ASTNode} node - node to check.
|
|
* @returns {void}
|
|
*/
|
|
function check(node) {
|
|
const isTemplateElement = node.type === "TemplateElement";
|
|
const value = isTemplateElement ? node.value.raw : node.raw;
|
|
const pattern = /\\[^\d]/g;
|
|
let nodeEscapes,
|
|
match;
|
|
|
|
if (typeof node.value === "string" || isTemplateElement) {
|
|
|
|
/*
|
|
* JSXAttribute doesn't have any escape sequence: https://facebook.github.io/jsx/.
|
|
* In addition, backticks are not supported by JSX yet: https://github.com/facebook/jsx/issues/25.
|
|
*/
|
|
if (node.parent.type === "JSXAttribute") {
|
|
return;
|
|
}
|
|
|
|
nodeEscapes = VALID_STRING_ESCAPES;
|
|
} else if (node.regex) {
|
|
nodeEscapes = VALID_REGEX_ESCAPES;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
while ((match = pattern.exec(value))) {
|
|
validate(nodeEscapes, node, match);
|
|
}
|
|
}
|
|
|
|
return {
|
|
Literal: check,
|
|
TemplateElement: check
|
|
};
|
|
}
|
|
};
|
|
|