Repository: eslint/eslint
Pull request #12602 (2019-11-25 19:15:18)

Update: improve suggestion testing experience
Previously you had to explicitly set `suggestions: undefined`, or omit the property.
I hate writing `undefined` in my code, but I also prefer to be explicit in my tests, and explicitly say "I expect no suggestions".

This just lets a user pass any falsey value, or an empty array.
The rule tester will interpret any of these values as "I expect no suggestions".

I.e. these will now be equivalent:
```js
ruleTester.run("suggestions-basic", rule, {
  valid: [],
  invalid: [
    // previously only allowed:
    {},
    {
      suggestions: undefined,
    },
    // now also allows
    {
      suggestions: [],
    },
    {
      suggestions: null,
    },
    {
      suggestions: false,
    },
  ],
});
```

kaicataldo: This seems like a good idea to me. I'll champion this.

Patch:
diff --git a/.azure-pipelines/job.yml b/.azure-pipelines/job.yml
deleted file mode 100644
index 2f8a55373..000000000
--- a/.azure-pipelines/job.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-parameters:
-  name: ""
-  displayName: ""
-  vmImage: ""
-  nodeVersion: ""
-
-jobs:
-  - job: ${{parameters.name}}
-    displayName: ${{parameters.displayName}}
-    pool:
-      vmImage: ${{parameters.vmImage}}
-    steps:
-      - task: NodeTool@0
-        displayName: Install Node.js
-        inputs:
-          versionSpec: ${{parameters.nodeVersion}}
-
-      - script: npm install
-        displayName: Install Packages
-
-      - script: npm test
-        displayName: Test
-
-      - task: PublishTestResults@2
-        displayName: Process Test Results
-        condition: succeededOrFailed()
-        inputs:
-          testRunner: JUnit
-          testResultsFiles: $(System.DefaultWorkingDirectory)/test-results.xml
-
-      - task: PublishCodeCoverageResults@1
-        displayName: Process Coverage Results
-        condition: succeededOrFailed()
-        inputs: 
-          codeCoverageTool: Cobertura
-          summaryFileLocation: $(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml
-          reportDirectory: $(System.DefaultWorkingDirectory)/coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d46edfd5d..d02601b7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+v6.7.2 - November 30, 2019
+
+* [`bc435a9`](https://github.com/eslint/eslint/commit/bc435a93afd6ba4def1b53993ef7cf8220f3f070) Fix: isSpaceBetweenTokens() recognizes spaces in JSXText (fixes #12614) (#12616) (Toru Nagashima)
+* [`4928d51`](https://github.com/eslint/eslint/commit/4928d513b4fe716c7ed958c294a10ef8517be25e) Fix: don't ignore the entry directory (fixes #12604) (#12607) (Toru Nagashima)
+* [`b41677a`](https://github.com/eslint/eslint/commit/b41677ae2a143790b19b0e70391a46ec6c8f5de1) Docs: Clarify suggestion's data in Working with Rules (refs #12606) (#12617) (Milos Djermanovic)
+* [`ea16de4`](https://github.com/eslint/eslint/commit/ea16de4e7c6f661398b0b7843f95e5f307c89551) Fix: Support tagged template literal generics in no-unexpected-multiline (#11698) (Brad Zacher)
+* [`fa6415d`](https://github.com/eslint/eslint/commit/fa6415d5b877370374a6a530a5190ab5a411b4dc) Sponsors: Sync README with website (ESLint Jenkins)
+* [`e1e158b`](https://github.com/eslint/eslint/commit/e1e158b4d7bd61e812723b378d2c391295da43a5) Sponsors: Sync README with website (ESLint Jenkins)
+
 v6.7.1 - November 24, 2019
 
 * [`dd1e9f4`](https://github.com/eslint/eslint/commit/dd1e9f4df2103c43509a54b0ad5f9106557997f9) Fix: revert changes to key-spacing due to regression (#12598) (Kai Cataldo)
diff --git a/Makefile.js b/Makefile.js
index 1b241c1ae..2dc8547f3 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -560,7 +560,7 @@ target.mocha = () => {
 target.karma = () => {
     echo("Running unit tests on browsers");
 
-    target.webpack();
+    target.webpack("production");
 
     const browserFileLintOutput = new CLIEngine({
         useEslintrc: false,
@@ -775,17 +775,7 @@ target.gensite = function(prereleaseVersion) {
     echo("> Removing the temporary directory (Step 12)");
     rm("-rf", TEMP_DIR);
 
-    // 13. Update demos, but only for non-prereleases
-    if (!prereleaseVersion) {
-        echo("> Updating the demos (Step 13)");
-        target.webpack("production");
-        cp("-f", "build/eslint.js", `${SITE_DIR}src/js/eslint.js`);
-        cp("-f", "build/espree.js", `${SITE_DIR}src/js/espree.js`);
-    } else {
-        echo("> Skipped updating the demos (Step 13)");
-    }
-
-    // 14. Create Example Formatter Output Page
+    // 13. Create Example Formatter Output Page
     echo("> Creating the formatter examples (Step 14)");
     generateFormatterExamples(getFormatterResults(), prereleaseVersion);
 
diff --git a/README.md b/README.md
index b7cc385f0..0cde09fc6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
 [![NPM version][npm-image]][npm-url]
-[![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master)
 [![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
 [![Downloads][downloads-image]][downloads-url]
 [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
@@ -265,7 +264,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <h3>Gold Sponsors</h3>
 <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
+<p><a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 13a2f38c4..000000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-trigger:
-  - master
-
-jobs:
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node12
-      displayName: Test on Node.js 12 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 12.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node10
-      displayName: Test on Node.js 10 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 10.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node8
-      displayName: Test on Node.js 8 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 8.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_windows_node12
-      displayName: Test on Node.js 12 (Windows)
-      vmImage: Windows-2019
-      nodeVersion: 12.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_macos_node12
-      displayName: Test on Node.js 12 (macOS)
-      vmImage: macOS-10.14
-      nodeVersion: 12.x
diff --git a/conf/config-schema.js b/conf/config-schema.js
index 83addff87..712fc4235 100644
--- a/conf/config-schema.js
+++ b/conf/config-schema.js
@@ -6,6 +6,7 @@
 "use strict";
 
 const baseConfigProperties = {
+    $schema: { type: "string" },
     env: { type: "object" },
     extends: { $ref: "#/definitions/stringOrStrings" },
     globals: { type: "object" },
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 7cc6e0165..e915ec449 100644
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -62,7 +62,6 @@ module.exports = {
         "no-useless-catch": "error",
         "no-useless-escape": "error",
         "no-with": "error",
-        "require-atomic-updates": "error",
         "require-yield": "error",
         "use-isnan": "error",
         "valid-typeof": "error"
diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md
index 945061f1f..deac450b0 100644
--- a/docs/developer-guide/working-with-rules.md
+++ b/docs/developer-guide/working-with-rules.md
@@ -352,6 +352,7 @@ In some cases fixes aren't appropriate to be automatically applied, for example,
 In order to provide suggestions, use the `suggest` key in the report argument with an array of suggestion objects. The suggestion objects represent individual suggestions that could be applied and require either a `desc` key string that describes what applying the suggestion would do or a `messageId` key (see [below](#suggestion-messageids)), and a `fix` key that is a function defining the suggestion result. This `fix` function follows the same API as regular fixes (described above in [applying fixes](#applying-fixes)).
 
 ```js
+{% raw %}
 context.report({
     node: node,
     message: "Unnecessary escape character: \\{{character}}.",
@@ -371,6 +372,7 @@ context.report({
         }
     ]
 });
+{% endraw %}
 ```
 
 Note: Suggestions will be applied as a stand-alone change, without triggering multipass fixes. Each suggestion should focus on a singular change in the code and should not try to conform to user defined styles. For example, if a suggestion is adding a new statement into the codebase, it should not try to match correct indentation, or confirm to user preferences on presence/absence of semicolumns. All of those things can be corrected by multipass autofix when the user triggers it.
@@ -385,6 +387,7 @@ Best practices for suggestions:
 Instead of using a `desc` key for suggestions a `messageId` can be used instead. This works the same way as `messageId`s for the overall error (see [messageIds](#messageIds)). Here is an example of how to use it in a rule:
 
 ```js
+{% raw %}
 module.exports = {
     meta: {
         messages: {
@@ -416,6 +419,43 @@ module.exports = {
         });
     }
 };
+{% endraw %}
+```
+
+#### Placeholders in suggestion messages
+
+You can also use placeholders in the suggestion message. This works the same way as placeholders for the overall error (see [using message placeholders](#using-message-placeholders)).
+
+Please note that you have to provide `data` on the suggestion's object. Suggestion messages cannot use properties from the overall error's `data`.
+
+```js
+{% raw %}
+module.exports = {
+    meta: {
+        messages: {
+            unnecessaryEscape: "Unnecessary escape character: \\{{character}}.",
+            removeEscape: "Remove `\\` before {{character}}.",
+        }
+    },
+    create: function(context) {
+        // ...
+        context.report({
+            node: node,
+            messageId: "unnecessaryEscape",
+            data: { character }, // data for the unnecessaryEscape overall message
+            suggest: [
+                {
+                    messageId: "removeEscape",
+                    data: { character }, // data for the removeEscape suggestion message
+                    fix: function(fixer) {
+                        return fixer.removeRange(range);
+                    }
+                }
+            ]
+        });
+    }
+};
+{% endraw %}
 ```
 
 ### context.options
diff --git a/docs/rules/brace-style.md b/docs/rules/brace-style.md
index 37098b1cd..dce2d9649 100644
--- a/docs/rules/brace-style.md
+++ b/docs/rules/brace-style.md
@@ -129,6 +129,27 @@ if (foo) { bar(); }
 if (foo) { bar(); } else { baz(); }
 
 try { somethingRisky(); } catch(e) { handleError(); }
+
+if (foo) { baz(); } else {
+  boom();
+}
+
+if (foo) { baz(); } else if (bar) {
+  boom();
+}
+
+if (foo) { baz(); } else
+if (bar) {
+  boom();
+}
+
+if (foo) { baz); } else if (bar) {
+  boom();
+}
+
+try { somethingRisky(); } catch(e) {
+  handleError();
+}
 ```
 
 ### stroustrup
diff --git a/docs/rules/comma-style.md b/docs/rules/comma-style.md
index 2a55dbf58..24b551574 100644
--- a/docs/rules/comma-style.md
+++ b/docs/rules/comma-style.md
@@ -39,7 +39,7 @@ This rule also accepts an additional `exceptions` object:
     * `"VariableDeclaration": true` ignores comma style in variable declarations
     * `"NewExpression": true` ignores comma style in the parameters of constructor expressions
 
-A way to determine the node types as defined by [ESTree](https://github.com/estree/estree) is to use the [online demo](https://eslint.org/parser).
+A way to determine the node types as defined by [ESTree](https://github.com/estree/estree) is to use [AST Explorer](https://astexplorer.net/) with the espree parser.
 
 ### last
 
diff --git a/docs/rules/func-style.md b/docs/rules/func-style.md
index 14f01b0c4..e17fecf8f 100644
--- a/docs/rules/func-style.md
+++ b/docs/rules/func-style.md
@@ -77,6 +77,8 @@ Examples of **correct** code for this rule with the default `"expression"` optio
 var foo = function() {
     // ...
 };
+
+var foo = () => {};
 ```
 
 ### declaration
diff --git a/docs/rules/no-console.md b/docs/rules/no-console.md
index bc163b937..f2fb79ec4 100644
--- a/docs/rules/no-console.md
+++ b/docs/rules/no-console.md
@@ -14,7 +14,7 @@ This rule disallows calls to methods of the `console` object.
 Examples of **incorrect** code for this rule:
 
 ```js
-/*eslint no-console: "error"*/
+/* eslint no-console: "error" */
 
 console.log("Log a debug level message.");
 console.warn("Log a warn level message.");
@@ -24,7 +24,7 @@ console.error("Log an error level message.");
 Examples of **correct** code for this rule:
 
 ```js
-/*eslint no-console: "error"*/
+/* eslint no-console: "error" */
 
 // custom console
 Console.log("Hello world!");
@@ -39,7 +39,7 @@ This rule has an object option for exceptions:
 Examples of additional **correct** code for this rule with a sample `{ "allow": ["warn", "error"] }` option:
 
 ```js
-/*eslint no-console: ["error", { allow: ["warn", "error"] }] */
+/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
 
 console.warn("Log a warn level message.");
 console.error("Log an error level message.");
@@ -52,7 +52,7 @@ If you're using Node.js, however, `console` is used to output information to the
 Another case where you might not use this rule is if you want to enforce console calls and not console overwrites. For example:
 
 ```js
-/*eslint no-console: ["error", { allow: ["warn"] }] */
+/* eslint no-console: ["error", { allow: ["warn"] }] */
 console.error = function (message) {
   throw new Error(message);
 };
diff --git a/docs/rules/no-multi-assign.md b/docs/rules/no-multi-assign.md
index 2da09ba07..41bba9ad6 100644
--- a/docs/rules/no-multi-assign.md
+++ b/docs/rules/no-multi-assign.md
@@ -3,7 +3,11 @@
 Chaining the assignment of variables can lead to unexpected results and be difficult to read.
 
 ```js
-a = b = c = d;
+(function() {
+    const foo = bar = 0; // Did you mean `foo = bar == 0`?
+    bar = 1;             // This will not fail since `bar` is not constant.
+})();
+console.log(bar);        // This will output 1 since `bar` is not scoped.
 ```
 
 ## Rule Details
@@ -17,9 +21,9 @@ Examples of **incorrect** code for this rule:
 
 var a = b = c = 5;
 
-var foo = bar = "baz";
+const foo = bar = "baz";
 
-var a =
+let a =
     b =
     c;
 ```
@@ -32,11 +36,11 @@ var a = 5;
 var b = 5;
 var c = 5;
 
-var foo = "baz";
-var bar = "baz";
+const foo = "baz";
+const bar = "baz";
 
-var a = c;
-var b = c;
+let a = c;
+let b = c;
 ```
 
 ## Related Rules
diff --git a/docs/rules/no-multi-spaces.md b/docs/rules/no-multi-spaces.md
index 07cd0e901..c4b12e938 100644
--- a/docs/rules/no-multi-spaces.md
+++ b/docs/rules/no-multi-spaces.md
@@ -102,7 +102,7 @@ var x = 5;      /* multiline
 
 To avoid contradictions with other rules that require multiple spaces, this rule has an `exceptions` option to ignore certain nodes.
 
-This option is an object that expects property names to be AST node types as defined by [ESTree](https://github.com/estree/estree). The easiest way to determine the node types for `exceptions` is to use the [online demo](https://eslint.org/parser).
+This option is an object that expects property names to be AST node types as defined by [ESTree](https://github.com/estree/estree). The easiest way to determine the node types for `exceptions` is to use [AST Explorer](https://astexplorer.net/) with the espree parser.
 
 Only the `Property` node type is ignored by default, because for the [key-spacing](key-spacing.md) rule some alignment options require multiple spaces in properties of object literals.
 
diff --git a/docs/rules/no-restricted-imports.md b/docs/rules/no-restricted-imports.md
index 62747ebce..e86544d2e 100644
--- a/docs/rules/no-restricted-imports.md
+++ b/docs/rules/no-restricted-imports.md
@@ -38,20 +38,26 @@ When using the object form, you can also specify an array of gitignore-style pat
 You may also specify a custom message for any paths you want to restrict as follows:
 
 ```json
-"no-restricted-imports": ["error", [{
-  "name": "import-foo",
-  "message": "Please use import-bar instead."
-}]]
+"no-restricted-imports": ["error", {
+    "name": "import-foo",
+    "message": "Please use import-bar instead."
+}, {
+    "name": "import-baz",
+    "message": "Please use import-quux instead."
+}]
 ```
 
 or like this:
 
 ```json
 "no-restricted-imports": ["error", {
-  "paths": [{
-    "name": "import-foo",
-    "message": "Please use import-bar instead."
-  }]
+    "paths": [{
+        "name": "import-foo",
+        "message": "Please use import-bar instead."
+    }, {
+        "name": "import-baz",
+        "message": "Please use import-quux instead."
+    }]
 }]
 ```
 
diff --git a/docs/rules/no-restricted-syntax.md b/docs/rules/no-restricted-syntax.md
index 37dbe8f01..066516721 100644
--- a/docs/rules/no-restricted-syntax.md
+++ b/docs/rules/no-restricted-syntax.md
@@ -2,7 +2,7 @@
 
 JavaScript has a lot of language features, and not everyone likes all of them. As a result, some projects choose to disallow the use of certain language features altogether. For instance, you might decide to disallow the use of `try-catch` or `class`, or you might decide to disallow the use of the `in` operator.
 
-Rather than creating separate rules for every language feature you want to turn off, this rule allows you to configure the syntax elements you want to restrict use of. These elements are represented by their [ESTree](https://github.com/estree/estree) node types. For example, a function declaration is represented by `FunctionDeclaration` and the `with` statement is represented by `WithStatement`. You may find the full list of AST node names you can use [on GitHub](https://github.com/eslint/espree/blob/master/lib/ast-node-types.js) and use the [online parser](https://eslint.org/parser/) to see what type of nodes your code consists of.
+Rather than creating separate rules for every language feature you want to turn off, this rule allows you to configure the syntax elements you want to restrict use of. These elements are represented by their [ESTree](https://github.com/estree/estree) node types. For example, a function declaration is represented by `FunctionDeclaration` and the `with` statement is represented by `WithStatement`. You may find the full list of AST node names you can use [on GitHub](https://github.com/eslint/espree/blob/master/lib/ast-node-types.js) and use [AST Explorer](https://astexplorer.net/) with the espree parser to see what type of nodes your code consists of.
 
 You can also specify [AST selectors](../developer-guide/selectors) to restrict, allowing much more precise control over syntax patterns.
 
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 5022fc44d..2a47a3e9e 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -664,6 +664,7 @@ In each case, the settings in the configuration file override default settings.
 ESLint supports configuration files in several formats:
 
 * **JavaScript** - use `.eslintrc.js` and export an object containing your configuration.
+* **JavaScript (ESM)** - use `.eslintrc.cjs` when running ESLint in JavaScript packages that specify `"type":"module"` in their `package.json`. Note that ESLint does not support ESM configuration at this time.
 * **YAML** - use `.eslintrc.yaml` or `.eslintrc.yml` to define the configuration structure.
 * **JSON** - use `.eslintrc.json` to define the configuration structure. ESLint's JSON files also allow JavaScript-style comments.
 * **Deprecated** - use `.eslintrc`, which can be either JSON or YAML.
@@ -672,13 +673,13 @@ ESLint supports configuration files in several formats:
 If there are multiple configuration files in the same directory, ESLint will only use one. The priority order is:
 
 1. `.eslintrc.js`
+1. `.eslintrc.cjs`
 1. `.eslintrc.yaml`
 1. `.eslintrc.yml`
 1. `.eslintrc.json`
 1. `.eslintrc`
 1. `package.json`
 
-
 ## Configuration Cascading and Hierarchy
 
 When using `.eslintrc.*` and `package.json` files for configuration, you can take advantage of configuration cascading. For instance, suppose you have the following structure:
diff --git a/lib/cli-engine/config-array-factory.js b/lib/cli-engine/config-array-factory.js
index c444031bc..76c4ccd70 100644
--- a/lib/cli-engine/config-array-factory.js
+++ b/lib/cli-engine/config-array-factory.js
@@ -62,6 +62,7 @@ const eslintRecommendedPath = path.resolve(__dirname, "../../conf/eslint-recomme
 const eslintAllPath = path.resolve(__dirname, "../../conf/eslint-all.js");
 const configFilenames = [
     ".eslintrc.js",
+    ".eslintrc.cjs",
     ".eslintrc.yaml",
     ".eslintrc.yml",
     ".eslintrc.json",
@@ -279,6 +280,7 @@ function configMissingError(configName, importerName) {
 function loadConfigFile(filePath) {
     switch (path.extname(filePath)) {
         case ".js":
+        case ".cjs":
             return loadJSConfigFile(filePath);
 
         case ".json":
diff --git a/lib/cli-engine/file-enumerator.js b/lib/cli-engine/file-enumerator.js
index 700f8009c..b5a082b71 100644
--- a/lib/cli-engine/file-enumerator.js
+++ b/lib/cli-engine/file-enumerator.js
@@ -375,9 +375,6 @@ class FileEnumerator {
      * @private
      */
     *_iterateFilesRecursive(directoryPath, options) {
-        if (this._isIgnoredFile(directoryPath + path.sep, options)) {
-            return;
-        }
         debug(`Enter the directory: ${directoryPath}`);
         const { configArrayFactory, extensionRegExp } = internalSlotsMap.get(this);
 
@@ -426,7 +423,20 @@ class FileEnumerator {
 
             // Dive into the sub directory.
             } else if (options.recursive && stat && stat.isDirectory()) {
-                yield* this._iterateFilesRecursive(filePath, options);
+                if (!config) {
+                    config = configArrayFactory.getConfigArrayForFile(
+                        filePath,
+                        { ignoreNotFoundError: true }
+                    );
+                }
+                const ignored = this._isIgnoredFile(
+                    filePath + path.sep,
+                    { ...options, config }
+                );
+
+                if (!ignored) {
+                    yield* this._iterateFilesRecursive(filePath, options);
+                }
             }
         }
 
diff --git a/lib/cli-engine/lint-result-cache.js b/lib/cli-engine/lint-result-cache.js
index 14e19d9e5..23a142097 100644
--- a/lib/cli-engine/lint-result-cache.js
+++ b/lib/cli-engine/lint-result-cache.js
@@ -20,6 +20,7 @@ const hash = require("./hash");
 //-----------------------------------------------------------------------------
 
 const configHashCache = new WeakMap();
+const nodeVersion = process && process.version;
 
 /**
  * Calculates the hash of the config
@@ -28,7 +29,7 @@ const configHashCache = new WeakMap();
  */
 function hashOfConfigFor(config) {
     if (!configHashCache.has(config)) {
-        configHashCache.set(config, hash(`${pkg.version}_${stringify(config)}`));
+        configHashCache.set(config, hash(`${pkg.version}_${nodeVersion}_${stringify(config)}`));
     }
 
     return configHashCache.get(config);
diff --git a/lib/linter/config-comment-parser.js b/lib/linter/config-comment-parser.js
index d0e24c594..35862315d 100644
--- a/lib/linter/config-comment-parser.js
+++ b/lib/linter/config-comment-parser.js
@@ -90,7 +90,7 @@ module.exports = class ConfigCommentParser {
          * But we are supporting that. So this is a fallback for that.
          */
         items = {};
-        const normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
+        const normalizedString = string.replace(/([-a-zA-Z0-9/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
 
         try {
             items = JSON.parse(`{${normalizedString}}`);
diff --git a/lib/rules/array-bracket-spacing.js b/lib/rules/array-bracket-spacing.js
index 2510159ee..c2b77a641 100644
--- a/lib/rules/array-bracket-spacing.js
+++ b/lib/rules/array-bracket-spacing.js
@@ -84,16 +84,16 @@ module.exports = {
          * @returns {void}
          */
         function reportNoBeginningSpace(node, token) {
+            const nextToken = sourceCode.getTokenAfter(token);
+
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: { start: token.loc.end, end: nextToken.loc.start },
                 messageId: "unexpectedSpaceAfter",
                 data: {
                     tokenValue: token.value
                 },
                 fix(fixer) {
-                    const nextToken = sourceCode.getTokenAfter(token);
-
                     return fixer.removeRange([token.range[1], nextToken.range[0]]);
                 }
             });
@@ -106,16 +106,16 @@ module.exports = {
          * @returns {void}
          */
         function reportNoEndingSpace(node, token) {
+            const previousToken = sourceCode.getTokenBefore(token);
+
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: { start: previousToken.loc.end, end: token.loc.start },
                 messageId: "unexpectedSpaceBefore",
                 data: {
                     tokenValue: token.value
                 },
                 fix(fixer) {
-                    const previousToken = sourceCode.getTokenBefore(token);
-
                     return fixer.removeRange([previousToken.range[1], token.range[0]]);
                 }
             });
@@ -130,7 +130,7 @@ module.exports = {
         function reportRequiredBeginningSpace(node, token) {
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: token.loc,
                 messageId: "missingSpaceAfter",
                 data: {
                     tokenValue: token.value
@@ -150,7 +150,7 @@ module.exports = {
         function reportRequiredEndingSpace(node, token) {
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: token.loc,
                 messageId: "missingSpaceBefore",
                 data: {
                     tokenValue: token.value
diff --git a/lib/rules/no-multiple-empty-lines.js b/lib/rules/no-multiple-empty-lines.js
index f945cfeff..41e6be3a2 100644
--- a/lib/rules/no-multiple-empty-lines.js
+++ b/lib/rules/no-multiple-empty-lines.js
@@ -110,7 +110,7 @@ module.exports = {
                         if (lineNumber - lastLineNumber - 1 > maxAllowed) {
                             context.report({
                                 node,
-                                loc: { start: { line: lastLineNumber + 1, column: 0 }, end: { line: lineNumber, column: 0 } },
+                                loc: { start: { line: lastLineNumber + maxAllowed + 1, column: 0 }, end: { line: lineNumber, column: 0 } },
                                 message,
                                 data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" },
                                 fix(fixer) {
diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js
index bed9c2432..ec0696f99 100644
--- a/lib/rules/no-restricted-imports.js
+++ b/lib/rules/no-restricted-imports.js
@@ -72,14 +72,14 @@ module.exports = {
                 arrayOfStringsOrObjects,
                 {
                     type: "array",
-                    items: {
+                    items: [{
                         type: "object",
                         properties: {
                             paths: arrayOfStringsOrObjects,
                             patterns: arrayOfStrings
                         },
                         additionalProperties: false
-                    },
+                    }],
                     additionalItems: false
                 }
             ]
diff --git a/lib/rules/no-unexpected-multiline.js b/lib/rules/no-unexpected-multiline.js
index 8026e1722..eb72008a2 100644
--- a/lib/rules/no-unexpected-multiline.js
+++ b/lib/rules/no-unexpected-multiline.js
@@ -74,6 +74,14 @@ module.exports = {
                 if (node.tag.loc.end.line === node.quasi.loc.start.line) {
                     return;
                 }
+
+                // handle generics type parameters on template tags
+                const tokenBefore = sourceCode.getTokenBefore(node.quasi);
+
+                if (tokenBefore.loc.end.line === node.quasi.loc.start.line) {
+                    return;
+                }
+
                 context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" });
             },
 
diff --git a/lib/rules/no-unsafe-negation.js b/lib/rules/no-unsafe-negation.js
index 5c8f569d7..a9c2ee74f 100644
--- a/lib/rules/no-unsafe-negation.js
+++ b/lib/rules/no-unsafe-negation.js
@@ -54,7 +54,8 @@ module.exports = {
             description: "disallow negating the left operand of relational operators",
             category: "Possible Errors",
             recommended: true,
-            url: "https://eslint.org/docs/rules/no-unsafe-negation"
+            url: "https://eslint.org/docs/rules/no-unsafe-negation",
+            suggestion: true
         },
 
         schema: [
@@ -69,9 +70,13 @@ module.exports = {
                 additionalProperties: false
             }
         ],
+
         fixable: null,
+
         messages: {
-            unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
+            unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
+            suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
+            suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
         }
     },
 
@@ -82,10 +87,11 @@ module.exports = {
 
         return {
             BinaryExpression(node) {
-                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(node.operator);
+                const operator = node.operator;
+                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);
 
                 if (
-                    (isInOrInstanceOfOperator(node.operator) || orderingRelationRuleApplies) &&
+                    (isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) &&
                     isNegation(node.left) &&
                     !astUtils.isParenthesised(sourceCode, node.left)
                 ) {
@@ -93,7 +99,26 @@ module.exports = {
                         node,
                         loc: node.left.loc,
                         messageId: "unexpected",
-                        data: { operator: node.operator }
+                        data: { operator },
+                        suggest: [
+                            {
+                                messageId: "suggestNegatedExpression",
+                                data: { operator },
+                                fix(fixer) {
+                                    const negationToken = sourceCode.getFirstToken(node.left);
+                                    const fixRange = [negationToken.range[1], node.range[1]];
+                                    const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
+
+                                    return fixer.replaceTextRange(fixRange, `(${text})`);
+                                }
+                            },
+                            {
+                                messageId: "suggestParenthesisedNegation",
+                                fix(fixer) {
+                                    return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
+                                }
+                            }
+                        ]
                     });
                 }
             }
diff --git a/lib/rules/prefer-numeric-literals.js b/lib/rules/prefer-numeric-literals.js
index 672d9bcaa..c352d88dc 100644
--- a/lib/rules/prefer-numeric-literals.js
+++ b/lib/rules/prefer-numeric-literals.js
@@ -15,6 +15,12 @@ const astUtils = require("./utils/ast-utils");
 // Helpers
 //------------------------------------------------------------------------------
 
+const radixMap = new Map([
+    [2, { system: "binary", literalPrefix: "0b" }],
+    [8, { system: "octal", literalPrefix: "0o" }],
+    [16, { system: "hexadecimal", literalPrefix: "0x" }]
+]);
+
 /**
  * Checks to see if a CallExpression's callee node is `parseInt` or
  * `Number.parseInt`.
@@ -54,49 +60,44 @@ module.exports = {
         },
 
         schema: [],
+
+        messages: {
+            useLiteral: "Use {{system}} literals instead of {{functionName}}()."
+        },
+
         fixable: "code"
     },
 
     create(context) {
         const sourceCode = context.getSourceCode();
 
-        const radixMap = {
-            2: "binary",
-            8: "octal",
-            16: "hexadecimal"
-        };
-
-        const prefixMap = {
-            2: "0b",
-            8: "0o",
-            16: "0x"
-        };
-
         //----------------------------------------------------------------------
         // Public
         //----------------------------------------------------------------------
 
         return {
 
-            CallExpression(node) {
-
-                // doesn't check parseInt() if it doesn't have a radix argument
-                if (node.arguments.length !== 2) {
-                    return;
-                }
+            "CallExpression[arguments.length=2]"(node) {
+                const [strNode, radixNode] = node.arguments,
+                    str = strNode.value,
+                    radix = radixNode.value;
+
+                if (
+                    strNode.type === "Literal" &&
+                    radixNode.type === "Literal" &&
+                    typeof str === "string" &&
+                    typeof radix === "number" &&
+                    radixMap.has(radix) &&
+                    isParseInt(node.callee)
+                ) {
 
-                // only error if the radix is 2, 8, or 16
-                const radixName = radixMap[node.arguments[1].value];
+                    const { system, literalPrefix } = radixMap.get(radix);
 
-                if (isParseInt(node.callee) &&
-                    radixName &&
-                    node.arguments[0].type === "Literal"
-                ) {
                     context.report({
                         node,
-                        message: "Use {{radixName}} literals instead of {{functionName}}().",
+                        messageId: "useLiteral",
                         data: {
-                            radixName,
+                            system,
                             functionName: sourceCode.getText(node.callee)
                         },
                         fix(fixer) {
@@ -104,9 +105,9 @@ module.exports = {
                                 return null;
                             }
 
-                            const replacement = `${prefixMap[node.arguments[1].value]}${node.arguments[0].value}`;
+                            const replacement = `${literalPrefix}${str}`;
 
-                            if (+replacement !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
+                            if (+replacement !== parseInt(str, radix)) {
 
                                 /*
                                  * If the newly-produced literal would be invalid, (e.g. 0b1234),
diff --git a/lib/rules/require-atomic-updates.js b/lib/rules/require-atomic-updates.js
index 3912ad86c..bdd6d81eb 100644
--- a/lib/rules/require-atomic-updates.js
+++ b/lib/rules/require-atomic-updates.js
@@ -162,7 +162,7 @@ module.exports = {
         docs: {
             description: "disallow assignments that can lead to race conditions due to usage of `await` or `yield`",
             category: "Possible Errors",
-            recommended: true,
+            recommended: false,
             url: "https://eslint.org/docs/rules/require-atomic-updates"
         },
 
diff --git a/lib/source-code/source-code.js b/lib/source-code/source-code.js
index 20b442f23..30b4e9ab5 100644
--- a/lib/source-code/source-code.js
+++ b/lib/source-code/source-code.js
@@ -90,6 +90,56 @@ function nodesOrTokensOverlap(first, second) {
         (second.range[0] <= first.range[0] && second.range[1] >= first.range[0]);
 }
 
+/**
+ * Determines if two nodes or tokens have at least one whitespace character
+ * between them. Order does not matter. Returns false if the given nodes or
+ * tokens overlap.
+ * @param {SourceCode} sourceCode The source code object.
+ * @param {ASTNode|Token} first The first node or token to check between.
+ * @param {ASTNode|Token} second The second node or token to check between.
+ * @param {boolean} checkInsideOfJSXText If `true` is present, check inside of JSXText tokens for backward compatibility.
+ * @returns {boolean} True if there is a whitespace character between
+ * any of the tokens found between the two given nodes or tokens.
+ * @public
+ */
+function isSpaceBetween(sourceCode, first, second, checkInsideOfJSXText) {
+    if (nodesOrTokensOverlap(first, second)) {
+        return false;
+    }
+
+    const [startingNodeOrToken, endingNodeOrToken] = first.range[1] <= second.range[0]
+        ? [first, second]
+        : [second, first];
+    const firstToken = sourceCode.getLastToken(startingNodeOrToken) || startingNodeOrToken;
+    const finalToken = sourceCode.getFirstToken(endingNodeOrToken) || endingNodeOrToken;
+    let currentToken = firstToken;
+
+    while (currentToken !== finalToken) {
+        const nextToken = sourceCode.getTokenAfter(currentToken, { includeComments: true });
+
+        if (
+            currentToken.range[1] !== nextToken.range[0] ||
+
+                /*
+                 * For backward compatibility, check speces in JSXText.
+                 * https://github.com/eslint/eslint/issues/12614
+                 */
+                (
+                    checkInsideOfJSXText &&
+                    nextToken !== finalToken &&
+                    nextToken.type === "JSXText" &&
+                    /\s/u.test(nextToken.value)
+                )
+        ) {
+            return true;
+        }
+
+        currentToken = nextToken;
+    }
+
+    return false;
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
 //------------------------------------------------------------------------------
@@ -433,42 +483,24 @@ class SourceCode extends TokenStore {
      * @public
      */
     isSpaceBetween(first, second) {
-        if (nodesOrTokensOverlap(first, second)) {
-            return false;
-        }
-
-        const [startingNodeOrToken, endingNodeOrToken] = first.range[1] <= second.range[0]
-            ? [first, second]
-            : [second, first];
-        const firstToken = this.getLastToken(startingNodeOrToken) || startingNodeOrToken;
-        const finalToken = this.getFirstToken(endingNodeOrToken) || endingNodeOrToken;
-        let currentToken = firstToken;
-
-        while (currentToken !== finalToken) {
-            const nextToken = this.getTokenAfter(currentToken, { includeComments: true });
-
-            if (currentToken.range[1] !== nextToken.range[0]) {
-                return true;
-            }
-
-            currentToken = nextToken;
-        }
-
-        return false;
+        return isSpaceBetween(this, first, second, false);
     }
 
     /**
      * Determines if two nodes or tokens have at least one whitespace character
      * between them. Order does not matter. Returns false if the given nodes or
      * tokens overlap.
-     * @param {...ASTNode|Token} args The nodes or tokens to check between.
+     * For backward compatibility, this method returns true if there are
+     * `JSXText` tokens that contain whitespaces between the two.
+     * @param {ASTNode|Token} first The first node or token to check between.
+     * @param {ASTNode|Token} second The second node or token to check between.
      * @returns {boolean} True if there is a whitespace character between
      * any of the tokens found between the two given nodes or tokens.
      * @deprecated in favor of isSpaceBetween().
      * @public
      */
-    isSpaceBetweenTokens(...args) {
-        return this.isSpaceBetween(...args);
+    isSpaceBetweenTokens(first, second) {
+        return isSpaceBetween(this, first, second, true);
     }
 
     /**
diff --git a/package.json b/package.json
index b0563edf1..5d0c0ba4a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "6.7.1",
+  "version": "6.7.2",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
diff --git a/webpack.config.js b/webpack.config.js
index 1630cef97..6a43ac755 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,8 +3,7 @@
 module.exports = {
     mode: "none",
     entry: {
-        eslint: ["core-js/stable", "regenerator-runtime/runtime", "./lib/linter/linter.js"],
-        espree: ["core-js/stable", "regenerator-runtime/runtime", "espree"]
+        eslint: ["core-js/stable", "regenerator-runtime/runtime", "./lib/linter/linter.js"]
     },
     output: {
         filename: "[name].js",


Test patch:
diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js
index b4b3b2bec..44e01dadf 100644
--- a/lib/rule-tester/rule-tester.js
+++ b/lib/rule-tester/rule-tester.js
@@ -596,8 +596,10 @@ class RuleTester {
                         if (hasOwnProperty(error, "suggestions")) {
 
                             // Support asserting there are no suggestions
-                            if (!error.suggestions) {
-                                assert.strictEqual(message.suggestions, error.suggestions, `Error should have no suggestions on error with message: "${message.message}"`);
+                            if (!error.suggestions || (Array.isArray(error.suggestions) && error.suggestions.length === 0)) {
+                                if (Array.isArray(message.suggestions) && message.suggestions.length > 0) {
+                                    assert.fail(`Error should have no suggestions on error with message: "${message.message}"`);
+                                }
                             } else {
                                 assert.strictEqual(Array.isArray(message.suggestions), true, `Error should have an array of suggestions. Instead received "${message.suggestions}" on error with message: "${message.message}"`);
                                 assert.strictEqual(message.suggestions.length, error.suggestions.length, `Error should have ${error.suggestions.length} suggestions. Instead found ${message.suggestions.length} suggestions`);
diff --git a/tests/fixtures/config-file/cjs/.eslintrc.cjs b/tests/fixtures/config-file/cjs/.eslintrc.cjs
new file mode 100644
index 000000000..b3100591d
--- /dev/null
+++ b/tests/fixtures/config-file/cjs/.eslintrc.cjs
@@ -0,0 +1,5 @@
+module.exports = {
+    rules: {
+        semi: [2, "always"]
+    }
+};
diff --git a/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-1.js b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-1.js
new file mode 100644
index 000000000..ba6cb389d
--- /dev/null
+++ b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-1.js
@@ -0,0 +1,245 @@
+"use strict";
+
+/*
+ * Parsed on astexplorer.net using @typescript-eslint/parser@1.4.2
+ *
+ * Source:
+ * tag<generic>`
+ *     multiline
+ * `;
+ */
+
+exports.parse = () => ({
+    type: "Program",
+    body: [
+        {
+            type: "ExpressionStatement",
+            expression: {
+                type: "TaggedTemplateExpression",
+                typeParameters: {
+                    type: "TSTypeParameterInstantiation",
+                    range: [3, 12],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 3
+                        },
+                        end: {
+                            line: 1,
+                            column: 12
+                        }
+                    },
+                    params: [
+                        {
+                            type: "TSTypeReference",
+                            typeName: {
+                                type: "Identifier",
+                                name: "generic",
+                                range: [4, 11],
+                                loc: {
+                                    start: {
+                                        line: 1,
+                                        column: 4
+                                    },
+                                    end: {
+                                        line: 1,
+                                        column: 11
+                                    }
+                                }
+                            },
+                            range: [4, 11],
+                            loc: {
+                                start: {
+                                    line: 1,
+                                    column: 4
+                                },
+                                end: {
+                                    line: 1,
+                                    column: 11
+                                }
+                            }
+                        }
+                    ]
+                },
+                tag: {
+                    type: "Identifier",
+                    name: "tag",
+                    range: [0, 3],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 0
+                        },
+                        end: {
+                            line: 1,
+                            column: 3
+                        }
+                    }
+                },
+                quasi: {
+                    type: "TemplateLiteral",
+                    quasis: [
+                        {
+                            type: "TemplateElement",
+                            value: {
+                                raw: "\n    multiline\n",
+                                cooked: "\n    multiline\n"
+                            },
+                            tail: true,
+                            range: [12, 29],
+                            loc: {
+                                start: {
+                                    line: 1,
+                                    column: 12
+                                },
+                                end: {
+                                    line: 3,
+                                    column: 1
+                                }
+                            }
+                        }
+                    ],
+                    expressions: [],
+                    range: [12, 29],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 12
+                        },
+                        end: {
+                            line: 3,
+                            column: 1
+                        }
+                    }
+                },
+                range: [0, 29],
+                loc: {
+                    start: {
+                        line: 1,
+                        column: 0
+                    },
+                    end: {
+                        line: 3,
+                        column: 1
+                    }
+                }
+            },
+            range: [0, 30],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 3,
+                    column: 2
+                }
+            }
+        }
+    ],
+    sourceType: "script",
+    range: [0, 30],
+    loc: {
+        start: {
+            line: 1,
+            column: 0
+        },
+        end: {
+            line: 3,
+            column: 2
+        }
+    },
+    tokens: [
+        {
+            type: "Identifier",
+            value: "tag",
+            range: [0, 3],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 1,
+                    column: 3
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: "<",
+            range: [3, 4],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 3
+                },
+                end: {
+                    line: 1,
+                    column: 4
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "generic",
+            range: [4, 11],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 4
+                },
+                end: {
+                    line: 1,
+                    column: 11
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ">",
+            range: [11, 12],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 11
+                },
+                end: {
+                    line: 1,
+                    column: 12
+                }
+            }
+        },
+        {
+            type: "Template",
+            value: "`\n    multiline\n`",
+            range: [12, 29],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 12
+                },
+                end: {
+                    line: 3,
+                    column: 1
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ";",
+            range: [29, 30],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 1
+                },
+                end: {
+                    line: 3,
+                    column: 2
+                }
+            }
+        }
+    ],
+    comments: []
+});
diff --git a/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-2.js b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-2.js
new file mode 100644
index 000000000..4ac20dc73
--- /dev/null
+++ b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-2.js
@@ -0,0 +1,247 @@
+"use strict";
+
+/*
+ * Parsed on astexplorer.net using @typescript-eslint/parser@1.4.2
+ *
+ * Source:
+ * tag<
+ *   generic
+ * >`
+ *     multiline
+ * `;
+ */
+
+exports.parse = () => ({
+    type: "Program",
+    body: [
+        {
+            type: "ExpressionStatement",
+            expression: {
+                type: "TaggedTemplateExpression",
+                typeParameters: {
+                    type: "TSTypeParameterInstantiation",
+                    range: [3, 16],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 3
+                        },
+                        end: {
+                            line: 3,
+                            column: 1
+                        }
+                    },
+                    params: [
+                        {
+                            type: "TSTypeReference",
+                            typeName: {
+                                type: "Identifier",
+                                name: "generic",
+                                range: [7, 14],
+                                loc: {
+                                    start: {
+                                        line: 2,
+                                        column: 2
+                                    },
+                                    end: {
+                                        line: 2,
+                                        column: 9
+                                    }
+                                }
+                            },
+                            range: [7, 14],
+                            loc: {
+                                start: {
+                                    line: 2,
+                                    column: 2
+                                },
+                                end: {
+                                    line: 2,
+                                    column: 9
+                                }
+                            }
+                        }
+                    ]
+                },
+                tag: {
+                    type: "Identifier",
+                    name: "tag",
+                    range: [0, 3],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 0
+                        },
+                        end: {
+                            line: 1,
+                            column: 3
+                        }
+                    }
+                },
+                quasi: {
+                    type: "TemplateLiteral",
+                    quasis: [
+                        {
+                            type: "TemplateElement",
+                            value: {
+                                raw: "\n    multiline\n",
+                                cooked: "\n    multiline\n"
+                            },
+                            tail: true,
+                            range: [16, 33],
+                            loc: {
+                                start: {
+                                    line: 3,
+                                    column: 1
+                                },
+                                end: {
+                                    line: 5,
+                                    column: 1
+                                }
+                            }
+                        }
+                    ],
+                    expressions: [],
+                    range: [16, 33],
+                    loc: {
+                        start: {
+                            line: 3,
+                            column: 1
+                        },
+                        end: {
+                            line: 5,
+                            column: 1
+                        }
+                    }
+                },
+                range: [0, 33],
+                loc: {
+                    start: {
+                        line: 1,
+                        column: 0
+                    },
+                    end: {
+                        line: 5,
+                        column: 1
+                    }
+                }
+            },
+            range: [0, 34],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 5,
+                    column: 2
+                }
+            }
+        }
+    ],
+    sourceType: "script",
+    range: [0, 34],
+    loc: {
+        start: {
+            line: 1,
+            column: 0
+        },
+        end: {
+            line: 5,
+            column: 2
+        }
+    },
+    tokens: [
+        {
+            type: "Identifier",
+            value: "tag",
+            range: [0, 3],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 1,
+                    column: 3
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: "<",
+            range: [3, 4],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 3
+                },
+                end: {
+                    line: 1,
+                    column: 4
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "generic",
+            range: [7, 14],
+            loc: {
+                start: {
+                    line: 2,
+                    column: 2
+                },
+                end: {
+                    line: 2,
+                    column: 9
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ">",
+            range: [15, 16],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 0
+                },
+                end: {
+                    line: 3,
+                    column: 1
+                }
+            }
+        },
+        {
+            type: "Template",
+            value: "`\n    multiline\n`",
+            range: [16, 33],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 1
+                },
+                end: {
+                    line: 5,
+                    column: 1
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ";",
+            range: [33, 34],
+            loc: {
+                start: {
+                    line: 5,
+                    column: 1
+                },
+                end: {
+                    line: 5,
+                    column: 2
+                }
+            }
+        }
+    ],
+    comments: []
+});
diff --git a/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-3.js b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-3.js
new file mode 100644
index 000000000..e9018e1ac
--- /dev/null
+++ b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-3.js
@@ -0,0 +1,245 @@
+"use strict";
+
+/*
+ * Parsed on astexplorer.net using @typescript-eslint/parser@1.4.2
+ *
+ * Source:
+ * tag<
+ *   generic
+ * >`multiline`;
+ */
+
+exports.parse = () => ({
+    type: "Program",
+    body: [
+        {
+            type: "ExpressionStatement",
+            expression: {
+                type: "TaggedTemplateExpression",
+                typeParameters: {
+                    type: "TSTypeParameterInstantiation",
+                    range: [3, 16],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 3
+                        },
+                        end: {
+                            line: 3,
+                            column: 1
+                        }
+                    },
+                    params: [
+                        {
+                            type: "TSTypeReference",
+                            typeName: {
+                                type: "Identifier",
+                                name: "generic",
+                                range: [7, 14],
+                                loc: {
+                                    start: {
+                                        line: 2,
+                                        column: 2
+                                    },
+                                    end: {
+                                        line: 2,
+                                        column: 9
+                                    }
+                                }
+                            },
+                            range: [7, 14],
+                            loc: {
+                                start: {
+                                    line: 2,
+                                    column: 2
+                                },
+                                end: {
+                                    line: 2,
+                                    column: 9
+                                }
+                            }
+                        }
+                    ]
+                },
+                tag: {
+                    type: "Identifier",
+                    name: "tag",
+                    range: [0, 3],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 0
+                        },
+                        end: {
+                            line: 1,
+                            column: 3
+                        }
+                    }
+                },
+                quasi: {
+                    type: "TemplateLiteral",
+                    quasis: [
+                        {
+                            type: "TemplateElement",
+                            value: {
+                                raw: "multiline",
+                                cooked: "multiline"
+                            },
+                            tail: true,
+                            range: [16, 27],
+                            loc: {
+                                start: {
+                                    line: 3,
+                                    column: 1
+                                },
+                                end: {
+                                    line: 3,
+                                    column: 12
+                                }
+                            }
+                        }
+                    ],
+                    expressions: [],
+                    range: [16, 27],
+                    loc: {
+                        start: {
+                            line: 3,
+                            column: 1
+                        },
+                        end: {
+                            line: 3,
+                            column: 12
+                        }
+                    }
+                },
+                range: [0, 27],
+                loc: {
+                    start: {
+                        line: 1,
+                        column: 0
+                    },
+                    end: {
+                        line: 3,
+                        column: 12
+                    }
+                }
+            },
+            range: [0, 28],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 3,
+                    column: 13
+                }
+            }
+        }
+    ],
+    sourceType: "script",
+    range: [0, 28],
+    loc: {
+        start: {
+            line: 1,
+            column: 0
+        },
+        end: {
+            line: 3,
+            column: 13
+        }
+    },
+    tokens: [
+        {
+            type: "Identifier",
+            value: "tag",
+            range: [0, 3],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 1,
+                    column: 3
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: "<",
+            range: [3, 4],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 3
+                },
+                end: {
+                    line: 1,
+                    column: 4
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "generic",
+            range: [7, 14],
+            loc: {
+                start: {
+                    line: 2,
+                    column: 2
+                },
+                end: {
+                    line: 2,
+                    column: 9
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ">",
+            range: [15, 16],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 0
+                },
+                end: {
+                    line: 3,
+                    column: 1
+                }
+            }
+        },
+        {
+            type: "Template",
+            value: "`multiline`",
+            range: [16, 27],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 1
+                },
+                end: {
+                    line: 3,
+                    column: 12
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ";",
+            range: [27, 28],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 12
+                },
+                end: {
+                    line: 3,
+                    column: 13
+                }
+            }
+        }
+    ],
+    comments: []
+});
diff --git a/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-and-comment.js b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-and-comment.js
new file mode 100644
index 000000000..e8c8ca148
--- /dev/null
+++ b/tests/fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-and-comment.js
@@ -0,0 +1,325 @@
+"use strict";
+
+/**
+ * Parsed on astexplorer.net using @typescript-eslint/parser@2.6.1
+ *
+ * Source:
+ */
+// const x = aaaa<
+//   test
+// >/*
+// test
+// */`foo`
+
+exports.parse = () => ({
+    type: "Program",
+    body: [
+        {
+            type: "VariableDeclaration",
+            declarations: [
+                {
+                    type: "VariableDeclarator",
+                    id: {
+                        type: "Identifier",
+                        name: "x",
+                        range: [6, 7],
+                        loc: {
+                            start: {
+                                line: 1,
+                                column: 6
+                            },
+                            end: {
+                                line: 1,
+                                column: 7
+                            }
+                        }
+                    },
+                    init: {
+                        type: "TaggedTemplateExpression",
+                        typeParameters: {
+                            type: "TSTypeParameterInstantiation",
+                            range: [14, 24],
+                            loc: {
+                                start: {
+                                    line: 1,
+                                    column: 14
+                                },
+                                end: {
+                                    line: 3,
+                                    column: 1
+                                }
+                            },
+                            params: [
+                                {
+                                    type: "TSTypeReference",
+                                    typeName: {
+                                        type: "Identifier",
+                                        name: "test",
+                                        range: [18, 22],
+                                        loc: {
+                                            start: {
+                                                line: 2,
+                                                column: 2
+                                            },
+                                            end: {
+                                                line: 2,
+                                                column: 6
+                                            }
+                                        }
+                                    },
+                                    range: [18, 22],
+                                    loc: {
+                                        start: {
+                                            line: 2,
+                                            column: 2
+                                        },
+                                        end: {
+                                            line: 2,
+                                            column: 6
+                                        }
+                                    }
+                                }
+                            ]
+                        },
+                        tag: {
+                            type: "Identifier",
+                            name: "aaaa",
+                            range: [10, 14],
+                            loc: {
+                                start: {
+                                    line: 1,
+                                    column: 10
+                                },
+                                end: {
+                                    line: 1,
+                                    column: 14
+                                }
+                            }
+                        },
+                        quasi: {
+                            type: "TemplateLiteral",
+                            quasis: [
+                                {
+                                    type: "TemplateElement",
+                                    value: {
+                                        raw: "foo",
+                                        cooked: "foo"
+                                    },
+                                    tail: true,
+                                    range: [34, 39],
+                                    loc: {
+                                        start: {
+                                            line: 5,
+                                            column: 2
+                                        },
+                                        end: {
+                                            line: 5,
+                                            column: 7
+                                        }
+                                    }
+                                }
+                            ],
+                            expressions: [],
+                            range: [34, 39],
+                            loc: {
+                                start: {
+                                    line: 5,
+                                    column: 2
+                                },
+                                end: {
+                                    line: 5,
+                                    column: 7
+                                }
+                            }
+                        },
+                        range: [10, 39],
+                        loc: {
+                            start: {
+                                line: 1,
+                                column: 10
+                            },
+                            end: {
+                                line: 5,
+                                column: 7
+                            }
+                        }
+                    },
+                    range: [6, 39],
+                    loc: {
+                        start: {
+                            line: 1,
+                            column: 6
+                        },
+                        end: {
+                            line: 5,
+                            column: 7
+                        }
+                    }
+                }
+            ],
+            kind: "const",
+            range: [0, 39],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 5,
+                    column: 7
+                }
+            }
+        }
+    ],
+    sourceType: "module",
+    range: [0, 39],
+    loc: {
+        start: {
+            line: 1,
+            column: 0
+        },
+        end: {
+            line: 5,
+            column: 7
+        }
+    },
+    tokens: [
+        {
+            type: "Keyword",
+            value: "const",
+            range: [0, 5],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 0
+                },
+                end: {
+                    line: 1,
+                    column: 5
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "x",
+            range: [6, 7],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 6
+                },
+                end: {
+                    line: 1,
+                    column: 7
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: "=",
+            range: [8, 9],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 8
+                },
+                end: {
+                    line: 1,
+                    column: 9
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "aaaa",
+            range: [10, 14],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 10
+                },
+                end: {
+                    line: 1,
+                    column: 14
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: "<",
+            range: [14, 15],
+            loc: {
+                start: {
+                    line: 1,
+                    column: 14
+                },
+                end: {
+                    line: 1,
+                    column: 15
+                }
+            }
+        },
+        {
+            type: "Identifier",
+            value: "test",
+            range: [18, 22],
+            loc: {
+                start: {
+                    line: 2,
+                    column: 2
+                },
+                end: {
+                    line: 2,
+                    column: 6
+                }
+            }
+        },
+        {
+            type: "Punctuator",
+            value: ">",
+            range: [23, 24],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 0
+                },
+                end: {
+                    line: 3,
+                    column: 1
+                }
+            }
+        },
+        {
+            type: "Template",
+            value: "`foo`",
+            range: [34, 39],
+            loc: {
+                start: {
+                    line: 5,
+                    column: 2
+                },
+                end: {
+                    line: 5,
+                    column: 7
+                }
+            }
+        }
+    ],
+    comments: [
+        {
+            type: "Block",
+            value: "\ntest\n",
+            range: [24, 34],
+            loc: {
+                start: {
+                    line: 3,
+                    column: 1
+                },
+                end: {
+                    line: 5,
+                    column: 2
+                }
+            }
+        }
+    ]
+});
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index 1d9bef090..1c2411c97 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -1288,7 +1288,7 @@ describe("CLIEngine", () => {
 
             assert.throws(() => {
                 engine.executeOnFiles(["./tests/fixtures/cli-engine/"]);
-            }, "No files matching './tests/fixtures/cli-engine/' were found.");
+            }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
         });
 
         it("should throw an error when all given files are ignored via ignore-pattern", () => {
@@ -3628,6 +3628,55 @@ describe("CLIEngine", () => {
                 assert.strictEqual(messages[0].ruleId, "no-console");
             });
         });
+
+        describe("don't ignore the entry directory.", () => {
+            const root = getFixturePath("cli-engine/dont-ignore-entry-dir");
+
+            it("'executeOnFiles(\".\")' should not load config files from outside of \".\".", () => {
+                CLIEngine = defineCLIEngineWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "../.eslintrc.json": "BROKEN FILE",
+                        ".eslintrc.json": JSON.stringify({ root: true }),
+                        "index.js": "console.log(\"hello\")"
+                    }
+                }).CLIEngine;
+                engine = new CLIEngine();
+
+                // Don't throw "failed to load config file" error.
+                engine.executeOnFiles(".");
+            });
+
+            it("'executeOnFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", () => {
+                CLIEngine = defineCLIEngineWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "../.eslintrc.json": JSON.stringify({ ignorePatterns: ["/dont-ignore-entry-dir"] }),
+                        ".eslintrc.json": JSON.stringify({ root: true }),
+                        "index.js": "console.log(\"hello\")"
+                    }
+                }).CLIEngine;
+                engine = new CLIEngine();
+
+                // Don't throw "file not found" error.
+                engine.executeOnFiles(".");
+            });
+
+            it("'executeOnFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", () => {
+                CLIEngine = defineCLIEngineWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({ ignorePatterns: ["/subdir"] }),
+                        "subdir/.eslintrc.json": JSON.stringify({ root: true }),
+                        "subdir/index.js": "console.log(\"hello\")"
+                    }
+                }).CLIEngine;
+                engine = new CLIEngine();
+
+                // Don't throw "file not found" error.
+                engine.executeOnFiles("subdir");
+            });
+        });
     });
 
     describe("getConfigForFile", () => {
diff --git a/tests/lib/cli-engine/config-array-factory.js b/tests/lib/cli-engine/config-array-factory.js
index 4f3ade1e6..1fb5661fb 100644
--- a/tests/lib/cli-engine/config-array-factory.js
+++ b/tests/lib/cli-engine/config-array-factory.js
@@ -171,6 +171,7 @@ describe("ConfigArrayFactory", () => {
     describe("'loadFile(filePath, options)' method should load a config file.", () => {
         const basicFiles = {
             "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }",
+            "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }",
             "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }",
             "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }",
             "legacy-yml/.eslintrc": "settings:\n  name: legacy-yml/.eslintrc",
@@ -288,6 +289,7 @@ describe("ConfigArrayFactory", () => {
     describe("'loadInDirectory(directoryPath, options)' method should load the config file of a directory.", () => {
         const basicFiles = {
             "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }",
+            "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }",
             "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }",
             "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }",
             "legacy-yml/.eslintrc": "settings:\n  name: legacy-yml/.eslintrc",
@@ -1497,6 +1499,7 @@ describe("ConfigArrayFactory", () => {
             "node_modules/eslint-plugin-invalid-parser/index.js": "exports.configs = { foo: { parser: 'nonexistent-parser' } }",
             "node_modules/eslint-plugin-invalid-config/index.js": "exports.configs = { foo: {} }",
             "js/.eslintrc.js": "module.exports = { rules: { semi: [2, 'always'] } };",
+            "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };",
             "json/.eslintrc.json": "{ \"rules\": { \"quotes\": [2, \"double\"] } }",
             "package-json/package.json": "{ \"eslintConfig\": { \"env\": { \"es6\": true } } }",
             "yaml/.eslintrc.yaml": "env:\n    browser: true"
@@ -1747,6 +1750,22 @@ describe("ConfigArrayFactory", () => {
             });
         });
 
+        it("should load information from a JavaScript file with a .cjs extension", () => {
+            const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
+                files: {
+                    "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };"
+                }
+            });
+            const factory = new ConfigArrayFactory();
+            const config = load(factory, "cjs/.eslintrc.cjs");
+
+            assertConfig(config, {
+                rules: {
+                    semi: [2, "always"]
+                }
+            });
+        });
+
         it("should throw error when loading invalid JavaScript file", () => {
             const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
                 files: {
diff --git a/tests/lib/cli-engine/file-enumerator.js b/tests/lib/cli-engine/file-enumerator.js
index 3d05f63ab..c62578c91 100644
--- a/tests/lib/cli-engine/file-enumerator.js
+++ b/tests/lib/cli-engine/file-enumerator.js
@@ -380,7 +380,7 @@ describe("FileEnumerator", () => {
 
                     assert.throws(() => {
                         listFiles(patterns);
-                    }, `No files matching '${patterns[0]}' were found.`);
+                    }, `All files matched by '${patterns[0]}' are ignored.`);
                 });
 
                 it("should return an ignored file, if ignore option is turned off", () => {
diff --git a/tests/lib/cli-engine/lint-result-cache.js b/tests/lib/cli-engine/lint-result-cache.js
index 7c5cc20a1..a3b6ee3ab 100644
--- a/tests/lib/cli-engine/lint-result-cache.js
+++ b/tests/lib/cli-engine/lint-result-cache.js
@@ -120,6 +120,35 @@ describe("LintResultCache", () => {
             lintResultsCache = new LintResultCache(cacheFileLocation);
         });
 
+        describe("when calculating the hashing", () => {
+            it("contains eslint version during hashing", () => {
+                const version = "eslint-=-version";
+                const NewLintResultCache = proxyquire("../../../lib/cli-engine/lint-result-cache.js", {
+                    "../../package.json": { version },
+                    "./hash": hashStub
+                });
+                const newLintResultCache = new NewLintResultCache(cacheFileLocation);
+
+                newLintResultCache.getCachedLintResults(filePath, fakeConfig);
+                assert.ok(hashStub.calledOnce);
+                assert.ok(hashStub.calledWithMatch(version));
+            });
+
+            it("contains node version during hashing", () => {
+                const version = "node-=-version";
+
+                sinon.stub(process, "version").value(version);
+                const NewLintResultCache = proxyquire("../../../lib/cli-engine/lint-result-cache.js", {
+                    "./hash": hashStub
+                });
+                const newLintResultCache = new NewLintResultCache(cacheFileLocation);
+
+                newLintResultCache.getCachedLintResults(filePath, fakeConfig);
+                assert.ok(hashStub.calledOnce);
+                assert.ok(hashStub.calledWithMatch(version));
+            });
+        });
+
         describe("When file is changed", () => {
             beforeEach(() => {
                 hashStub.returns(hashOfConfig);
diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js
index 6ab341ccc..4abb053ab 100644
--- a/tests/lib/rule-tester/rule-tester.js
+++ b/tests/lib/rule-tester/rule-tester.js
@@ -1018,29 +1018,33 @@ describe("RuleTester", () => {
         });
 
         it("should support explicitly expecting no suggestions", () => {
-            ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/no-eval"), {
-                valid: [],
-                invalid: [{
-                    code: "eval('var foo');",
-                    errors: [{
-                        suggestions: void 0
-                    }]
-                }]
-            });
-        });
-
-        it("should fail when expecting no suggestions and there are suggestions", () => {
-            assert.throws(() => {
-                ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/suggestions").basic, {
+            [void 0, null, false, []].forEach(suggestions => {
+                ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/no-eval"), {
                     valid: [],
                     invalid: [{
-                        code: "var foo;",
+                        code: "eval('var foo');",
                         errors: [{
-                            suggestions: void 0
+                            suggestions
                         }]
                     }]
                 });
-            }, "Error should have no suggestions on error with message: \"Avoid using identifiers named 'foo'.\"");
+            });
+        });
+
+        it("should fail when expecting no suggestions and there are suggestions", () => {
+            [void 0, null, false, []].forEach(suggestions => {
+                assert.throws(() => {
+                    ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/suggestions").basic, {
+                        valid: [],
+                        invalid: [{
+                            code: "var foo;",
+                            errors: [{
+                                suggestions
+                            }]
+                        }]
+                    });
+                }, "Error should have no suggestions on error with message: \"Avoid using identifiers named 'foo'.\"");
+            });
         });
 
         it("should fail when testing for suggestions that don't exist", () => {
diff --git a/tests/lib/rules/array-bracket-spacing.js b/tests/lib/rules/array-bracket-spacing.js
index 120c90501..33caf0889 100644
--- a/tests/lib/rules/array-bracket-spacing.js
+++ b/tests/lib/rules/array-bracket-spacing.js
@@ -190,7 +190,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -208,7 +210,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -217,7 +221,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 36
+                    column: 36,
+                    endLine: 1,
+                    endColumn: 37
                 }
             ]
         },
@@ -233,7 +239,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -242,7 +250,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 35
+                    column: 34,
+                    endLine: 1,
+                    endColumn: 35
                 }
             ]
         },
@@ -258,7 +268,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -267,7 +279,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 50
+                    column: 49,
+                    endLine: 1,
+                    endColumn: 50
                 }
             ]
         },
@@ -285,7 +299,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -294,7 +310,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 19
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
                 }
             ]
         },
@@ -310,7 +328,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 18
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 18
                 }
             ]
         },
