summaryrefslogtreecommitdiff
path: root/tools/eslint-rules
diff options
context:
space:
mode:
authorGus Caplan <me@gus.host>2018-07-07 23:32:23 -0500
committerGus Caplan <me@gus.host>2018-07-12 16:11:11 -0500
commit8cae9b2ff808198b4451d9de634320fa5750c4cd (patch)
tree40b8264e77fefec5a9dba3c0d646483b8260cf3a /tools/eslint-rules
parent1849a2b2e98c093e27d781bd5040f76a22e8f977 (diff)
downloadnode-new-8cae9b2ff808198b4451d9de634320fa5750c4cd.tar.gz
tools: add no-duplicate-requires rule
PR-URL: https://github.com/nodejs/node/pull/21712 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Weijia Wang <starkwang@126.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jon Moss <me@jonathanmoss.me>
Diffstat (limited to 'tools/eslint-rules')
-rw-r--r--tools/eslint-rules/no-duplicate-requires.js70
1 files changed, 70 insertions, 0 deletions
diff --git a/tools/eslint-rules/no-duplicate-requires.js b/tools/eslint-rules/no-duplicate-requires.js
new file mode 100644
index 0000000000..595c223601
--- /dev/null
+++ b/tools/eslint-rules/no-duplicate-requires.js
@@ -0,0 +1,70 @@
+/**
+ * @fileoverview Ensure modules are not required twice at top level of a module
+ * @author devsnek
+ */
+'use strict';
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+
+function isString(node) {
+ return node && node.type === 'Literal' && typeof node.value === 'string';
+}
+
+function isRequireCall(node) {
+ return node.callee.type === 'Identifier' && node.callee.name === 'require';
+}
+
+function isTopLevel(node) {
+ do {
+ if (node.type === 'FunctionDeclaration' ||
+ node.type === 'FunctionExpression' ||
+ node.type === 'ArrowFunctionExpression' ||
+ node.type === 'ClassBody' ||
+ node.type === 'MethodDefinition') {
+ return false;
+ }
+ } while (node = node.parent);
+ return true;
+}
+
+module.exports = (context) => {
+ if (context.parserOptions.sourceType === 'module') {
+ return {};
+ }
+
+ function getRequiredModuleNameFromCall(node) {
+ // node has arguments and first argument is string
+ if (node.arguments.length && isString(node.arguments[0])) {
+ return node.arguments[0].value.trim();
+ }
+
+ return undefined;
+ }
+
+ const required = new Set();
+
+ const rules = {
+ CallExpression: (node) => {
+ if (isRequireCall(node) && isTopLevel(node)) {
+ const moduleName = getRequiredModuleNameFromCall(node);
+ if (moduleName === undefined) {
+ return;
+ }
+ if (required.has(moduleName)) {
+ context.report(
+ node,
+ '\'{{moduleName}}\' require is duplicated.',
+ { moduleName }
+ );
+ } else {
+ required.add(moduleName);
+ }
+ }
+ },
+ };
+
+ return rules;
+};