Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: eslint rule making common.js mandatory #3157

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions test/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ rules:
no-undef: 0
## allow global Buffer usage
require-buffer: 0
## common module is mandatory in tests
required-modules: [2, "common"]

globals:
gc: false
1 change: 1 addition & 0 deletions test/addons/async-hello-world/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../../common');
var assert = require('assert');
var binding = require('./build/Release/binding');
var called = false;
Expand Down
1 change: 1 addition & 0 deletions test/addons/at-exit/test.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
'use strict';
require('../../common');
var binding = require('./build/Release/binding');
2 changes: 2 additions & 0 deletions test/addons/heap-profiler/test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

require('../../common');

const binding = require('./build/Release/binding');

// Create an AsyncWrap object.
Expand Down
1 change: 1 addition & 0 deletions test/addons/hello-world-function-export/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../../common');
var assert = require('assert');
var binding = require('./build/Release/binding');
assert.equal('world', binding());
Expand Down
1 change: 1 addition & 0 deletions test/addons/hello-world/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../../common');
var assert = require('assert');
var binding = require('./build/Release/binding');
assert.equal('world', binding.hello());
Expand Down
1 change: 1 addition & 0 deletions test/addons/repl-domain-abort/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../../common');
var assert = require('assert');
var repl = require('repl');
var stream = require('stream');
Expand Down
1 change: 1 addition & 0 deletions test/common.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable required-modules */
'use strict';
var path = require('path');
var fs = require('fs');
Expand Down
1 change: 1 addition & 0 deletions test/debugger/test-debugger-repl-break-in-module.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../common');
var repl = require('./helper-debugger-repl.js');

repl.startDebugger('break-in-module/main.js');
Expand Down
1 change: 1 addition & 0 deletions test/debugger/test-debugger-repl-restart.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../common');
var repl = require('./helper-debugger-repl.js');

repl.startDebugger('breakpoints.js');
Expand Down
1 change: 1 addition & 0 deletions test/debugger/test-debugger-repl-term.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../common');
process.env.NODE_FORCE_READLINE = 1;

var repl = require('./helper-debugger-repl.js');
Expand Down
1 change: 1 addition & 0 deletions test/debugger/test-debugger-repl.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
require('../common');
var repl = require('./helper-debugger-repl.js');

repl.startDebugger('breakpoints.js');
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-domain-crypto.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable strict */
/* eslint-disable strict, required-modules */
try {
var crypto = require('crypto');
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-regression-object-prototype.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable required-modules */
'use strict';
//console.log('puts before');

Object.prototype.xadsadsdasasdxx = function() {
};
Expand Down
1 change: 1 addition & 0 deletions test/parallel/test-repl-autolibs.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable required-modules */
'use strict';
var assert = require('assert');
var util = require('util');
Expand Down
104 changes: 104 additions & 0 deletions tools/eslint-rules/required-modules.js
Original file line number Diff line number Diff line change
@@ -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
};