@@ -326,7 +346,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -335,7 +357,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 17
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 18
                 }
             ]
         },
@@ -353,7 +377,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -369,7 +395,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 31
+                    column: 30,
+                    endLine: 1,
+                    endColumn: 31
                 }
             ]
         },
@@ -385,7 +413,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 34
+                    column: 33,
+                    endLine: 1,
+                    endColumn: 34
                 }
             ]
         },
@@ -401,7 +431,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -417,7 +449,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -426,7 +460,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 35
+                    column: 34,
+                    endLine: 1,
+                    endColumn: 35
                 }
             ]
         },
@@ -444,7 +480,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -453,7 +491,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 9
+                column: 9,
+                endLine: 1,
+                endColumn: 10
             }]
         },
         {
@@ -468,7 +508,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -483,7 +525,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -492,7 +536,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 12
+                column: 12,
+                endLine: 1,
+                endColumn: 13
             }]
         },
         {
@@ -507,7 +553,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 13
+                column: 13,
+                endLine: 1,
+                endColumn: 14
             }]
         },
         {
@@ -522,7 +570,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -531,7 +581,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 14
+                column: 14,
+                endLine: 1,
+                endColumn: 15
             }]
         },
         {
@@ -546,7 +598,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -561,7 +615,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 6,
+                endLine: 1,
+                endColumn: 7
             }]
         },
         {
@@ -576,7 +632,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 1
+                column: 2,
+                endLine: 1,
+                endColumn: 3
             }]
         },
         {
@@ -591,7 +649,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 15
+                column: 14,
+                endLine: 1,
+                endColumn: 15
             }]
         },
 
