Repository: eslint/eslint
Pull request #12330 (2019-09-28 02:59:52)

Chore: add autofix npm script
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[x] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
This adds a `fix` flag to the `lint` task in `Makefile.js` and adds a `fix` npm script as a small convenience for contributors.

**Is there anything you'd like reviewers to focus on?**
Nothing in particular!



kaicataldo: @platinumazure Mind elaborating on what you mean? Not sure I understand. Thanks!
platinumazure: I was just wondering if we wanted to have an environment variable check in that task, where if the task was called from CI, then it should throw an error.

As I type this, I'm thinking not, so go ahead and just ignore what I said.

Patch:
diff --git a/Makefile.js b/Makefile.js
index a01d13bde..d11ca75a0 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -473,12 +473,12 @@ target.all = function() {
     target.test();
 };
 
-target.lint = function() {
+target.lint = function([fix = false] = []) {
     let errors = 0,
         lastReturn;
 
     echo("Validating JavaScript files");
-    lastReturn = exec(`${ESLINT} .`);
+    lastReturn = exec(`${ESLINT}${fix ? "--fix" : ""} .`);
     if (lastReturn.code !== 0) {
         errors++;
     }
diff --git a/README.md b/README.md
index 969547200..c553cc810 100644
--- a/README.md
+++ b/README.md
@@ -120,7 +120,7 @@ Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [confi
 
 ### What ECMAScript versions does ESLint support?
 
-ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, and 2018. You can set your desired ECMAScript syntax (and other settings, like global variables or your target environments) through [configuration](https://eslint.org/docs/user-guide/configuring).
+ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, 2018, and 2019. You can set your desired ECMAScript syntax (and other settings, like global variables or your target environments) through [configuration](https://eslint.org/docs/user-guide/configuring).
 
 ### What about experimental features?
 
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 8f5fd286d..172e79736 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -138,6 +138,8 @@ An environment defines global variables that are predefined. The available envir
 * `commonjs` - CommonJS global variables and CommonJS scoping (use this for browser-only code that uses Browserify/WebPack).
 * `shared-node-browser` - Globals common to both Node.js and Browser.
 * `es6` - enable all ECMAScript 6 features except for modules (this automatically sets the `ecmaVersion` parser option to 6).
+* `es2017` - adds all ECMAScript 2017 globals and automatically sets the `ecmaVersion` parser option to 8.
+* `es2020` - adds all ECMAScript 2020 globals and automatically sets the `ecmaVersion` parser option to 11.
 * `worker` - web workers global variables.
 * `amd` - defines `require()` and `define()` as global variables as per the [amd](https://github.com/amdjs/amdjs-api/wiki/AMD) spec.
 * `mocha` - adds all of the Mocha testing global variables.
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index 7f80887f0..3c67d33da 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -85,8 +85,8 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
  * @property {number} warningCount Number of warnings for the result.
  * @property {number} fixableErrorCount Number of fixable errors for the result.
  * @property {number} fixableWarningCount Number of fixable warnings for the result.
- * @property {string=} [source] The source code of the file that was linted.
- * @property {string=} [output] The source code of the file that was linted, with as many fixes applied as possible.
+ * @property {string} [source] The source code of the file that was linted.
+ * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
  */
 
 /**
@@ -329,7 +329,6 @@ function getRule(ruleId, configArrays) {
 /**
  * Collect used deprecated rules.
  * @param {ConfigArray[]} usedConfigArrays The config arrays which were used.
- * @param {Map<string, Object>} ruleMap The rule definitions which were used (built-ins).
  * @returns {IterableIterator<DeprecatedRuleInfo>} Used deprecated rules.
  */
 function *iterateRuleDeprecationWarnings(usedConfigArrays) {
@@ -530,7 +529,6 @@ class CLIEngine {
     /**
      * Creates a new instance of the core CLI engine.
      * @param {CLIEngineOptions} providedOptions The options for this instance.
-     * @constructor
      */
     constructor(providedOptions) {
         const options = Object.assign(
diff --git a/lib/cli-engine/ignored-paths.js b/lib/cli-engine/ignored-paths.js
index 137d156e9..12dfce066 100644
--- a/lib/cli-engine/ignored-paths.js
+++ b/lib/cli-engine/ignored-paths.js
@@ -78,7 +78,7 @@ function mergeDefaultOptions(options) {
     return Object.assign({}, DEFAULT_OPTIONS, options);
 }
 
-/* eslint-disable valid-jsdoc */
+/* eslint-disable jsdoc/check-param-names, jsdoc/require-param */
 /**
  * Normalize the path separators in a given string.
  * On Windows environment, this replaces `\` by `/`.
@@ -89,7 +89,7 @@ function mergeDefaultOptions(options) {
 const normalizePathSeps = path.sep === "/"
     ? (str => str)
     : ((seps, str) => str.replace(seps, "/")).bind(null, new RegExp(`\\${path.sep}`, "gu"));
-/* eslint-enable valid-jsdoc */
+/* eslint-enable jsdoc/check-param-names, jsdoc/require-param */
 
 /**
  * Converts a glob pattern to a new glob pattern relative to a different directory
@@ -298,7 +298,7 @@ class IgnoredPaths {
 
     /**
      * read ignore filepath
-     * @param {string} filePath, file to add to ig
+     * @param {string} filePath file to add to ig
      * @returns {Array} raw ignore rules
      */
     readIgnoreFile(filePath) {
diff --git a/lib/cli-engine/lint-result-cache.js b/lib/cli-engine/lint-result-cache.js
index 9408780fb..14e19d9e5 100644
--- a/lib/cli-engine/lint-result-cache.js
+++ b/lib/cli-engine/lint-result-cache.js
@@ -47,7 +47,6 @@ class LintResultCache {
 
     /**
      * Creates a new LintResultCache instance.
-     * @constructor
      * @param {string} cacheFileLocation The cache file location.
      *   configuration lookup by file path).
      */
diff --git a/lib/init/config-rule.js b/lib/init/config-rule.js
index fbe9b779a..e40feb714 100644
--- a/lib/init/config-rule.js
+++ b/lib/init/config-rule.js
@@ -99,7 +99,7 @@ function groupByProperty(objects) {
  * Configs may also have one or more additional elements to specify rule
  * configuration or options.
  *
- * @typedef {array|number} ruleConfig
+ * @typedef {Array|number} ruleConfig
  * @param {number}  0  The rule's severity (0, 1, 2).
  */
 
@@ -185,7 +185,7 @@ class RuleConfigSet {
 
         /**
          * Stored valid rule configurations for this instance
-         * @type {array}
+         * @type {Array}
          */
         this.ruleConfigs = configs || [];
     }
diff --git a/lib/init/npm-utils.js b/lib/init/npm-utils.js
index 7fe7c6e7d..3d4a896b6 100644
--- a/lib/init/npm-utils.js
+++ b/lib/init/npm-utils.js
@@ -163,7 +163,7 @@ function checkDevDeps(packages) {
 /**
  * Check whether package.json is found in current path.
  *
- * @param   {string=} startDir Starting directory
+ * @param   {string} [startDir] Starting directory
  * @returns {boolean} Whether a package.json is found in current path.
  */
 function checkPackageJson(startDir) {
diff --git a/lib/linter/code-path-analysis/debug-helpers.js b/lib/linter/code-path-analysis/debug-helpers.js
index 9af985ce8..2ca6dbc1e 100644
--- a/lib/linter/code-path-analysis/debug-helpers.js
+++ b/lib/linter/code-path-analysis/debug-helpers.js
@@ -21,7 +21,7 @@ const debug = require("debug")("eslint:code-path");
  * @returns {string} Id of the segment.
  */
 /* istanbul ignore next */
-function getId(segment) { // eslint-disable-line require-jsdoc
+function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc
     return segment.id + (segment.reachable ? "" : "!");
 }
 
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index 7d1dc8c8c..534181da9 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -472,7 +472,6 @@ function normalizeFilename(filename) {
     return index === -1 ? filename : parts.slice(index).join(path.sep);
 }
 
-// eslint-disable-next-line valid-jsdoc
 /**
  * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
  * consistent shape.
diff --git a/lib/rules/indent-legacy.js b/lib/rules/indent-legacy.js
index fb84b732e..f1c024c36 100644
--- a/lib/rules/indent-legacy.js
+++ b/lib/rules/indent-legacy.js
@@ -303,7 +303,7 @@ module.exports = {
          * @param {int} needed Expected indentation character count
          * @param {int} gottenSpaces Indentation space count in the actual node/code
          * @param {int} gottenTabs Indentation tab count in the actual node/code
-         * @param {Object=} loc Error line and column location
+         * @param {Object} [loc] Error line and column location
          * @param {boolean} isLastNodeCheck Is the error for last node check
          * @returns {void}
          */
diff --git a/lib/rules/no-useless-rename.js b/lib/rules/no-useless-rename.js
index c1860645e..4ff65d4b8 100644
--- a/lib/rules/no-useless-rename.js
+++ b/lib/rules/no-useless-rename.js
@@ -41,6 +41,8 @@ module.exports = {
             ignoreImport = options.ignoreImport === true,
             ignoreExport = options.ignoreExport === true;
 
+        const sourceCode = context.getSourceCode();
+
         //--------------------------------------------------------------------------
         // Helpers
         //--------------------------------------------------------------------------
@@ -64,6 +66,9 @@ module.exports = {
                     type
                 },
                 fix(fixer) {
+                    if (sourceCode.commentsExistBetween(initial, result)) {
+                        return null;
+                    }
                     return fixer.replaceTextRange([
                         initial.range[0],
                         result.range[1]
diff --git a/lib/shared/logging.js b/lib/shared/logging.js
index 3eb898c34..6aa1f5a1e 100644
--- a/lib/shared/logging.js
+++ b/lib/shared/logging.js
@@ -12,6 +12,7 @@ module.exports = {
 
     /**
      * Cover for console.log
+     * @param {...any} args The elements to log.
      * @returns {void}
      */
     info(...args) {
@@ -20,6 +21,7 @@ module.exports = {
 
     /**
      * Cover for console.error
+     * @param {...any} args The elements to log.
      * @returns {void}
      */
     error(...args) {
diff --git a/lib/source-code/source-code.js b/lib/source-code/source-code.js
index 88a9c0a4e..42e7b0c2f 100644
--- a/lib/source-code/source-code.js
+++ b/lib/source-code/source-code.js
@@ -93,7 +93,6 @@ class SourceCode extends TokenStore {
      * @param {ScopeManager|null} textOrConfig.scopeManager - The scope of this source code.
      * @param {Object|null} textOrConfig.visitorKeys - The visitor keys to traverse AST.
      * @param {ASTNode} [astIfNoConfig] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
-     * @constructor
      */
     constructor(textOrConfig, astIfNoConfig) {
         let text, ast, parserServices, scopeManager, visitorKeys;
@@ -206,9 +205,9 @@ class SourceCode extends TokenStore {
 
     /**
      * Gets the source code for the given node.
-     * @param {ASTNode=} node The AST node to get the text for.
-     * @param {int=} beforeCount The number of characters before the node to retrieve.
-     * @param {int=} afterCount The number of characters after the node to retrieve.
+     * @param {ASTNode} [node] The AST node to get the text for.
+     * @param {int} [beforeCount] The number of characters before the node to retrieve.
+     * @param {int} [afterCount] The number of characters after the node to retrieve.
      * @returns {string} The text representing the AST node.
      * @public
      */
diff --git a/package.json b/package.json
index 9ce1c59b0..e1fb731c1 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
   "scripts": {
     "test": "node Makefile.js test",
     "lint": "node Makefile.js lint",
+    "fix": "node Makefile.js lint -- fix",
     "fuzz": "node Makefile.js fuzz",
     "generate-release": "node Makefile.js generateRelease",
     "generate-alpharelease": "node Makefile.js generatePrerelease -- alpha",
@@ -96,6 +97,7 @@
     "eslint-config-eslint": "file:packages/eslint-config-eslint",
     "eslint-plugin-eslint-plugin": "^2.0.1",
     "eslint-plugin-internal-rules": "file:tools/internal-rules",
+    "eslint-plugin-jsdoc": "^15.9.5",
     "eslint-plugin-node": "^9.0.0",
     "eslint-release": "^1.2.0",
     "eslump": "^2.0.0",
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index 526ce5600..1bbc1c576 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -1,6 +1,16 @@
 extends:
     - "eslint:recommended"
     - "plugin:node/recommended"
+plugins:
+    - "jsdoc"
+settings:
+    jsdoc:
+        tagNamePreference:
+            file: "fileoverview"
+            augments: "extends"
+            class: "constructor"
+        preferredTypes:
+            object: "Object"
 rules:
     array-bracket-spacing: "error"
     array-callback-return: "error"
@@ -31,6 +41,20 @@ rules:
     generator-star-spacing: "error"
     guard-for-in: "error"
     handle-callback-err: ["error", "err"]
+    jsdoc/check-alignment: "error"
+    jsdoc/check-param-names: "error"
+    jsdoc/check-syntax: "error"
+    jsdoc/check-tag-names: "error"
+    jsdoc/check-types: "error"
+    jsdoc/implements-on-classes: "error"
+    jsdoc/require-jsdoc: "error"
+    jsdoc/require-param: "error"
+    jsdoc/require-param-description: "error"
+    jsdoc/require-param-name: "error"
+    jsdoc/require-param-type: "error"
+    jsdoc/require-returns: ["error", { forceRequireReturn: true, forceReturnsWithAsync: true }]
+    jsdoc/require-returns-description: "error"
+    jsdoc/require-returns-type: "error"
     key-spacing: ["error", { beforeColon: false, afterColon: true }]
     keyword-spacing: "error"
     lines-around-comment: ["error", {
@@ -154,7 +178,6 @@ rules:
     quotes: ["error", "double", {avoidEscape: true}]
     quote-props: ["error", "as-needed"]
     radix: "error"
-    require-jsdoc: "error"
     require-unicode-regexp: "error"
     rest-spread-spacing: "error"
     semi: "error"
@@ -172,17 +195,6 @@ rules:
     template-curly-spacing: ["error", "never"]
     template-tag-spacing: "error"
     unicode-bom: "error"
-    valid-jsdoc: ["error", {
-        prefer: { "return": "returns"},
-        preferType: {
-            "String": "string",
-            "Number": "number",
-            "Boolean": "boolean",
-            "array": "Array",
-            "object": "Object",
-            "function": "Function"
-        }
-    }]
     wrap-iife: "error"
     yield-star-spacing: "error"
     yoda: ["error", "never"]
diff --git a/packages/eslint-config-eslint/package.json b/packages/eslint-config-eslint/package.json
index 514dbb7ca..48bfb65f5 100644
--- a/packages/eslint-config-eslint/package.json
+++ b/packages/eslint-config-eslint/package.json
@@ -20,6 +20,7 @@
   "homepage": "https://eslint.org",
   "bugs": "https://github.com/eslint/eslint/issues/",
   "peerDependencies": {
+    "eslint-plugin-jsdoc": "^15.9.5",
     "eslint-plugin-node": "^9.0.0"
   },
   "keywords": [
diff --git a/tools/code-sample-minimizer.js b/tools/code-sample-minimizer.js
index 63a687e56..2954bf08f 100644
--- a/tools/code-sample-minimizer.js
+++ b/tools/code-sample-minimizer.js
@@ -30,6 +30,7 @@ function isStatement(node) {
  * Given "bad" source text (e.g. an code sample that causes a rule to crash), tries to return a smaller
  * piece of source text which is also "bad", to make it easier for a human to figure out where the
  * problem is.
+ * @param {Object} options Options to process
  * @param {string} options.sourceText Initial piece of "bad" source text
  * @param {function(string): boolean} options.predicate A predicate that returns `true` for bad source text and `false` for good source text
  * @param {Parser} [options.parser] The parser used to parse the source text. Defaults to a modified
diff --git a/tools/internal-rules/no-invalid-meta.js b/tools/internal-rules/no-invalid-meta.js
index aeb7862fa..016643a8d 100644
--- a/tools/internal-rules/no-invalid-meta.js
+++ b/tools/internal-rules/no-invalid-meta.js
@@ -104,7 +104,6 @@ function hasMetaSchema(metaPropertyNode) {
  *
  * @param {RuleContext} context The ESLint rule context.
  * @param {ASTNode} exportsNode ObjectExpression node that the rule exports.
- * @param {boolean} ruleIsFixable whether the rule is fixable or not.
  * @returns {void}
  */
 function checkMetaValidity(context, exportsNode) {


Test patch:
diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js
index 0d1319c11..83b91c45d 100644
--- a/lib/rule-tester/rule-tester.js
+++ b/lib/rule-tester/rule-tester.js
@@ -177,7 +177,6 @@ class RuleTester {
     /**
      * Creates a new instance of RuleTester.
      * @param {Object} [testerConfig] Optional, extra configuration for the tester
-     * @constructor
      */
     constructor(testerConfig) {
 
diff --git a/tests/lib/_utils.js b/tests/lib/_utils.js
index 3251a6023..2ac119fb7 100644
--- a/tests/lib/_utils.js
+++ b/tests/lib/_utils.js
@@ -25,7 +25,6 @@ function unIndent(strings, ...values) {
     return lines.map(line => line.slice(minLineIndent)).join("\n");
 }
 
-// eslint-disable-next-line valid-jsdoc
 /**
  * Add support of `recursive` option.
  * @param {import("fs")} fs The in-memory file system.
@@ -56,7 +55,6 @@ function supportMkdirRecursiveOption(fs, cwd) {
     };
 }
 
-// eslint-disable-next-line valid-jsdoc
 /**
  * Define in-memory file system.
  * @param {Object} options The options.
diff --git a/tests/lib/cli-engine/_utils.js b/tests/lib/cli-engine/_utils.js
index a3c56484c..bff1801f3 100644
--- a/tests/lib/cli-engine/_utils.js
+++ b/tests/lib/cli-engine/_utils.js
@@ -53,9 +53,6 @@
  */
 "use strict";
 
-// To use TypeScript type annotations for VSCode intellisense.
-/* eslint-disable valid-jsdoc */
-
 const path = require("path");
 const vm = require("vm");
 const Proxyquire = require("proxyquire/lib/proxyquire");
diff --git a/tests/lib/cli-engine/cascading-config-array-factory.js b/tests/lib/cli-engine/cascading-config-array-factory.js
index e0ca4f063..22c9b956d 100644
--- a/tests/lib/cli-engine/cascading-config-array-factory.js
+++ b/tests/lib/cli-engine/cascading-config-array-factory.js
@@ -85,6 +85,7 @@ describe("CascadingConfigArrayFactory", () => {
 
             /**
              * Returns the path inside of the fixture directory.
+             * @param {...string} args file path segments.
              * @returns {string} The path inside the fixture directory.
              * @private
              */
@@ -671,6 +672,7 @@ describe("CascadingConfigArrayFactory", () => {
 
                 /**
                  * Returns the path inside of the fixture directory.
+                 * @param {...string} args file path segments.
                  * @returns {string} The path inside the fixture directory.
                  * @private
                  */
@@ -766,6 +768,7 @@ describe("CascadingConfigArrayFactory", () => {
 
                 /**
                  * Returns the path inside of the fixture directory.
+                 * @param {...string} args file path segments.
                  * @returns {string} The path inside the fixture directory.
                  * @private
                  */
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index b3039e743..223cb6607 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -50,6 +50,7 @@ describe("CLIEngine", () => {
 
     /**
      * Returns the path inside of the fixture directory.
+     * @param {...string} args file path segments.
      * @returns {string} The path inside the fixture directory.
      * @private
      */
@@ -1543,7 +1544,11 @@ describe("CLIEngine", () => {
             engine = new CLIEngine({
                 cwd: originalDir,
                 configFile: ".eslintrc.js",
-                rules: { "indent-legacy": 1 }
+                rules: {
+                    "indent-legacy": 1,
+                    "require-jsdoc": 1,
+                    "valid-jsdoc": 1
+                }
             });
 
             const report = engine.executeOnFiles(["lib/cli*.js"]);
diff --git a/tests/lib/cli-engine/file-enumerator.js b/tests/lib/cli-engine/file-enumerator.js
index 13ff479db..d379ac520 100644
--- a/tests/lib/cli-engine/file-enumerator.js
+++ b/tests/lib/cli-engine/file-enumerator.js
@@ -173,6 +173,7 @@ describe("FileEnumerator", () => {
 
             /**
              * Returns the path inside of the fixture directory.
+             * @param {...string} args file path segments.
              * @returns {string} The path inside the fixture directory.
              * @private
              */
diff --git a/tests/lib/cli-engine/ignored-paths.js b/tests/lib/cli-engine/ignored-paths.js
index 487024427..7fd8e8408 100644
--- a/tests/lib/cli-engine/ignored-paths.js
+++ b/tests/lib/cli-engine/ignored-paths.js
@@ -92,6 +92,7 @@ function countDefaultPatterns(ignoredPaths) {
 
 /**
  * Returns the path inside of the fixture directory.
+ * @param {...string} args file path segments.
  * @returns {string} The path inside the fixture directory.
  * @private
  */
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index 1b98fb137..e0f10d5ae 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -71,6 +71,7 @@ describe("cli", () => {
 
     /**
      * Returns the path inside of the fixture directory.
+     * @param {...string} args file path segments.
      * @returns {string} The path inside the fixture directory.
      * @private
      */
diff --git a/tests/lib/init/config-initializer.js b/tests/lib/init/config-initializer.js
index ed2388fd5..3393ae2be 100644
--- a/tests/lib/init/config-initializer.js
+++ b/tests/lib/init/config-initializer.js
@@ -57,6 +57,7 @@ describe("configInitializer", () => {
 
     /**
      * Returns the path inside of the fixture directory.
+     * @param {...string} args file path segments.
      * @returns {string} The path inside the fixture directory.
      * @private
      */
diff --git a/tests/lib/init/source-code-utils.js b/tests/lib/init/source-code-utils.js
index a5c9e90a1..8c821de78 100644
--- a/tests/lib/init/source-code-utils.js
+++ b/tests/lib/init/source-code-utils.js
@@ -31,6 +31,7 @@ describe("SourceCodeUtil", () => {
 
     /**
      * Returns the path inside of the fixture directory.
+     * @param {...string} args file path segments.
      * @returns {string} The path inside the fixture directory.
      * @private
      */
diff --git a/tests/lib/rules/no-useless-rename.js b/tests/lib/rules/no-useless-rename.js
index 1fcc843db..58796c625 100644
--- a/tests/lib/rules/no-useless-rename.js
+++ b/tests/lib/rules/no-useless-rename.js
@@ -299,6 +299,133 @@ ruleTester.run("no-useless-rename", rule, {
             code: "export {foo as foo, bar as bar} from 'foo';",
             output: "export {foo, bar} from 'foo';",
             errors: ["Export foo unnecessarily renamed.", "Export bar unnecessarily renamed."]
+        },
+
+        // Should not autofix if it would remove comments
+        {
+            code: "({/* comment */foo: foo} = {});",
+            output: "({/* comment */foo} = {});",
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo, /* comment */bar: bar} = {});",
+            output: "({foo, /* comment */bar} = {});",
+            errors: ["Destructuring assignment bar unnecessarily renamed."]
+        },
+        {
+            code: "({foo/**/ : foo} = {});",
+            output: null,
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo /**/: foo} = {});",
+            output: null,
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo://\nfoo} = {});",
+            output: null,
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo: /**/foo} = {});",
+            output: null,
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo: foo/* comment */} = {});",
+            output: "({foo/* comment */} = {});",
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "({foo: foo//comment\n,bar} = {});",
+            output: "({foo//comment\n,bar} = {});",
+            errors: ["Destructuring assignment foo unnecessarily renamed."]
+        },
+        {
+            code: "import {/* comment */foo as foo} from 'foo';",
+            output: "import {/* comment */foo} from 'foo';",
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo,/* comment */bar as bar} from 'foo';",
+            output: "import {foo,/* comment */bar} from 'foo';",
+            errors: ["Import bar unnecessarily renamed."]
+        },
+        {
+            code: "import {foo/**/ as foo} from 'foo';",
+            output: null,
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo /**/as foo} from 'foo';",
+            output: null,
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo //\nas foo} from 'foo';",
+            output: null,
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo as/**/foo} from 'foo';",
+            output: null,
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo as foo/* comment */} from 'foo';",
+            output: "import {foo/* comment */} from 'foo';",
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "import {foo as foo/* comment */,bar} from 'foo';",
+            output: "import {foo/* comment */,bar} from 'foo';",
+            errors: ["Import foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {/* comment */foo as foo};",
+            output: "let foo; export {/* comment */foo};",
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo, bar; export {foo,/* comment */bar as bar};",
+            output: "let foo, bar; export {foo,/* comment */bar};",
+            errors: ["Export bar unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {foo/**/as foo};",
+            output: null,
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {foo as/**/ foo};",
+            output: null,
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {foo as /**/foo};",
+            output: null,
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {foo as//comment\n foo};",
+            output: null,
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo; export {foo as foo/* comment*/};",
+            output: "let foo; export {foo/* comment*/};",
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo, bar; export {foo as foo/* comment*/,bar};",
+            output: "let foo, bar; export {foo/* comment*/,bar};",
+            errors: ["Export foo unnecessarily renamed."]
+        },
+        {
+            code: "let foo, bar; export {foo as foo//comment\n,bar};",
+            output: "let foo, bar; export {foo//comment\n,bar};",
+            errors: ["Export foo unnecessarily renamed."]
         }
     ]
 });
diff --git a/tests/tools/loose-parser.js b/tests/tools/loose-parser.js
index abb3aeb5b..98e97cc36 100644
--- a/tests/tools/loose-parser.js
+++ b/tests/tools/loose-parser.js
@@ -9,7 +9,6 @@
 const acorn = require("acorn");
 const espree = require("espree/lib/espree");
 
-// eslint-disable-next-line valid-jsdoc
 /**
  * Define the parser which ignores recoverable errors.
  * @returns {(parser:acorn.Parser) => acorn.Parser} The function that defines loose parser.