From 42cf53ea823813ba4dc4d7667e5c81e3f88fd2b1 Mon Sep 17 00:00:00 2001 From: Julian Descottes Date: Mon, 16 Sep 2024 09:13:30 +0000 Subject: [PATCH] Bug 1917003 - [eslint] Add linter rule to ban await await r=Standard8,frontend-codestyle-reviewers Differential Revision: https://phabricator.services.mozilla.com/D221187 --- .../rules/reject-multiple-await.rst | 23 ++++++++++++ .../lib/configs/recommended.js | 1 + .../eslint/eslint-plugin-mozilla/lib/index.js | 1 + .../lib/rules/reject-multiple-await.js | 35 ++++++++++++++++++ .../tests/reject-multiple-await.js | 37 +++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-await.rst create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-await.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-await.js diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-await.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-await.rst new file mode 100644 index 000000000000..a9ee4c215c97 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-await.rst @@ -0,0 +1,23 @@ +reject-multiple-await +===================== + +Disallows using `await await somePromise`. While this is valid syntax, this +usually unintentional and can have a slightly different behavior from using a +single `await`. Using `await await` should ideally be explained with a comment. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + await await somePromise; + await await await somePromise; + await (await somePromise); + + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + await somePromise; diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js index 56f760b835bf..27aa3fb9013d 100644 --- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js @@ -176,6 +176,7 @@ module.exports = { "mozilla/reject-chromeutils-import": "error", "mozilla/reject-chromeutils-import-params": "error", "mozilla/reject-importGlobalProperties": ["error", "allownonwebidl"], + "mozilla/reject-multiple-await": "error", "mozilla/reject-multiple-getters-calls": "error", "mozilla/reject-scriptableunicodeconverter": "warn", "mozilla/rejects-requires-await": "error", diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js index 23da078fe978..0d50402f0bad 100644 --- a/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js @@ -76,6 +76,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-await": require("../lib/rules/reject-multiple-await.js"), "reject-multiple-getters-calls": require("../lib/rules/reject-multiple-getters-calls"), "reject-scriptableunicodeconverter": require("../lib/rules/reject-scriptableunicodeconverter"), "reject-relative-requires": require("../lib/rules/reject-relative-requires"), diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-await.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-await.js new file mode 100644 index 000000000000..06f32cfb6464 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-await.js @@ -0,0 +1,35 @@ +/** + * @fileoverview Reject multiple await operators. + * + * 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"; + +module.exports = { + meta: { + docs: { + url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-await.html", + }, + messages: { + rejectMultipleAwait: "Do not use multiple await operators.", + }, + schema: [], + type: "problem", + }, + + create(context) { + return { + AwaitExpression(node) { + if ( + node.parent.type === "AwaitExpression" && + node.parent.parent.type !== "AwaitExpression" + ) { + context.report({ node, messageId: "rejectMultipleAwait" }); + } + }, + }; + }, +}; diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-await.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-await.js new file mode 100644 index 000000000000..c5051a447107 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-await.js @@ -0,0 +1,37 @@ +/* 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-await"); +var RuleTester = require("eslint").RuleTester; + +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } }); + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +function invalidCode(code) { + return { code, errors: [{ messageId: "rejectMultipleAwait" }] }; +} + +ruleTester.run("reject-multiple-await", rule, { + valid: [ + "async () => await new Promise(r => r());", + "async () => await awaitSomething;", + ], + invalid: [ + invalidCode("async () => await await new Promise(r => r());"), + invalidCode(`async () => { + await + await new Promise(r => r()); + }`), + invalidCode("async () => await (await new Promise(r => r()));"), + invalidCode("async () => await await await new Promise(r => r());"), + ], +});