@@ -608,7 +668,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -617,7 +679,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 29
+                    column: 29,
+                    endLine: 1,
+                    endColumn: 30
                 }
             ]
         },
@@ -633,7 +697,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -651,7 +717,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -669,7 +737,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -678,7 +748,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 22
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 23
                 }
             ]
         },
@@ -694,7 +766,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 }
             ]
         },
@@ -710,7 +784,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 23
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
                 }
             ]
         },
@@ -728,7 +804,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -737,7 +815,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 24
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
                 }
             ]
         },
@@ -753,7 +833,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 23
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 23
                 }
             ]
         },
@@ -769,7 +851,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -785,7 +869,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceAfter",
@@ -794,7 +880,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 13
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         },
@@ -810,7 +898,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 15
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 15
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -819,7 +909,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 26
+                    column: 25,
+                    endLine: 1,
+                    endColumn: 26
                 }
             ]
         },
@@ -841,7 +933,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 2
+                    column: 3,
+                    endLine: 1,
+                    endColumn: 4
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -850,7 +944,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 9
+                    column: 8,
+                    endLine: 1,
+                    endColumn: 9
                 }
             ]
         },
@@ -870,7 +966,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 2
+                    column: 2,
+                    endLine: 1,
+                    endColumn: 3
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -879,7 +977,152 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 7
+                    column: 7,
+                    endLine: 1,
+                    endColumn: 8
+                }
+            ]
+        },
+
+        // multiple spaces
+        {
+            code: "var arr = [  1, 2   ];",
+            output: "var arr = [1, 2];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 14
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 21
+                }
+            ]
+        },
+        {
+            code: "function f( [   a, b  ] ) {}",
+            output: "function f( [a, b] ) {}",
+            options: ["never"],
+            parserOptions: {
+                ecmaVersion: 6
+            },
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 17
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 21,
+                    endLine: 1,
+                    endColumn: 23
+                }
+            ]
+        },
+        {
+            code: "var arr = [ 1,\n   2   ];",
+            output: "var arr = [1,\n   2];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 5,
+                    endLine: 2,
+                    endColumn: 8
+                }
+            ]
+        },
+        {
+            code: "var arr = [  1, [ 2, 3  ] ];",
+            output: "var arr = [1, [2, 3]];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 14
+                },
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 25
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 26,
+                    endLine: 1,
+                    endColumn: 27
                 }
             ]
         }
