From 4aa64bb7129955a27ed52641e38e5f54aaea9c53 Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Tue, 2 Nov 2021 23:18:34 +0800 Subject: [PATCH 01/11] feat: support async formatter closes #15242 --- lib/cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli.js b/lib/cli.js index 477310da585..f09d143d255 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -178,7 +178,7 @@ async function printResults(engine, results, format, outputFile) { return false; } - const output = formatter.format(results); + const output = await formatter.format(results); if (output) { if (outputFile) { From 95b68730d166bb0af0ba5e3ac6191814df944444 Mon Sep 17 00:00:00 2001 From: MO Date: Thu, 4 Nov 2021 03:41:29 +0800 Subject: [PATCH 02/11] test: add test for async formatter --- tests/fixtures/async-formatter.js | 4 ++++ tests/lib/cli.js | 11 +++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/fixtures/async-formatter.js diff --git a/tests/fixtures/async-formatter.js b/tests/fixtures/async-formatter.js new file mode 100644 index 00000000000..9d8c76b43ce --- /dev/null +++ b/tests/fixtures/async-formatter.js @@ -0,0 +1,4 @@ +/*global module*/ +module.exports = async function(results) { + return await Promise.resolve('from async formatter'); +}; diff --git a/tests/lib/cli.js b/tests/lib/cli.js index 1b3828b4090..2ba5ac4baf3 100644 --- a/tests/lib/cli.js +++ b/tests/lib/cli.js @@ -287,6 +287,17 @@ describe("cli", () => { }); }); + describe("when given an async formatter path", () => { + it("should execute without any errors", async () => { + const formatterPath = getFixturePath("async-formatter.js"); + const filePath = getFixturePath("passing.js"); + const exit = await cli.execute(`-f ${formatterPath} ${filePath}`); + + assert.strictEqual(log.info.getCall(0).args[0], "from async formatter"); + assert.strictEqual(exit, 0); + }); + }); + describe("when executing a file with a lint error", () => { it("should exit with error", async () => { const filePath = getFixturePath("undef.js"); From 260305f26e30fa057f7c58c68b08ef8985dc19e7 Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Thu, 4 Nov 2021 03:54:39 +0800 Subject: [PATCH 03/11] test: tweak async formatter fixture --- tests/fixtures/async-formatter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fixtures/async-formatter.js b/tests/fixtures/async-formatter.js index 9d8c76b43ce..b5651a697a4 100644 --- a/tests/fixtures/async-formatter.js +++ b/tests/fixtures/async-formatter.js @@ -1,4 +1,4 @@ /*global module*/ -module.exports = async function(results) { - return await Promise.resolve('from async formatter'); +module.exports = function(results) { + return Promise.resolve('from async formatter'); }; From 500f4e29aba237eb55c07ee775654009b1e104e6 Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Thu, 4 Nov 2021 12:01:11 +0800 Subject: [PATCH 04/11] docs: support async formatter --- docs/developer-guide/working-with-custom-formatters.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md index a5e9ade81bf..f3f7b27a831 100644 --- a/docs/developer-guide/working-with-custom-formatters.md +++ b/docs/developer-guide/working-with-custom-formatters.md @@ -11,6 +11,16 @@ module.exports = function(results) { }; ``` +Formatter can also be an async function (from ESLint 8.2.0), the following shows a simple example: + +```js +//my-awesome-formatter.js +module.exports = async function(results) { + const formatted = await asyncTask(); + return formatted; +}; +``` + To run ESLint with this formatter, you can use the `-f` (or `--format`) command line flag: ```bash From b72a9e8597592ace0e38eac4b09c94871a379a55 Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Thu, 4 Nov 2021 13:12:55 +0800 Subject: [PATCH 05/11] docs: fix formatter type --- docs/developer-guide/nodejs-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md index 378b9c16b8d..e4a3a1e42c1 100644 --- a/docs/developer-guide/nodejs-api.md +++ b/docs/developer-guide/nodejs-api.md @@ -404,7 +404,7 @@ This edit information means replacing the range of the `range` property by the ` The `Formatter` value is the object to convert the [LintResult] objects to text. The [eslint.loadFormatter()][eslint-loadformatter] method returns it. It has the following method: -* `format` (`(results: LintResult[]) => string`)
+* `format` (`(results: LintResult[]) => string | Promise`)
The method to convert the [LintResult] objects to text. --- From a62dac5ab600d5ea95cb7430186a4c97c02da96a Mon Sep 17 00:00:00 2001 From: MO Date: Sun, 7 Nov 2021 12:51:55 +0800 Subject: [PATCH 06/11] test: move async formatter to formatters --- .../{async-formatter.js => formatters/async.js} | 0 tests/lib/cli-engine/cli-engine.js | 10 +++++++--- tests/lib/cli.js | 2 +- tests/lib/eslint/eslint.js | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) rename tests/fixtures/{async-formatter.js => formatters/async.js} (100%) diff --git a/tests/fixtures/async-formatter.js b/tests/fixtures/formatters/async.js similarity index 100% rename from tests/fixtures/async-formatter.js rename to tests/fixtures/formatters/async.js diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js index 31f59bf51b4..16beb92b87b 100644 --- a/tests/lib/cli-engine/cli-engine.js +++ b/tests/lib/cli-engine/cli-engine.js @@ -1160,7 +1160,7 @@ describe("CLIEngine", () => { const report = engine.executeOnFiles([getFixturePath("formatters")]); - assert.strictEqual(report.results.length, 3); + assert.strictEqual(report.results.length, 4); assert.strictEqual(report.errorCount, 0); assert.strictEqual(report.warningCount, 0); assert.strictEqual(report.fixableErrorCount, 0); @@ -1200,14 +1200,18 @@ describe("CLIEngine", () => { assert.strictEqual(report.results[0].warningCount, 0); assert.strictEqual(report.results[0].fixableErrorCount, 0); assert.strictEqual(report.results[0].fixableWarningCount, 0); - assert.strictEqual(report.results[1].errorCount, 3); + assert.strictEqual(report.results[1].errorCount, 0); assert.strictEqual(report.results[1].warningCount, 0); - assert.strictEqual(report.results[1].fixableErrorCount, 3); + assert.strictEqual(report.results[1].fixableErrorCount, 0); assert.strictEqual(report.results[1].fixableWarningCount, 0); assert.strictEqual(report.results[2].errorCount, 3); assert.strictEqual(report.results[2].warningCount, 0); assert.strictEqual(report.results[2].fixableErrorCount, 3); assert.strictEqual(report.results[2].fixableWarningCount, 0); + assert.strictEqual(report.results[3].errorCount, 3); + assert.strictEqual(report.results[3].warningCount, 0); + assert.strictEqual(report.results[3].fixableErrorCount, 3); + assert.strictEqual(report.results[3].fixableWarningCount, 0); }); it("should process when file is given by not specifying extensions", () => { diff --git a/tests/lib/cli.js b/tests/lib/cli.js index 2ba5ac4baf3..143a3ac1efc 100644 --- a/tests/lib/cli.js +++ b/tests/lib/cli.js @@ -289,7 +289,7 @@ describe("cli", () => { describe("when given an async formatter path", () => { it("should execute without any errors", async () => { - const formatterPath = getFixturePath("async-formatter.js"); + const formatterPath = getFixturePath("formatters", "async.js"); const filePath = getFixturePath("passing.js"); const exit = await cli.execute(`-f ${formatterPath} ${filePath}`); diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js index eaf4aaaaf05..d984f5a3082 100644 --- a/tests/lib/eslint/eslint.js +++ b/tests/lib/eslint/eslint.js @@ -1212,7 +1212,7 @@ describe("ESLint", () => { }); const results = await eslint.lintFiles([getFixturePath("formatters")]); - assert.strictEqual(results.length, 3); + assert.strictEqual(results.length, 4); assert.strictEqual(results[0].messages.length, 0); assert.strictEqual(results[1].messages.length, 0); assert.strictEqual(results[2].messages.length, 0); From 8b21d5fccc89ce062c05dfb51fde5e56c246c70a Mon Sep 17 00:00:00 2001 From: MO Date: Sun, 7 Nov 2021 13:12:37 +0800 Subject: [PATCH 07/11] chore: add Formatter typedef --- lib/eslint/eslint.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/eslint/eslint.js b/lib/eslint/eslint.js index 8886d45ab43..d8b2c4bb3e6 100644 --- a/lib/eslint/eslint.js +++ b/lib/eslint/eslint.js @@ -34,7 +34,12 @@ const { version } = require("../../package.json"); /** @typedef {import("../shared/types").LintMessage} LintMessage */ /** @typedef {import("../shared/types").Plugin} Plugin */ /** @typedef {import("../shared/types").Rule} Rule */ -/** @typedef {import("./load-formatter").Formatter} Formatter */ + +/** + * The main formatter object. + * @typedef Formatter + * @property {function(LintResult[]): string | Promise } [format] format function. + */ /** * The options with which to configure the ESLint instance. @@ -629,7 +634,7 @@ class ESLint { /** * The main formatter method. * @param {LintResults[]} results The lint results to format. - * @returns {string} The formatted lint results. + * @returns {string | Promise} The formatted lint results. */ format(results) { let rulesMeta = null; From f9049df4150a81506c89724895f6af6b64a97c17 Mon Sep 17 00:00:00 2001 From: MO Date: Sun, 7 Nov 2021 13:19:35 +0800 Subject: [PATCH 08/11] style: remove extra space --- lib/eslint/eslint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/eslint/eslint.js b/lib/eslint/eslint.js index d8b2c4bb3e6..e02c14df167 100644 --- a/lib/eslint/eslint.js +++ b/lib/eslint/eslint.js @@ -38,7 +38,7 @@ const { version } = require("../../package.json"); /** * The main formatter object. * @typedef Formatter - * @property {function(LintResult[]): string | Promise } [format] format function. + * @property {function(LintResult[]): string | Promise} [format] format function. */ /** From 945bfb7700a1adc17cdd791b61e6e9611754354f Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Tue, 23 Nov 2021 23:03:43 +0800 Subject: [PATCH 09/11] docs: update ESLint version for async formatter Co-authored-by: Milos Djermanovic --- docs/developer-guide/working-with-custom-formatters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md index f3f7b27a831..2fe9a9c5a9a 100644 --- a/docs/developer-guide/working-with-custom-formatters.md +++ b/docs/developer-guide/working-with-custom-formatters.md @@ -11,7 +11,7 @@ module.exports = function(results) { }; ``` -Formatter can also be an async function (from ESLint 8.2.0), the following shows a simple example: +Formatter can also be an async function (from ESLint 8.4.0), the following shows a simple example: ```js //my-awesome-formatter.js From 2bbf360f5b4b97b0a856216cde918ad04ba95754 Mon Sep 17 00:00:00 2001 From: MO <9125255+fengzilong@users.noreply.github.com> Date: Tue, 23 Nov 2021 23:08:09 +0800 Subject: [PATCH 10/11] chore: format is not optional Co-authored-by: Milos Djermanovic --- lib/eslint/eslint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/eslint/eslint.js b/lib/eslint/eslint.js index e02c14df167..29d7e5cbc92 100644 --- a/lib/eslint/eslint.js +++ b/lib/eslint/eslint.js @@ -38,7 +38,7 @@ const { version } = require("../../package.json"); /** * The main formatter object. * @typedef Formatter - * @property {function(LintResult[]): string | Promise} [format] format function. + * @property {function(LintResult[]): string | Promise} format format function. */ /** From 30a9e9e468108741cdf642622d2017cced89732b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 23 Nov 2021 17:22:17 -0800 Subject: [PATCH 11/11] Update docs/developer-guide/working-with-custom-formatters.md --- docs/developer-guide/working-with-custom-formatters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md index 2fe9a9c5a9a..181aa69cec5 100644 --- a/docs/developer-guide/working-with-custom-formatters.md +++ b/docs/developer-guide/working-with-custom-formatters.md @@ -11,7 +11,7 @@ module.exports = function(results) { }; ``` -Formatter can also be an async function (from ESLint 8.4.0), the following shows a simple example: +Formatter can also be an async function (from ESLint v8.4.0), the following shows a simple example: ```js //my-awesome-formatter.js