Bug 1456686: Part 2 - Update ESLint plugin to treat explicit imports as real variable definitions. r=standard8
authorKris Maglione <maglione.k@gmail.com>
Tue, 24 Apr 2018 20:17:12 -0700
changeset 469198 9800c0f0edc9049f3004bf23e0676d4d467fd8e6
parent 469197 95b7f4ae23fdaf6d806ffac8a402e5f043dbd1c5
child 469199 e316258ed9aeeed1257b138dbaa1f03899828b84
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstandard8
bugs1456686
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456686: Part 2 - Update ESLint plugin to treat explicit imports as real variable definitions. r=standard8 This has the effect of exposing explicit imports (e.g., defineModuleGetter), but not implicit imports (e.g., Cu.import), to rules like no-unused-vars and no-shadow. MozReview-Commit-ID: C8oXoSKMU1s
tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js
tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
tools/lint/eslint/eslint-plugin-mozilla/package.json
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js
@@ -223,15 +223,15 @@ module.exports = {
     let handler = new GlobalsForNode(helpers.getAbsoluteFilePath(context));
 
     for (let type of Object.keys(GlobalsForNode.prototype)) {
       parser[type] = function(node) {
         if (type === "Program") {
           globalScope = context.getScope();
         }
         let globals = handler[type](node, context.getAncestors(), globalScope);
-        helpers.addGlobals(globals, globalScope);
+        helpers.addGlobals(globals, globalScope, node.type !== "Program" && node);
       };
     }
 
     return parser;
   }
 };
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
@@ -295,56 +295,62 @@ module.exports = {
     // a global, so bail out early if we're not a global.
     if (!isGlobal) {
       return [];
     }
 
     for (let reg of callExpressionDefinitions) {
       let match = source.match(reg);
       if (match) {
-        return [{ name: match[1], writable: true }];
+        return [{ name: match[1], writable: true, explicit: true }];
       }
     }
 
     if (callExpressionMultiDefinitions.some(expr => source.startsWith(expr)) &&
         node.expression.arguments[1] &&
         node.expression.arguments[1].type === "ObjectExpression") {
       return node.expression.arguments[1].properties
-                 .map(p => ({ name: p.type === "Property" && p.key.name, writable: true }))
+                 .map(p => ({ name: p.type === "Property" && p.key.name, writable: true, explicit: true }))
                  .filter(g => g.name);
     }
 
     if (node.expression.callee.type == "MemberExpression" &&
         node.expression.callee.property.type == "Identifier" &&
         node.expression.callee.property.name == "defineLazyScriptGetter") {
       // The case where we have a single symbol as a string has already been
       // handled by the regexp, so we have an array of symbols here.
-      return node.expression.arguments[1].elements.map(n => ({ name: n.value, writable: true }));
+      return node.expression.arguments[1].elements.map(n => ({ name: n.value, writable: true, explicit: true }));
     }
 
     return [];
   },
 
   /**
    * Add a variable to the current scope.
    * HACK: This relies on eslint internals so it could break at any time.
    *
    * @param {String} name
    *        The variable name to add to the scope.
    * @param {ASTScope} scope
    *        The scope to add to.
    * @param {boolean} writable
    *        Whether the global can be overwritten.
+   * @param {Object} [node]
+   *        The AST node that defined the globals.
    */
-  addVarToScope(name, scope, writable) {
+  addVarToScope(name, scope, writable, node) {
     scope.__defineGeneric(name, scope.set, scope.variables, null, null);
 
     let variable = scope.set.get(name);
     variable.eslintExplicitGlobal = false;
     variable.writeable = writable;
+    if (node) {
+      variable.defs.push({node, name: {name}});
+      variable.identifiers.push(node);
+    }
 
     // Walk to the global scope which holds all undeclared variables.
     while (scope.type != "global") {
       scope = scope.upper;
     }
 
     // "through" contains all references with no found definition.
     scope.through = scope.through.filter(function(reference) {
@@ -362,19 +368,21 @@ module.exports = {
 
   /**
    * Adds a set of globals to a scope.
    *
    * @param {Array} globalVars
    *        An array of global variable names.
    * @param {ASTScope} scope
    *        The scope.
+   * @param {Object} [node]
+   *        The AST node that defined the globals.
    */
-  addGlobals(globalVars, scope) {
-    globalVars.forEach(v => this.addVarToScope(v.name, scope, v.writable));
+  addGlobals(globalVars, scope, node) {
+    globalVars.forEach(v => this.addVarToScope(v.name, scope, v.writable, v.explicit && node));
   },
 
   /**
    * To allow espree to parse almost any JavaScript we need as many features as
    * possible turned on. This method returns that config.
    *
    * @return {Object}
    *         Espree compatible permissive config.
--- a/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
@@ -1,11 +1,11 @@
 {
   "name": "eslint-plugin-mozilla",
-  "version": "0.10.0",
+  "version": "0.11.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
     "acorn": {
       "version": "5.5.3",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
       "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==",
       "dev": true
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -1,11 +1,11 @@
 {
   "name": "eslint-plugin-mozilla",
-  "version": "0.10.0",
+  "version": "0.11.0",
   "description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
   "keywords": [
     "eslint",
     "eslintplugin",
     "eslint-plugin",
     "mozilla",
     "firefox"
   ],