diff --git a/tests/lib/rules/brace-style.js b/tests/lib/rules/brace-style.js
index 4444863b6..70211608b 100644
--- a/tests/lib/rules/brace-style.js
+++ b/tests/lib/rules/brace-style.js
@@ -82,6 +82,22 @@ ruleTester.run("brace-style", rule, {
         { code: "if (foo) {}\nelse {}", options: ["allman", { allowSingleLine: true }] },
         { code: "try {  bar(); }\ncatch (e) { baz();  }", options: ["allman", { allowSingleLine: true }] },
         { code: "var foo = () => { return; }", options: ["allman", { allowSingleLine: true }], parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "if (foo) { baz(); } else {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "if (foo) { baz(); } else if (bar) {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "if (foo) { baz(); } else\nif (bar) {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "try { somethingRisky(); } catch(e) {\n  handleError();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
         {
             code: "if (tag === 1) fontstack.name = pbf.readString(); \nelse if (tag === 2) fontstack.range = pbf.readString(); \nelse if (tag === 3) {\n var glyph = pbf.readMessage(readGlyph, {});\n fontstack.glyphs[glyph.id] = glyph; \n}",
             options: ["1tbs"]
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index 9225b4341..3a4f0aa73 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -359,6 +359,16 @@ ruleTester.run("comma-dangle", rule, {
         },
 
         // trailing comma in functions
+        {
+            code: "function foo(a) {} ",
+            options: [{}],
+            parserOptions: { ecmaVersion: 8 }
+        },
+        {
+            code: "foo(a)",
+            options: [{}],
+            parserOptions: { ecmaVersion: 8 }
+        },
         {
             code: "function foo(a) {} ",
             options: [{ functions: "never" }],
diff --git a/tests/lib/rules/no-multiple-empty-lines.js b/tests/lib/rules/no-multiple-empty-lines.js
index 5c51dd811..7b14f75ae 100644
--- a/tests/lib/rules/no-multiple-empty-lines.js
+++ b/tests/lib/rules/no-multiple-empty-lines.js
@@ -316,6 +316,32 @@ ruleTester.run("no-multiple-empty-lines", rule, {
             output: "foo\n",
             options: [{ max: 1, maxEOF: 0 }],
             errors: [getExpectedErrorEOF(0)]
+        },
+        {
+
+            // https://github.com/eslint/eslint/pull/12594
+            code: "var a;\n\n\n\n\nvar b;",
+            output: "var a;\n\nvar b;",
+            options: [{ max: 1 }],
+            errors: [{
+                message: "More than 1 blank line not allowed.",
+                type: "Program",
+                line: 3,
+                column: 1
+            }]
+        },
+        {
+
+            // https://github.com/eslint/eslint/pull/12594
+            code: "var a;\n\n\n\n\nvar b;",
+            output: "var a;\n\n\nvar b;",
+            options: [{ max: 2 }],
+            errors: [{
+                message: "More than 2 blank lines not allowed.",
+                type: "Program",
+                line: 4,
+                column: 1
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js
index ac97bc137..15ee089b2 100644
--- a/tests/lib/rules/no-restricted-imports.js
+++ b/tests/lib/rules/no-restricted-imports.js
@@ -20,6 +20,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6, sourceType:
 
 ruleTester.run("no-restricted-imports", rule, {
     valid: [
+        "import os from \"os\";",
         { code: "import os from \"os\";", options: ["osx"] },
         { code: "import fs from \"fs\";", options: ["crypto"] },
         { code: "import path from \"path\";", options: ["crypto", "stream", "os"] },
diff --git a/tests/lib/rules/no-unexpected-multiline.js b/tests/lib/rules/no-unexpected-multiline.js
index 5811015c3..6d0eba33c 100644
--- a/tests/lib/rules/no-unexpected-multiline.js
+++ b/tests/lib/rules/no-unexpected-multiline.js
@@ -82,7 +82,35 @@ ruleTester.run("no-unexpected-multiline", rule, {
         `
             5 / (5
             / 5)
-        `
+        `,
+
+        // https://github.com/eslint/eslint/issues/11650
+        {
+            code: `
+                tag<generic>\`
+                    multiline
+                \`;
+            `,
+            parser: require.resolve("../../fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-1")
+        },
+        {
+            code: `
+                tag<
+                  generic
+                >\`
+                    multiline
+                \`;
+            `,
+            parser: require.resolve("../../fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-2")
+        },
+        {
+            code: `
+                tag<
+                  generic
+                >\`multiline\`;
+            `,
+            parser: require.resolve("../../fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-3")
+        }
     ],
     invalid: [
         {
@@ -215,6 +243,25 @@ ruleTester.run("no-unexpected-multiline", rule, {
                 column: 17,
                 messageId: "division"
             }]
+        },
+
+        // https://github.com/eslint/eslint/issues/11650
+        {
+            code: `
+                const x = aaaa<
+                    test
+                >/*
+                test
+                */\`foo\`
+            `,
+            parser: require.resolve("../../fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-and-comment"),
+            errors: [
+                {
+                    line: 1,
+                    column: 11,
+                    messageId: "taggedTemplate"
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/no-unsafe-negation.js b/tests/lib/rules/no-unsafe-negation.js
index 9493bbb72..23e6cd5ce 100644
--- a/tests/lib/rules/no-unsafe-negation.js
+++ b/tests/lib/rules/no-unsafe-negation.js
@@ -17,27 +17,6 @@ const rule = require("../../../lib/rules/no-unsafe-negation"),
 //------------------------------------------------------------------------------
 
 const ruleTester = new RuleTester();
-const unexpectedInError = { messageId: "unexpected", data: { operator: "in" } };
-const unexpectedInstanceofError = {
-    messageId: "unexpected",
-    data: { operator: "instanceof" }
-};
-const unexpectedLessThanOperatorError = {
-    messageId: "unexpected",
-    data: { operator: "<" }
-};
-const unexpectedMoreThanOperatorError = {
-    messageId: "unexpected",
-    data: { operator: ">" }
-};
-const unexpectedMoreThanOrEqualOperatorError = {
-    messageId: "unexpected",
-    data: { operator: ">=" }
-};
-const unexpectedLessThanOrEqualOperatorError = {
-    messageId: "unexpected",
-    data: { operator: "<=" }
-};
 
 ruleTester.run("no-unsafe-negation", rule, {
     valid: [
@@ -83,52 +62,194 @@ ruleTester.run("no-unsafe-negation", rule, {
     invalid: [
         {
             code: "!a in b",
-            errors: [unexpectedInError]
+            errors: [{
+                message: "Unexpected negating the left operand of 'in' operator.",
+                suggestions: [
+                    {
+                        desc: "Negate 'in' expression instead of its left operand. This changes the current behavior.",
+                        output: "!(a in b)"
+                    },
+                    {
+                        desc: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior.",
+                        output: "(!a) in b"
+                    }
+                ]
+            }]
         },
         {
             code: "(!a in b)",
-            errors: [unexpectedInError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "in" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "(!(a in b))"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "((!a) in b)"
+                    }
+                ]
+            }]
         },
         {
             code: "!(a) in b",
-            errors: [unexpectedInError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "in" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!((a) in b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!(a)) in b"
+                    }
+                ]
+            }]
         },
         {
             code: "!a instanceof b",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!(a instanceof b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!a) instanceof b"
+                    }
+                ]
+            }]
         },
         {
             code: "(!a instanceof b)",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "(!(a instanceof b))"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "((!a) instanceof b)"
+                    }
+                ]
+            }]
         },
         {
             code: "!(a) instanceof b",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!((a) instanceof b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!(a)) instanceof b"
+                    }
+                ]
+            }]
         },
         {
             code: "if (! a < b) {}",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "if (!( a < b)) {}"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "if ((! a) < b) {}"
+                    }
+                ]
+            }]
         },
         {
             code: "while (! a > b) {}",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedMoreThanOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: ">" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "while (!( a > b)) {}"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "while ((! a) > b) {}"
+                    }
+                ]
+            }]
         },
         {
             code: "foo = ! a <= b;",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "foo = !( a <= b);"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "foo = (! a) <= b;"
+                    }
+                ]
+            }]
         },
         {
             code: "foo = ! a >= b;",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedMoreThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: ">=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "foo = !( a >= b);"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "foo = (! a) >= b;"
+                    }
+                ]
+            }]
         },
         {
             code: "! a <= b",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!( a <= b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(! a) <= b"
+                    }
+                ]
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/prefer-numeric-literals.js b/tests/lib/rules/prefer-numeric-literals.js
index ddd6e36c8..4d3037f44 100644
--- a/tests/lib/rules/prefer-numeric-literals.js
+++ b/tests/lib/rules/prefer-numeric-literals.js
@@ -31,7 +31,28 @@ ruleTester.run("prefer-numeric-literals", rule, {
         "parseInt(foo);",
         "parseInt(foo, 2);",
         "Number.parseInt(foo);",
-        "Number.parseInt(foo, 2);"
+        "Number.parseInt(foo, 2);",
+        "parseInt(11, 2);",
+        "Number.parseInt(1, 8);",
+        "parseInt(1e5, 16);",
+        "parseInt('11', '2');",
+        "Number.parseInt('11', '8');",
+        {
+            code: "parseInt('11', 2n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "Number.parseInt('11', 8n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "parseInt('11', 16n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "parseInt(1n, 2);",
+            parserOptions: { ecmaVersion: 2020 }
+        }
     ],
     invalid: [
         {
diff --git a/tests/lib/shared/config-validator.js b/tests/lib/shared/config-validator.js
index 1c4cfe895..95976fc9f 100644
--- a/tests/lib/shared/config-validator.js
+++ b/tests/lib/shared/config-validator.js
@@ -114,6 +114,7 @@ describe("Validator", () => {
         it("should do nothing with a valid eslint config", () => {
             validator.validate(
                 {
+                    $schema: "http://json.schemastore.org/eslintrc",
                     root: true,
                     globals: { globalFoo: "readonly" },
                     parser: "parserFoo",
diff --git a/tests/lib/source-code/source-code.js b/tests/lib/source-code/source-code.js
index 29dbf1d6f..e89f9a328 100644
--- a/tests/lib/source-code/source-code.js
+++ b/tests/lib/source-code/source-code.js
@@ -2076,6 +2076,69 @@ describe("SourceCode", () => {
                     });
                 });
             });
+
+            it("JSXText tokens that contain only whitespaces should NOT be handled as space", () => {
+                const code = "let jsx = <div>\n   {content}\n</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+                const interpolation = jsx.children[1];
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.openingElement, interpolation),
+                    false
+                );
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(interpolation, jsx.closingElement),
+                    false
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(interpolation, jsx.openingElement),
+                    false
+                );
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.closingElement, interpolation),
+                    false
+                );
+            });
+
+            it("JSXText tokens that contain both letters and whitespaces should NOT be handled as space", () => {
+                const code = "let jsx = <div>\n   Hello\n</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.openingElement, jsx.closingElement),
+                    false
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.closingElement, jsx.openingElement),
+                    false
+                );
+            });
+
+            it("JSXText tokens that contain only letters should NOT be handled as space", () => {
+                const code = "let jsx = <div>Hello</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.openingElement, jsx.closingElement),
+                    false
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetween(jsx.closingElement, jsx.openingElement),
+                    false
+                );
+            });
         });
 
         describe("should return false either of the arguments' location is inside the other one", () => {
@@ -2409,6 +2472,69 @@ describe("SourceCode", () => {
                     });
                 });
             });
