Skip to content

Commit

Permalink
Update: no-restricted-modules handle TemplateLiteral (fixes #12926) (#…
Browse files Browse the repository at this point in the history
…12927)

* Update: no-restricted-modules handle TemplateLiteral (fixes #12926)

* add fixture using backslashes

* finally understood, I think
  • Loading branch information
pieh committed Feb 28, 2020
1 parent 051567a commit a5b41a7
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 19 deletions.
66 changes: 48 additions & 18 deletions lib/rules/no-restricted-modules.js
Expand Up @@ -106,10 +106,19 @@ module.exports = {
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a string literal.
*/
function isString(node) {
function isStringLiteral(node) {
return node && node.type === "Literal" && typeof node.value === "string";
}

/**
* Function to check if a node is a static string template literal.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a string template literal.
*/
function isStaticTemplateLiteral(node) {
return node && node.type === "TemplateLiteral" && node.expressions.length === 0;
}

/**
* Function to check if a node is a require call.
* @param {ASTNode} node The node to check.
Expand All @@ -119,14 +128,31 @@ module.exports = {
return node.callee.type === "Identifier" && node.callee.name === "require";
}

/**
* Extract string from Literal or TemplateLiteral node
* @param {ASTNode} node The node to extract from
* @returns {string|null} Extracted string or null if node doesn't represent a string
*/
function getFirstArgumentString(node) {
if (isStringLiteral(node)) {
return node.value.trim();
}

if (isStaticTemplateLiteral(node)) {
return node.quasis[0].value.cooked.trim();
}

return null;
}

/**
* Report a restricted path.
* @param {node} node representing the restricted path reference
* @param {string} name restricted path
* @returns {void}
* @private
*/
function reportPath(node) {
const name = node.arguments[0].value.trim();
function reportPath(node, name) {
const customMessage = restrictedPathMessages[name];
const messageId = customMessage
? "customMessage"
Expand Down Expand Up @@ -156,21 +182,25 @@ module.exports = {
CallExpression(node) {
if (isRequireCall(node)) {

// node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
const name = node.arguments[0].value.trim();

// check if argument value is in restricted modules array
if (isRestrictedPath(name)) {
reportPath(node);
}

if (restrictedPatterns.length > 0 && ig.ignores(name)) {
context.report({
node,
messageId: "patternMessage",
data: { name }
});
// node has arguments
if (node.arguments.length) {
const name = getFirstArgumentString(node.arguments[0]);

// if first argument is a string literal or a static string template literal
if (name) {

// check if argument value is in restricted modules array
if (isRestrictedPath(name)) {
reportPath(node, name);
}

if (restrictedPatterns.length > 0 && ig.ignores(name)) {
context.report({
node,
messageId: "patternMessage",
data: { name }
});
}
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion tests/lib/rules/no-restricted-modules.js
Expand Up @@ -30,7 +30,9 @@ ruleTester.run("no-restricted-modules", rule, {
{ code: "var withPaths = require(\"foo/bar\");", options: [{ paths: ["foo", "bar"] }] },
{ code: "var withPatterns = require(\"foo/bar\");", options: [{ patterns: ["foo/c*"] }] },
{ code: "var withPatternsAndPaths = require(\"foo/bar\");", options: [{ paths: ["foo"], patterns: ["foo/c*"] }] },
{ code: "var withGitignores = require(\"foo/bar\");", options: [{ paths: ["foo"], patterns: ["foo/*", "!foo/bar"] }] }
{ code: "var withGitignores = require(\"foo/bar\");", options: [{ paths: ["foo"], patterns: ["foo/*", "!foo/bar"] }] },
{ code: "require(`fs`)", options: ["crypto"], parserOptions: { ecmaVersion: 6 } },
{ code: "require(`foo${bar}`)", options: ["foo"], parserOptions: { ecmaVersion: 6 } }
],
invalid: [{
code: "require(\"fs\")",
Expand Down Expand Up @@ -99,5 +101,15 @@ ruleTester.run("no-restricted-modules", rule, {
data: { name: "foo", customMessage: "Please use 'bar' module instead." },
type: "CallExpression"
}]
}, {
code: "require(`fs`)",
options: ["fs"],
parserOptions: { ecmaVersion: 6 },
errors: [{ messageId: "defaultMessage", data: { name: "fs" }, type: "CallExpression" }]
}, {
code: "require(`crypt\\o`);",
options: ["crypto"],
parserOptions: { ecmaVersion: 6 },
errors: [{ messageId: "defaultMessage", data: { name: "crypto" }, type: "CallExpression" }]
}]
});

0 comments on commit a5b41a7

Please sign in to comment.