Repository: eslint/eslint
Pull request #11042 (2018-10-31 04:33:06)

Docs: Cross-reference two rules (refs #11041)
**What is the purpose of this pull request? (put an "X" next to item)**

[x] Documentation update

**What changes did you make? (Give an overview)**

Cross reference two rules in the documentation.

**Is there anything you'd like reviewers to focus on?**

Nope; there's not much to see!

/cc @platinumazure 


Patch:
diff --git a/docs/rules/no-useless-rename.md b/docs/rules/no-useless-rename.md
index 3675075b2..ea38e844b 100644
--- a/docs/rules/no-useless-rename.md
+++ b/docs/rules/no-useless-rename.md
@@ -28,13 +28,17 @@ let { foo } = bar;
 
 This rule disallows the renaming of import, export, and destructured assignments to the same name.
 
+See Also:
+
+- [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand) which can enforce this behavior for properties in object literals.
+
 ## Options
 
 This rule allows for more fine-grained control with the following options:
 
-* `ignoreImport`: When set to `true`, this rule does not check imports
-* `ignoreExport`: When set to `true`, this rule does not check exports
-* `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments
+- `ignoreImport`: When set to `true`, this rule does not check imports
+- `ignoreExport`: When set to `true`, this rule does not check exports
+- `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments
 
 By default, all options are set to `false`:
 
@@ -117,4 +121,4 @@ You can safely disable this rule if you do not care about redundantly renaming i
 
 ## Compatibility
 
-* **JSCS**: [disallowIdenticalDestructuringNames](https://jscs-dev.github.io/rule/disallowIdenticalDestructuringNames)
+- **JSCS**: [disallowIdenticalDestructuringNames](https://jscs-dev.github.io/rule/disallowIdenticalDestructuringNames)
diff --git a/docs/rules/object-shorthand.md b/docs/rules/object-shorthand.md
index 1f2f80db9..6f2471faf 100644
--- a/docs/rules/object-shorthand.md
+++ b/docs/rules/object-shorthand.md
@@ -82,16 +82,20 @@ var foo = {
 };
 ```
 
+See Also:
+
+- [`no-useless-rename`](https://eslint.org/docs/rules/object-shorthand) which disallows renaming import, export, and destructured assignments to the same name.
+
 ## Options
 
 The rule takes an option which specifies when it should be applied. It can be set to one of the following values:
 
-* `"always"` (default) expects that the shorthand will be used whenever possible.
-* `"methods"` ensures the method shorthand is used (also applies to generators).
-* `"properties"` ensures the property shorthand is used (where the key and variable name match).
-* `"never"` ensures that no property or method shorthand is used in any object literal.
-* `"consistent"` ensures that either all shorthand or all long-form will be used in an object literal.
-* `"consistent-as-needed"` ensures that either all shorthand or all long-form will be used in an object literal, but ensures all shorthand whenever possible.
+- `"always"` (default) expects that the shorthand will be used whenever possible.
+- `"methods"` ensures the method shorthand is used (also applies to generators).
+- `"properties"` ensures the property shorthand is used (where the key and variable name match).
+- `"never"` ensures that no property or method shorthand is used in any object literal.
+- `"consistent"` ensures that either all shorthand or all long-form will be used in an object literal.
+- `"consistent-as-needed"` ensures that either all shorthand or all long-form will be used in an object literal, but ensures all shorthand whenever possible.
 
 You can set the option in configuration like this:
 
@@ -103,9 +107,9 @@ You can set the option in configuration like this:
 
 Additionally, the rule takes an optional object configuration:
 
-* `"avoidQuotes": true` indicates that long-form syntax is preferred whenever the object key is a string literal (default: `false`). Note that this option can only be enabled when the string option is set to `"always"`, `"methods"`, or `"properties"`.
-* `"ignoreConstructors": true` can be used to prevent the rule from reporting errors for constructor functions. (By default, the rule treats constructors the same way as other functions.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
-* `"avoidExplicitReturnArrows": true` indicates that methods are preferred over explicit-return arrow functions for function properties. (By default, the rule allows either of these.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
+- `"avoidQuotes": true` indicates that long-form syntax is preferred whenever the object key is a string literal (default: `false`). Note that this option can only be enabled when the string option is set to `"always"`, `"methods"`, or `"properties"`.
+- `"ignoreConstructors": true` can be used to prevent the rule from reporting errors for constructor functions. (By default, the rule treats constructors the same way as other functions.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
+- `"avoidExplicitReturnArrows": true` indicates that methods are preferred over explicit-return arrow functions for function properties. (By default, the rule allows either of these.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
 
 ### `avoidQuotes`
 
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 1545bf4c0..f801aee48 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -22,6 +22,7 @@ const fs = require("fs"),
     lodash = require("lodash"),
     IgnoredPaths = require("./ignored-paths"),
     Config = require("./config"),
+    ConfigOps = require("./config/config-ops"),
     LintResultCache = require("./util/lint-result-cache"),
     globUtils = require("./util/glob-utils"),
     validator = require("./config/config-validator"),
@@ -143,7 +144,7 @@ function calculateStatsPerRun(results) {
  * @param {boolean} allowInlineConfig Allow/ignore comments that change config.
  * @param {boolean} reportUnusedDisableDirectives Allow/ignore comments that change config.
  * @param {Linter} linter Linter context
- * @returns {LintResult} The results for linting on this text.
+ * @returns {{rules: LintResult, config: Object}} The results for linting on this text and the fully-resolved config for it.
  * @private
  */
 function processText(text, configHelper, filename, fix, allowInlineConfig, reportUnusedDisableDirectives, linter) {
@@ -204,7 +205,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
         result.source = text;
     }
 
-    return result;
+    return { result, config };
 }
 
 /**
@@ -214,24 +215,22 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
  * @param {Object} configHelper The configuration options for ESLint.
  * @param {Object} options The CLIEngine options object.
  * @param {Linter} linter Linter context
- * @returns {LintResult} The results for linting on this file.
+ * @returns {{rules: LintResult, config: Object}} The results for linting on this text and the fully-resolved config for it.
  * @private
  */
 function processFile(filename, configHelper, options, linter) {
 
-    const text = fs.readFileSync(path.resolve(filename), "utf8"),
-        result = processText(
-            text,
-            configHelper,
-            filename,
-            options.fix,
-            options.allowInlineConfig,
-            options.reportUnusedDisableDirectives,
-            linter
-        );
-
-    return result;
-
+    const text = fs.readFileSync(path.resolve(filename), "utf8");
+
+    return processText(
+        text,
+        configHelper,
+        filename,
+        options.fix,
+        options.allowInlineConfig,
+        options.reportUnusedDisableDirectives,
+        linter
+    );
 }
 
 /**
@@ -275,32 +274,30 @@ function createIgnoreResult(filePath, baseDir) {
 
 /**
  * Produces rule warnings (i.e. deprecation) from configured rules
- * @param {Object} rules - Rules configured
+ * @param {(Array<string>|Set<string>)} usedRules - Rules configured
  * @param {Map} loadedRules - Map of loaded rules
- * @returns {Object} Contains rule warnings
+ * @returns {Array<Object>} Contains rule warnings
  * @private
  */
-function createRuleWarnings(rules, loadedRules) {
-    const ruleWarnings = { usedDeprecatedRules: [] };
-
-    if (rules) {
-        Object.keys(rules).forEach(name => {
-            const loadedRule = loadedRules.get(name);
+function createRuleDeprecationWarnings(usedRules, loadedRules) {
+    const usedDeprecatedRules = [];
 
-            if (loadedRule.meta && loadedRule.meta.deprecated) {
-                const deprecatedRule = { ruleId: name };
-                const replacedBy = lodash.get(loadedRule, "meta.replacedBy", []);
+    usedRules.forEach(name => {
+        const loadedRule = loadedRules.get(name);
 
-                if (replacedBy.every(newRule => lodash.isString(newRule))) {
-                    deprecatedRule.replacedBy = replacedBy;
-                }
+        if (loadedRule && loadedRule.meta && loadedRule.meta.deprecated) {
+            const deprecatedRule = { ruleId: name };
+            const replacedBy = lodash.get(loadedRule, "meta.replacedBy", []);
 
-                ruleWarnings.usedDeprecatedRules.push(deprecatedRule);
+            if (replacedBy.every(newRule => lodash.isString(newRule))) {
+                deprecatedRule.replacedBy = replacedBy;
             }
-        });
-    }
 
-    return ruleWarnings;
+            usedDeprecatedRules.push(deprecatedRule);
+        }
+    });
+
+    return usedDeprecatedRules;
 }
 
 /**
@@ -541,6 +538,7 @@ class CLIEngine {
 
         const startTime = Date.now();
         const fileList = globUtils.listFilesToProcess(patterns, options);
+        const allUsedRules = new Set();
         const results = fileList.map(fileInfo => {
             if (fileInfo.ignored) {
                 return createIgnoreResult(fileInfo.filename, options.cwd);
@@ -564,7 +562,13 @@ class CLIEngine {
 
             debug(`Processing ${fileInfo.filename}`);
 
-            return processFile(fileInfo.filename, configHelper, options, this.linter);
+            const { result, config } = processFile(fileInfo.filename, configHelper, options, this.linter);
+
+            Object.keys(config.rules)
+                .filter(ruleId => ConfigOps.getRuleSeverity(config.rules[ruleId]))
+                .forEach(ruleId => allUsedRules.add(ruleId));
+
+            return result;
         });
 
         if (options.cache) {
@@ -585,7 +589,7 @@ class CLIEngine {
 
         const stats = calculateStatsPerRun(results);
 
-        const ruleWarnings = createRuleWarnings(this.options.rules, this.getRules());
+        const usedDeprecatedRules = createRuleDeprecationWarnings(allUsedRules, this.getRules());
 
         debug(`Linting complete in: ${Date.now() - startTime}ms`);
 
@@ -595,7 +599,7 @@ class CLIEngine {
             warningCount: stats.warningCount,
             fixableErrorCount: stats.fixableErrorCount,
             fixableWarningCount: stats.fixableWarningCount,
-            usedDeprecatedRules: ruleWarnings.usedDeprecatedRules
+            usedDeprecatedRules
         };
     }
 
@@ -618,22 +622,28 @@ class CLIEngine {
         const resolvedFilename = filename && !path.isAbsolute(filename)
             ? path.resolve(options.cwd, filename)
             : filename;
+        let usedDeprecatedRules;
 
         if (resolvedFilename && ignoredPaths.contains(resolvedFilename)) {
             if (warnIgnored) {
                 results.push(createIgnoreResult(resolvedFilename, options.cwd));
             }
+            usedDeprecatedRules = [];
         } else {
-            results.push(
-                processText(
-                    text,
-                    configHelper,
-                    resolvedFilename,
-                    options.fix,
-                    options.allowInlineConfig,
-                    options.reportUnusedDisableDirectives,
-                    this.linter
-                )
+            const { result, config } = processText(
+                text,
+                configHelper,
+                resolvedFilename,
+                options.fix,
+                options.allowInlineConfig,
+                options.reportUnusedDisableDirectives,
+                this.linter
+            );
+
+            results.push(result);
+            usedDeprecatedRules = createRuleDeprecationWarnings(
+                Object.keys(config.rules).filter(rule => ConfigOps.getRuleSeverity(config.rules[rule])),
+                this.getRules()
             );
         }
 
@@ -644,7 +654,8 @@ class CLIEngine {
             errorCount: stats.errorCount,
             warningCount: stats.warningCount,
             fixableErrorCount: stats.fixableErrorCount,
-            fixableWarningCount: stats.fixableWarningCount
+            fixableWarningCount: stats.fixableWarningCount,
+            usedDeprecatedRules
         };
     }
 
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index 579b53abc..30444d640 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -53,7 +53,6 @@ rules:
     no-async-promise-executor: "error"
     no-buffer-constructor: "error"
     no-caller: "error"
-    no-catch-shadow: "error"
     no-confusing-arrow: "error"
     no-console: "error"
     no-delete-var: "error"


Test patch:
diff --git a/tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml b/tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml
new file mode 100644
index 000000000..e4ea290db
--- /dev/null
+++ b/tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml
@@ -0,0 +1,2 @@
+rules:
+  indent-legacy: error
diff --git a/tests/lib/cli-engine.js b/tests/lib/cli-engine.js
index 92458b59a..acc093b31 100644
--- a/tests/lib/cli-engine.js
+++ b/tests/lib/cli-engine.js
@@ -299,7 +299,8 @@ describe("CLIEngine", () => {
                 errorCount: 0,
                 warningCount: 0,
                 fixableErrorCount: 0,
-                fixableWarningCount: 0
+                fixableWarningCount: 0,
+                usedDeprecatedRules: []
             });
         });
 
@@ -371,7 +372,8 @@ describe("CLIEngine", () => {
                 errorCount: 1,
                 warningCount: 0,
                 fixableErrorCount: 0,
-                fixableWarningCount: 0
+                fixableWarningCount: 0,
+                usedDeprecatedRules: []
             });
         });
 
@@ -412,7 +414,8 @@ describe("CLIEngine", () => {
                 errorCount: 1,
                 warningCount: 0,
                 fixableErrorCount: 0,
-                fixableWarningCount: 0
+                fixableWarningCount: 0,
+                usedDeprecatedRules: []
             });
         });
 
@@ -453,7 +456,8 @@ describe("CLIEngine", () => {
                 errorCount: 1,
                 warningCount: 0,
                 fixableErrorCount: 0,
-                fixableWarningCount: 0
+                fixableWarningCount: 0,
+                usedDeprecatedRules: []
             });
         });
 
@@ -540,7 +544,8 @@ describe("CLIEngine", () => {
                 errorCount: 1,
                 warningCount: 0,
                 fixableErrorCount: 0,
-                fixableWarningCount: 0
+                fixableWarningCount: 0,
+                usedDeprecatedRules: []
             });
         });
 
@@ -598,6 +603,19 @@ describe("CLIEngine", () => {
                 assert.strictEqual(report.messages[0].message, "OK");
             });
         });
+        it("should warn when deprecated rules are found in a config", () => {
+            engine = new CLIEngine({
+                cwd: originalDir,
+                configFile: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
+            });
+
+            const report = engine.executeOnText("foo");
+
+            assert.deepStrictEqual(
+                report.usedDeprecatedRules,
+                [{ ruleId: "indent-legacy", replacedBy: ["indent"] }]
+            );
+        });
     });
 
     describe("executeOnFiles()", () => {
@@ -1402,6 +1420,20 @@ describe("CLIEngine", () => {
             assert.deepStrictEqual(report.usedDeprecatedRules, []);
         });
 
+        it("should warn when deprecated rules are found in a config", () => {
+            engine = new CLIEngine({
+                cwd: originalDir,
+                configFile: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
+            });
+
+            const report = engine.executeOnFiles(["lib/cli*.js"]);
+
+            assert.deepStrictEqual(
+                report.usedDeprecatedRules,
+                [{ ruleId: "indent-legacy", replacedBy: ["indent"] }]
+            );
+        });
+
         describe("Fix Mode", () => {
 
             it("should return fixed text on multiple files when in fix mode", () => {
@@ -3177,7 +3209,8 @@ describe("CLIEngine", () => {
                     errorCount: 1,
                     warningCount: 0,
                     fixableErrorCount: 0,
-                    fixableWarningCount: 0
+                    fixableWarningCount: 0,
+                    usedDeprecatedRules: []
                 }
             );
         });