Custom rule to identify unused goog.require() calls
This commit is contained in:
+6
-1
@@ -35,6 +35,7 @@
|
|||||||
"browserify": "13.1.0",
|
"browserify": "13.1.0",
|
||||||
"closure-util": "1.15.0",
|
"closure-util": "1.15.0",
|
||||||
"derequire": "2.0.3",
|
"derequire": "2.0.3",
|
||||||
|
"eslint-plugin-openlayers-internal": "file:test/rules",
|
||||||
"fs-extra": "0.30.0",
|
"fs-extra": "0.30.0",
|
||||||
"glob": "7.0.5",
|
"glob": "7.0.5",
|
||||||
"handlebars": "4.0.5",
|
"handlebars": "4.0.5",
|
||||||
@@ -82,6 +83,9 @@
|
|||||||
"goog": false,
|
"goog": false,
|
||||||
"proj4": false
|
"proj4": false
|
||||||
},
|
},
|
||||||
|
"plugins": [
|
||||||
|
"openlayers-internal"
|
||||||
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": [
|
"no-console": [
|
||||||
2,
|
2,
|
||||||
@@ -91,7 +95,8 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"no-constant-condition": 0
|
"no-constant-condition": 0,
|
||||||
|
"openlayers-internal/no-unused-requires": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ext": [
|
"ext": [
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es6": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
rules: {
|
||||||
|
'no-unused-requires': require('./no-unused-requires').rule
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
function isGoogRequire(node) {
|
||||||
|
const callee = node.callee;
|
||||||
|
return callee.type === 'MemberExpression' &&
|
||||||
|
callee.object.type === 'Identifier' && callee.object.name === 'goog' &&
|
||||||
|
callee.property.type === 'Identifier' && !callee.property.computed && callee.property.name === 'require';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getName(node) {
|
||||||
|
if (node.type !== 'MemberExpression') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.property.type !== 'Identifier' || node.property.computed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let objectName;
|
||||||
|
if (node.object.type === 'Identifier' && !node.object.computed) {
|
||||||
|
objectName = node.object.name;
|
||||||
|
} else if (node.object.type === 'MemberExpression' && !node.object.computed) {
|
||||||
|
objectName = getName(node.object);
|
||||||
|
}
|
||||||
|
if (!objectName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return `${objectName}.${node.property.name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.rule = {
|
||||||
|
meta: {
|
||||||
|
docs: {
|
||||||
|
description: 'disallow unused goog.require() calls'
|
||||||
|
},
|
||||||
|
schema: []
|
||||||
|
},
|
||||||
|
create: function(context) {
|
||||||
|
|
||||||
|
// a lookup of goog.require() nodes by argument
|
||||||
|
const requireNodes = {};
|
||||||
|
|
||||||
|
// used names from member expressions that match the goog.require() arg
|
||||||
|
const usedNames = {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
CallExpression: function(node) {
|
||||||
|
|
||||||
|
if (isGoogRequire(node)) {
|
||||||
|
if (node.arguments.length !== 1) {
|
||||||
|
return context.report(node, 'Expected one argument for goog.require()');
|
||||||
|
}
|
||||||
|
const arg = node.arguments[0];
|
||||||
|
if (arg.type !== 'Literal' || !arg.value || typeof arg.value !== 'string') {
|
||||||
|
return context.report(node, 'Expected goog.require() to be called with a string');
|
||||||
|
}
|
||||||
|
const name = arg.value;
|
||||||
|
if (name in requireNodes) {
|
||||||
|
return context.report(node, `Duplicate goog.require('${name}')`);
|
||||||
|
}
|
||||||
|
requireNodes[name] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
MemberExpression: function(node) {
|
||||||
|
const name = getName(node);
|
||||||
|
if (name in requireNodes) {
|
||||||
|
const requiredAncestor = context.getAncestors().some(ancestorNode => !!requireNodes[getName(ancestorNode)]);
|
||||||
|
if (!requiredAncestor) {
|
||||||
|
usedNames[name] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Identifier: function(node) {
|
||||||
|
const name = node.name;
|
||||||
|
if (name in requireNodes) {
|
||||||
|
const ancestors = context.getAncestors();
|
||||||
|
if (ancestors.length && ancestors[0].type === 'MemberExpression') {
|
||||||
|
const requiredAncestor = context.getAncestors().some(ancestorNode => !!requireNodes[getName(ancestorNode)]);
|
||||||
|
if (!requiredAncestor) {
|
||||||
|
usedNames[name] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
usedNames[name] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'Program:exit': function(node) {
|
||||||
|
const source = context.getSourceCode();
|
||||||
|
for (let name in requireNodes) {
|
||||||
|
if (!usedNames[name]) {
|
||||||
|
const unusedRequire = requireNodes[name];
|
||||||
|
context.report(unusedRequire, `Unused ${source.getText(unusedRequire)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "eslint-plugin-openlayers-internal",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Custom ESLint rules for the OpenLayers project",
|
||||||
|
"main": "index.js"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user