+
+            it("JSXText tokens that contain only whitespaces should be handled as space", () => {
+                const code = "let jsx = <div>\n   {content}\n</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+                const interpolation = jsx.children[1];
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.openingElement, interpolation),
+                    true
+                );
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(interpolation, jsx.closingElement),
+                    true
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(interpolation, jsx.openingElement),
+                    true
+                );
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.closingElement, interpolation),
+                    true
+                );
+            });
+
+            it("JSXText tokens that contain both letters and whitespaces should be handled as space", () => {
+                const code = "let jsx = <div>\n   Hello\n</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.openingElement, jsx.closingElement),
+                    true
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.closingElement, jsx.openingElement),
+                    true
+                );
+            });
+
+            it("JSXText tokens that contain only letters should NOT be handled as space", () => {
+                const code = "let jsx = <div>Hello</div>";
+                const ast = espree.parse(code, { ...DEFAULT_CONFIG, ecmaFeatures: { jsx: true } });
+                const sourceCode = new SourceCode(code, ast);
+                const jsx = ast.body[0].declarations[0].init;
+
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.openingElement, jsx.closingElement),
+                    false
+                );
+
+                // Reversed order
+                assert.strictEqual(
+                    sourceCode.isSpaceBetweenTokens(jsx.closingElement, jsx.openingElement),
+                    false
+                );
+            });
         });
 
         describe("should return false either of the arguments' location is inside the other one", () => {