diff --git a/lib/linter/report-translator.js b/lib/linter/report-translator.js index 9ce482a9ee7..874bb4aef7b 100644 --- a/lib/linter/report-translator.js +++ b/lib/linter/report-translator.js @@ -195,12 +195,10 @@ function mapSuggestions(descriptor, sourceCode) { return []; } - return descriptor.suggest.map(suggestInfo => Object.assign( - {}, - suggestInfo, - { fix: normalizeFixes(suggestInfo, sourceCode) } - )); - + return descriptor.suggest.map(suggestInfo => ({ + desc: suggestInfo.desc, + fix: normalizeFixes(suggestInfo, sourceCode) + })); } /** diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js index e4e4e163e67..041c7f126eb 100644 --- a/tests/lib/linter/linter.js +++ b/tests/lib/linter/linter.js @@ -4299,6 +4299,42 @@ describe("Linter", () => { }); }); + describe("suggestions", () => { + it("provides suggestion information for tools to use", () => { + linter.defineRule("rule-with-suggestions", context => ({ + Program(node) { + context.report({ + node, + message: "Incorrect spacing", + suggest: [{ + desc: "Insert space at the beginning", + fix: fixer => fixer.insertTextBefore(node, " ") + }, { + desc: "Insert space at the end", + fix: fixer => fixer.insertTextAfter(node, " ") + }] + }); + } + })); + + const messages = linter.verify("var a = 1;", { rules: { "rule-with-suggestions": "error" } }); + + assert.deepStrictEqual(messages[0].suggestions, [{ + desc: "Insert space at the beginning", + fix: { + range: [0, 0], + text: " " + } + }, { + desc: "Insert space at the end", + fix: { + range: [10, 10], + text: " " + } + }]); + }); + }); + describe("mutability", () => { let linter1 = null; let linter2 = null; diff --git a/tests/lib/linter/report-translator.js b/tests/lib/linter/report-translator.js index 50a7d82f7ee..542a8af4b4f 100644 --- a/tests/lib/linter/report-translator.js +++ b/tests/lib/linter/report-translator.js @@ -367,6 +367,73 @@ describe("createReportTranslator", () => { }); }); + describe("suggestions", () => { + it("should support multiple suggestions.", () => { + const reportDescriptor = { + node, + loc: location, + message, + suggest: [{ + desc: "A first suggestion for the issue", + fix: () => [{ range: [1, 2], text: "foo" }] + }, { + desc: "A different suggestion for the issue", + fix: () => [{ range: [1, 3], text: "foobar" }] + }] + }; + + assert.deepStrictEqual( + translateReport(reportDescriptor), + { + ruleId: "foo-rule", + severity: 2, + message: "foo", + line: 2, + column: 1, + nodeType: "ExpressionStatement", + suggestions: [{ + desc: "A first suggestion for the issue", + fix: { range: [1, 2], text: "foo" } + }, { + desc: "A different suggestion for the issue", + fix: { range: [1, 3], text: "foobar" } + }] + } + ); + }); + + it("should merge suggestion fixes to one if 'fix' function returns an array of fixes.", () => { + const reportDescriptor = { + node, + loc: location, + message, + suggest: [{ + desc: "A suggestion for the issue", + fix: () => [{ range: [1, 2], text: "foo" }, { range: [4, 5], text: "bar" }] + }] + }; + + assert.deepStrictEqual( + translateReport(reportDescriptor), + { + ruleId: "foo-rule", + severity: 2, + message: "foo", + line: 2, + column: 1, + nodeType: "ExpressionStatement", + suggestions: [{ + desc: "A suggestion for the issue", + fix: { + range: [1, 5], + text: "fooo\nbar" + } + }] + } + ); + }); + }); + describe("message interpolation", () => { it("should correctly parse a message when being passed all options in an old-style report", () => { assert.deepStrictEqual(