Bug 1779988 - Part 2: Add ESLint rule that rejects multiple `ChromeUtils.defineESModuleGetters` call on the same object. r=Standard8

Differential Revision: https://phabricator.services.mozilla.com/D152880
This commit is contained in:
Tooru Fujisawa 2022-07-28 00:54:20 +00:00
Родитель bf159ca171
Коммит de340512f3
6 изменённых файлов: 171 добавлений и 0 удалений

Просмотреть файл

@ -55,6 +55,7 @@ The plugin implements the following rules:
eslint-plugin-mozilla/reject-importGlobalProperties
eslint-plugin-mozilla/reject-lazy-imports-into-globals
eslint-plugin-mozilla/reject-mixing-eager-and-lazy
eslint-plugin-mozilla/reject-multiple-getters-calls
eslint-plugin-mozilla/reject-osfile
eslint-plugin-mozilla/reject-relative-requires
eslint-plugin-mozilla/reject-requires-await

Просмотреть файл

@ -0,0 +1,27 @@
reject-multiple-getters-calls
=============================
Rejects multiple calls on ``ChromeUtils.defineESModuleGetters`` for the same
target in the same context.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
});
ChromeUtils.defineESModuleGetters(lazy, {
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});

Просмотреть файл

@ -165,6 +165,7 @@ module.exports = {
"mozilla/reject-addtask-only": "error",
"mozilla/reject-chromeutils-import-params": "error",
"mozilla/reject-importGlobalProperties": ["error", "allownonwebidl"],
"mozilla/reject-multiple-getters-calls": "error",
"mozilla/reject-osfile": "warn",
"mozilla/reject-scriptableunicodeconverter": "warn",
"mozilla/rejects-requires-await": "error",

Просмотреть файл

@ -66,6 +66,7 @@ module.exports = {
"reject-importGlobalProperties": require("../lib/rules/reject-importGlobalProperties"),
"reject-lazy-imports-into-globals": require("../lib/rules/reject-lazy-imports-into-globals"),
"reject-mixing-eager-and-lazy": require("../lib/rules/reject-mixing-eager-and-lazy"),
"reject-multiple-getters-calls": require("../lib/rules/reject-multiple-getters-calls"),
"reject-osfile": require("../lib/rules/reject-osfile"),
"reject-scriptableunicodeconverter": require("../lib/rules/reject-scriptableunicodeconverter"),
"reject-relative-requires": require("../lib/rules/reject-relative-requires"),

Просмотреть файл

@ -0,0 +1,81 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
"use strict";
const helpers = require("../helpers");
function findStatement(node) {
while (node && node.type !== "ExpressionStatement") {
node = node.parent;
}
return node;
}
function isIdentifier(node, id) {
return node && node.type === "Identifier" && node.name === id;
}
module.exports = {
meta: {
docs: {
url:
"https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.html",
},
messages: {
rejectMultipleCalls:
"ChromeUtils.defineESModuleGetters is already called for {{target}} in the same context. Please merge those calls",
},
type: "suggestion",
},
create(context) {
const parentToTargets = new Map();
return {
CallExpression(node) {
let callee = node.callee;
if (
callee.type === "MemberExpression" &&
isIdentifier(callee.object, "ChromeUtils") &&
isIdentifier(callee.property, "defineESModuleGetters")
) {
const stmt = findStatement(node);
if (!stmt) {
return;
}
let target;
try {
target = helpers.getASTSource(node.arguments[0]);
} catch (e) {
return;
}
const parent = stmt.parent;
let targets;
if (parentToTargets.has(parent)) {
targets = parentToTargets.get(parent);
} else {
targets = new Set();
parentToTargets.set(parent, targets);
}
if (targets.has(target)) {
context.report({
node,
messageId: "rejectMultipleCalls",
data: { target },
});
}
targets.add(target);
}
},
};
},
};

Просмотреть файл

@ -0,0 +1,60 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
var rule = require("../lib/rules/reject-multiple-getters-calls");
var RuleTester = require("eslint").RuleTester;
const ruleTester = new RuleTester();
// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------
function invalidCode(code) {
return { code, errors: [{ messageId: "rejectMultipleCalls" }] };
}
ruleTester.run("reject-multiple-getters-calls", rule, {
valid: [
`
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
`,
`
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
});
ChromeUtils.defineESModuleGetters(window, {
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
`,
`
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
});
if (cond) {
ChromeUtils.defineESModuleGetters(lazy, {
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
}
`,
],
invalid: [
invalidCode(`
ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
});
ChromeUtils.defineESModuleGetters(lazy, {
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
`),
],
});