diff options
author | Rich Trott <rtrott@gmail.com> | 2015-10-01 21:38:16 -0700 |
---|---|---|
committer | Rich Trott <rtrott@gmail.com> | 2015-10-06 15:11:58 -0700 |
commit | 3de353b5544ec5863dc4e1291cdf1aed01b50358 (patch) | |
tree | 7998c70ed474ce800b479314f86bcad32d4264a8 /tools/eslint-rules | |
parent | c78091d689d0d4d56b3231b9050d52ca69ecb449 (diff) | |
download | android-node-v8-3de353b5544ec5863dc4e1291cdf1aed01b50358.tar.gz android-node-v8-3de353b5544ec5863dc4e1291cdf1aed01b50358.tar.bz2 android-node-v8-3de353b5544ec5863dc4e1291cdf1aed01b50358.zip |
test: make common.js mandatory via linting rule
test/common.js contains code that detects global variable leaks.
This eslint rule checks that a module named `common` is loaded. It is
only applicable to files in the test directory. Tests that intentionally
leak variables can opt out with an eslint-disable comment.
PR-URL: https://github.com/nodejs/node/pull/3157
Reviewed-By: Rod Vagg <rod@vagg.org>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'tools/eslint-rules')
-rw-r--r-- | tools/eslint-rules/required-modules.js | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/tools/eslint-rules/required-modules.js b/tools/eslint-rules/required-modules.js new file mode 100644 index 0000000000..647726bf9a --- /dev/null +++ b/tools/eslint-rules/required-modules.js @@ -0,0 +1,104 @@ +/** + * @fileoverview Require usage of specified node modules. + * @author Rich Trott + */ +'use strict'; + +var path = require('path'); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + // trim required module names + var requiredModules = context.options; + + var foundModules = []; + + // if no modules are required we don't need to check the CallExpressions + if (requiredModules.length === 0) { + return {}; + } + + /** + * Function to check if a node is a string literal. + * @param {ASTNode} node The node to check. + * @returns {boolean} If the node is a string literal. + */ + function isString(node) { + return node && node.type === 'Literal' && typeof node.value === 'string'; + } + + /** + * Function to check if a node is a require call. + * @param {ASTNode} node The node to check. + * @returns {boolean} If the node is a require call. + */ + function isRequireCall(node) { + return node.callee.type === 'Identifier' && node.callee.name === 'require'; + } + + /** + * Function to check if a node has an argument that is a required module and + * return its name. + * @param {ASTNode} node The node to check + * @returns {undefined|String} required module name or undefined + */ + function getRequiredModuleName(node) { + var moduleName; + + // node has arguments and first argument is string + if (node.arguments.length && isString(node.arguments[0])) { + var argValue = path.basename(node.arguments[0].value.trim()); + + // check if value is in required modules array + if (requiredModules.indexOf(argValue) !== -1) { + moduleName = argValue; + } + } + + return moduleName; + } + + return { + 'CallExpression': function(node) { + if (isRequireCall(node)) { + var requiredModuleName = getRequiredModuleName(node); + + if (requiredModuleName) { + foundModules.push(requiredModuleName); + } + } + }, + 'Program:exit': function(node) { + if (foundModules.length < requiredModules.length) { + var missingModules = requiredModules.filter( + function(module) { + return foundModules.indexOf(module === -1); + } + ); + missingModules.forEach(function(moduleName) { + context.report( + node, + 'Mandatory module "{{moduleName}}" must be loaded.', + { moduleName: moduleName } + ); + }); + } + } + }; +}; + +module.exports.schema = { + 'type': 'array', + 'items': [ + { + 'enum': [0, 1, 2] + } + ], + 'additionalItems': { + 'type': 'string' + }, + 'uniqueItems': true +}; |