From 02d3dc36b3ef040b43e7b19010c7412c8504e60b Mon Sep 17 00:00:00 2001 From: Colin Chang Date: Sun, 7 Oct 2018 11:11:02 -0400 Subject: [PATCH] Fix: add deprecation warning to Node API output (#7443) --- lib/cli-engine.js | 29 +++++++- tests/lib/cli-engine.js | 155 +++++++++++++++++++++++----------------- 2 files changed, 118 insertions(+), 66 deletions(-) diff --git a/lib/cli-engine.js b/lib/cli-engine.js index 5b52459ac830..c25ff4f7c732 100644 --- a/lib/cli-engine.js +++ b/lib/cli-engine.js @@ -272,6 +272,30 @@ function createIgnoreResult(filePath, baseDir) { }; } +/** + * Produces rule warnings (i.e. deprecation) from configured rules + * @param {Object} rules - Rules configured + * @param {Map} loadedRules - Map of loaded rules + * @returns {Object} Contains rule warnings + * @private + */ +function createRuleWarnings(rules, loadedRules) { + const ruleWarnings = { usedDeprecatedRules: [] }; + + if (!rules) { + return ruleWarnings; + } + + Object.keys(rules).forEach(name => { + const loadedRule = loadedRules.get(name); + + if (loadedRule.meta && loadedRule.meta.deprecated) { + ruleWarnings.usedDeprecatedRules.push({ ruleId: name, replacedBy: loadedRule.meta.docs.replacedBy }); + } + }); + + return ruleWarnings; +} /** * Checks if the given message is an error message. @@ -555,6 +579,8 @@ class CLIEngine { const stats = calculateStatsPerRun(results); + const ruleWarnings = createRuleWarnings(this.options.rules, this.getRules()); + debug(`Linting complete in: ${Date.now() - startTime}ms`); return { @@ -562,7 +588,8 @@ class CLIEngine { errorCount: stats.errorCount, warningCount: stats.warningCount, fixableErrorCount: stats.fixableErrorCount, - fixableWarningCount: stats.fixableWarningCount + fixableWarningCount: stats.fixableWarningCount, + usedDeprecatedRules: ruleWarnings.usedDeprecatedRules }; } diff --git a/tests/lib/cli-engine.js b/tests/lib/cli-engine.js index cac7671b197e..92458b59af70 100644 --- a/tests/lib/cli-engine.js +++ b/tests/lib/cli-engine.js @@ -1375,6 +1375,33 @@ describe("CLIEngine", () => { assert.strictEqual(report.results[0].messages.length, 0); }); + it("should warn when deprecated rules are configured", () => { + engine = new CLIEngine({ + cwd: originalDir, + configFile: ".eslintrc.js", + rules: { "indent-legacy": 1 } + }); + + const report = engine.executeOnFiles(["lib/cli*.js"]); + + assert.deepStrictEqual( + report.usedDeprecatedRules, + [{ ruleId: "indent-legacy", replacedBy: ["indent"] }] + ); + }); + + it("should not warn when deprecated rules are not configured", () => { + engine = new CLIEngine({ + cwd: originalDir, + configFile: ".eslintrc.js", + rules: { indent: 1 } + }); + + const report = engine.executeOnFiles(["lib/cli*.js"]); + + assert.deepStrictEqual(report.usedDeprecatedRules, []); + }); + describe("Fix Mode", () => { it("should return fixed text on multiple files when in fix mode", () => { @@ -1407,70 +1434,68 @@ describe("CLIEngine", () => { const report = engine.executeOnFiles([path.resolve(fixtureDir, `${fixtureDir}/fixmode`)]); report.results.forEach(convertCRLF); - assert.deepStrictEqual(report, { - results: [ - { - filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/multipass.js")), - messages: [], - errorCount: 0, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0, - output: "true ? \"yes\" : \"no\";\n" - }, - { - filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/ok.js")), - messages: [], - errorCount: 0, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0 - }, - { - filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes-semi-eqeqeq.js")), - messages: [ - { - column: 9, - line: 2, - message: "Expected '===' and instead saw '=='.", - messageId: "unexpected", - nodeType: "BinaryExpression", - ruleId: "eqeqeq", - severity: 2 - } - ], - errorCount: 1, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0, - output: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n" - }, - { - filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes.js")), - messages: [ - { - column: 18, - line: 1, - endColumn: 21, - endLine: 1, - message: "'foo' is not defined.", - nodeType: "Identifier", - ruleId: "no-undef", - severity: 2 - } - ], - errorCount: 1, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0, - output: "var msg = \"hi\" + foo;\n" - } - ], - errorCount: 2, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0 - }); + assert.deepStrictEqual(report.results, [ + { + filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/multipass.js")), + messages: [], + errorCount: 0, + warningCount: 0, + fixableErrorCount: 0, + fixableWarningCount: 0, + output: "true ? \"yes\" : \"no\";\n" + }, + { + filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/ok.js")), + messages: [], + errorCount: 0, + warningCount: 0, + fixableErrorCount: 0, + fixableWarningCount: 0 + }, + { + filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes-semi-eqeqeq.js")), + messages: [ + { + column: 9, + line: 2, + message: "Expected '===' and instead saw '=='.", + messageId: "unexpected", + nodeType: "BinaryExpression", + ruleId: "eqeqeq", + severity: 2 + } + ], + errorCount: 1, + warningCount: 0, + fixableErrorCount: 0, + fixableWarningCount: 0, + output: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n" + }, + { + filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes.js")), + messages: [ + { + column: 18, + line: 1, + endColumn: 21, + endLine: 1, + message: "'foo' is not defined.", + nodeType: "Identifier", + ruleId: "no-undef", + severity: 2 + } + ], + errorCount: 1, + warningCount: 0, + fixableErrorCount: 0, + fixableWarningCount: 0, + output: "var msg = \"hi\" + foo;\n" + } + ]); + assert.strictEqual(report.errorCount, 2); + assert.strictEqual(report.warningCount, 0); + assert.strictEqual(report.fixableErrorCount, 0); + assert.strictEqual(report.fixableWarningCount, 0); }); it("should run autofix even if files are cached without autofix results", () => { @@ -2117,7 +2142,7 @@ describe("CLIEngine", () => { assert.deepStrictEqual(result, cachedResult, "the result is the same regardless of using cache or not"); // assert the file was not processed because the cache was used - assert.isFalse(spy.called, "the file was not loaded because it used the cache"); + assert.isFalse(spy.calledWith(file), "the file was not loaded because it used the cache"); }); it("should remember the files from a previous run and do not operate on then if not changed", () => {