Repository: eslint/eslint
Pull request #10040 (2018-03-01 21:29:20)

Update: Add --fix for one-var rule (refs #9072)
**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[x] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

#9072


**What changes did you make? (Give an overview)**
Added support for `--fix` to the `one-var` rule going from one to many statements

**Is there anything you'd like reviewers to focus on?**
The formatting of the output is correct



jsf-clabot: [![CLA assistant check](https://cla.js.foundation/pull/badge/not_signed)](https://cla.js.foundation/eslint/eslint?pullRequest=10040) <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint?pullRequest=10040) before we can accept your contribution.<br/><hr/>**Sebastian Malton** seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please [add the email address used for this commit to your account](https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/#commits-are-not-linked-to-any-user).
Nokel81: @j-f1 Thank you for the starting point on this PR, your work helped a lot
platinumazure: Would you mind updating your commit message/PR title to be a little more descriptive? Also, it should end with "(fixes #9072)". Thanks!
Nokel81: Done
Nokel81: I will look into fixing the many-to-one direction today
not-an-aardvark: @Nokel81 Thanks for working on this! To clarify, are you planning to add support for the many-to-one direction in this PR, or are you planning to make a separate PR after this gets merged?

I think there is a build failure due to some changes on master since you started working on this, but this can be merged after the build failure is fixed.
Nokel81: I have finished the code work for the many-to-one direction. I just have to add some more test cases 
Nokel81: But I have come across an odd issue where the lint is reporting an error where I don't think that there should be one. I will post the case here in about an hour. So I might try and fix that too
Aladdin-ADD: I guess the current behavior is fine. Since ESLint rule is separate from others, it would be also fixed (if possible ).

thanks for doing this! I want it eagerly~ ❤
Nokel81: Since this is not a breaking change, will this go out with the next release?

Patch:
diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
new file mode 100644
index 000000000..ef8c5101c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
@@ -0,0 +1,54 @@
+---
+name: Bug report
+about: Report an issue with ESLint or rules bundled with ESLint
+
+---
+
+<!--
+    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
+
+    This template is for bug reports. If you are here for another reason, please see below:
+
+    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
+    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
+    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
+    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
+
+    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
+-->
+
+**Tell us about your environment**
+
+* **ESLint Version:**
+* **Node Version:**
+* **npm Version:**
+
+**What parser (default, Babel-ESLint, etc.) are you using?**
+
+**Please show your full configuration:**
+
+<details>
+<summary>Configuration</summary>
+
+<!-- Paste your configuration below: -->
+```js
+
+```
+
+</details>
+
+**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**
+
+<!-- Paste the source code below: -->
+```js
+
+```
+
+<!-- Paste the command you used to run ESLint: -->
+```bash
+
+```
+
+**What did you expect to happen?**
+
+**What actually happened? Please include the actual, raw output from ESLint.**
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/CHANGE.md b/.github/ISSUE_TEMPLATE/CHANGE.md
index b8181f56c..14cff91b0 100644
--- a/.github/ISSUE_TEMPLATE/CHANGE.md
+++ b/.github/ISSUE_TEMPLATE/CHANGE.md
@@ -1,3 +1,9 @@
+---
+name: Non-rule change request
+about: Request a change that is not a bug fix, rule change, or new rule
+
+---
+
 <!--
     ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
 
@@ -11,15 +17,9 @@
     Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
 -->
 
-**Tell us about your environment**
-
-* **ESLint Version:**
-* **Node Version:**
-* **npm Version:**
-
-**What did you do?**
+**The version of ESLint you are using.**
 
-**What happened?**
+**The problem you want to solve.**
 
-**What did you expect to happen?**
+**Your take on the correct solution to problem.**
 
diff --git a/.github/ISSUE_TEMPLATE/NEW_RULE.md b/.github/ISSUE_TEMPLATE/NEW_RULE.md
index 81248324b..454b28e40 100644
--- a/.github/ISSUE_TEMPLATE/NEW_RULE.md
+++ b/.github/ISSUE_TEMPLATE/NEW_RULE.md
@@ -1,3 +1,9 @@
+---
+name: New rule proposal
+about: Propose a new rule to be added to ESLint
+
+---
+
 <!--
     ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
 
diff --git a/.github/ISSUE_TEMPLATE/RULE_CHANGE.md b/.github/ISSUE_TEMPLATE/RULE_CHANGE.md
index b68b90714..7b0c65379 100644
--- a/.github/ISSUE_TEMPLATE/RULE_CHANGE.md
+++ b/.github/ISSUE_TEMPLATE/RULE_CHANGE.md
@@ -1,3 +1,9 @@
+---
+name: Rule change request
+about: Request a change to an existing rule
+
+---
+
 <!--
     ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
 
diff --git a/.travis.yml b/.travis.yml
index d481188d3..5763f04af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,6 @@
 language: node_js
 node_js:
-    - "4"
-    - "5"
     - "6"
-    - "7"
     - "8"
     - "9"
 sudo: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdf338ffa..9ceed89e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,55 @@
+v5.0.0-alpha.2 - April 27, 2018
+
+* 510ca8b Docs: make grammatical tweaks in migration guide (#10278) (Teddy Katz)
+* 02e44a5 Breaking: remove TDZ scopes (fixes #10245) (#10270) (Toru Nagashima)
+* c74933b Breaking: remove extra check in getScope (fixes #10246, fixes #10247) (#10252) (Toru Nagashima)
+* 7c2e83a Chore: improve tests and checking for equality (#10182) (Ruben Bridgewater)
+* 8799972 Docs: make template link wording more clear (#10219) (David Luzar)
+* 8b7c6ea Breaking: report fatal error for linting nonexistent files (fixes #7390) (#10143) (Teddy Katz)
+* 9100819 Breaking: fix plugin resolver in extends (fixes #9904) (#10236) (Toru Nagashima)
+* c45f1d0 Breaking: add rules to recommended (fixes #8865) (#10158) (薛定谔的猫)
+* 1d443a0 Fix: valid-jsdoc does not know async function returns (fixes #9881) (#10161) (Rachael Sim)
+* a82cbea Update: re-enable experimentalObjectRestSpread (fixes #9990) (#10230) (Toru Nagashima)
+* f9c7371 Fix: do not autofix object-shorthand with comments (fixes #10038) (#10238) (Malcolm Groves)
+* 4672b56 Docs: Correct wording in the `smart-tabs` docs page (#10277) (Jed Fox)
+* b32d1f4 Chore: upgrade eslump@1.6.2 (#10258) (薛定谔的猫)
+* 7938bf1 Chore: update eslint-fuzzer ecmaVersion to 2018 (#10255) (薛定谔的猫)
+* a2953ec Chore: small opt to improve readability (#10225) (薛定谔的猫)
+* 85a5191 Docs: Update JSCS FAQ (#10221) (alberto)
+* 8e89d5c Docs: Fix typo (#10223) (alberto)
+* c0c331e Docs: Add Prettier to FAQ (#10222) (alberto)
+* 2443627 Docs: add backticks in getter-return (#10218) (薛定谔的猫)
+* 74bb5b5 Docs: Fix misspelling in changelog (#10216) (Kevin Partington)
+
+v5.0.0-alpha.1 - April 13, 2018
+
+* b2a48a9 Breaking: stop using fake `context._linter` property (fixes #10140) (#10209) (Teddy Katz)
+* a039956 Breaking: remove deprecated browser/jest/node globals (fixes #10141) (#10210) (Teddy Katz)
+* 98f1cad Docs: update migration guide with latest changes (#10212) (Teddy Katz)
+* 2e60017 Chore: remove concat-stream dependency (#10173) (Teddy Katz)
+* 7f69f11 Chore:  rearrange init options. (#10131) (薛定谔的猫)
+* f595fd8 Upgrade: upgrade deps (#10184) (alberto)
+* 71167be Docs: fix wrong config in id-length (#10196) (薛定谔的猫)
+* 81629d2 Chore: enable rest/spread rules on ESLint codebase (#10211) (Teddy Katz)
+* 2324570 Breaking: no-unused-vars reports all after-used params (fixes #9909) (#10119) (Kevin Partington)
+* 7765fc4 Upgrade: ajv@^6.0.1, still using json schema draft 04 (#9856) (Kevin Partington)
+* b77846d Breaking: drop supporting Node.js 4 (fixes #10052) (#10074) (薛定谔的猫)
+* cd34d44 Chore: avoid modifying global state when tests fail (#10201) (Teddy Katz)
+* 731da1e Docs: fix code in correct example. (#10195) (薛定谔的猫)
+* 3780915 Docs: fix some small errors in examples (#10194) (薛定谔的猫)
+* 869c9f5 Upgrade: babelify (#10185) (alberto)
+* 218ee57 Fix: report no-case-declarations from declarations (fixes #10048) (#10167) (Carlo Abelli)
+* b7ee1ed Upgrade: upgrade devdeps (#10178) (alberto)
+* db1a582 Chore: Add debug logging for CLI args as they came in (#10174) (Kevin Partington)
+* f3a0291 Upgrade: Update dependencies. (#10168) (alberto)
+* 7d6e052 Upgrade: esquery@^1.0.1 (fixes #8733) (#10170) (Kevin Partington)
+* 1e7252f Docs: Add more related rules for object-curly-spacing (#10175) (Saugat Acharya)
+* e5cf9cc Docs: Reorder README sections (#10172) (alberto)
+* c85578f Chore: Remove `esprima-fb` dependency. (#10171) (alberto)
+* d0dc2e3 Docs: Add Missing Quotes (#10162) (Samarth Verma)
+* 7a63bfa Upgrade: eslint-release to v0.11.1 (#10156) (Teddy Katz)
+* b7a1a7a Build: Gensite creates prerelease dirs if needed (#10154) (Brandon Mills)
+
 v5.0.0-alpha.0 - March 30, 2018
 
 * f4b3af5 Breaking: Upgrade to Espree v4 alpha (refs #9990) (#10152) (Brandon Mills)
@@ -3856,7 +3908,7 @@ v0.5.1 - April 17, 2014
 * Docs: Updated contributor guidelines (Nicholas C. Zakas)
 * Added Mocha global variables for TDD style. Fixes #793. (Golo Roden)
 * Rule: no-sequences (fixes #561) (Brandon Mills)
-* Change .eslintingore to plain text (fixes #761) (Brandon Mills)
+* Change .eslintignore to plain text (fixes #761) (Brandon Mills)
 * Change 'no-spaced-func' message (fixes #762) (Aliaksei Shytkin)
 * Rule 'block-scoped-var' works correct when object inits (fixes #783) (Aliaksei Shytkin)
 * Build: Always build docs site on top of origin/master (Nicholas C. Zakas)
diff --git a/Makefile.js b/Makefile.js
index 63b6204fa..78063832f 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -979,10 +979,7 @@ function createConfigForPerformanceTest() {
         "rules:"
     ];
 
-    content.push.apply(
-        content,
-        ls("lib/rules").map(fileName => `    ${path.basename(fileName, ".js")}: 1`)
-    );
+    content.push(...ls("lib/rules").map(fileName => `    ${path.basename(fileName, ".js")}: 1`));
 
     content.join("\n").to(PERF_ESLINTRC);
 }
diff --git a/README.md b/README.md
index ccf0cda62..cb8c0277d 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
 
 ## Installation and Usage
 
-Prerequisites: [Node.js](https://nodejs.org/en/) (>=4.x), npm version 2+.
+Prerequisites: [Node.js](https://nodejs.org/en/) (>=6.14), npm version 3+.
 
 There are two ways to install ESLint: globally and locally.
 
@@ -113,19 +113,15 @@ Before filing an issue, please be sure to read the guidelines for what you're re
 
 ## Frequently Asked Questions
 
-### I heard ESLint is going to replace JSCS?
+### I'm using JSCS, should I migrate to ESLint?
 
-Yes. Since we are solving the same problems, ESLint and JSCS teams have decided to join forces and work together in the development of ESLint instead of competing with each other. You can read more about this in both [ESLint](https://eslint.org/blog/2016/04/welcoming-jscs-to-eslint) and [JSCS](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2#.u76sx334n) announcements.
+Maybe, depending on how much you need it. [JSCS has reached end of life](https://eslint.org/blog/2016/07/jscs-end-of-life), but if it is working for you then there is no reason to move yet. There are still [a few issues](https://github.com/eslint/eslint/milestones/JSCS%20Compatibility) pending. We’ll announce when all of the changes necessary to support JSCS users in ESLint are complete and will start encouraging JSCS users to switch to ESLint at that time.
 
-### So, should I stop using JSCS and start using ESLint?
+If you are having issues with JSCS, you can try to move to ESLint. Have a look at our [migration guide](https://eslint.org/docs/user-guide/migrating-from-jscs).
 
-Maybe, depending on how much you need it. [JSCS has reached end of life](https://eslint.org/blog/2016/07/jscs-end-of-life), but if it is working for you then there is no reason to move yet. We are still working to smooth the transition. You can see our progress [here](https://github.com/eslint/eslint/milestones/JSCS%20Compatibility). We’ll announce when all of the changes necessary to support JSCS users in ESLint are complete and will start encouraging JSCS users to switch to ESLint at that time.
+### Does Prettier replace ESLint?
 
-If you are having issues with JSCS, you can try to move to ESLint. We are focusing our time and energy on JSCS compatibility issues.
-
-### Is ESLint just linting or does it also check style?
-
-ESLint does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use it for both.
+No, ESLint does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use ESLint for everything, or you can combine both using Prettier to format your code and ESLint to catch possible errors.
 
 ### Why can't ESLint find my plugins?
 
diff --git a/bin/eslint.js b/bin/eslint.js
index 5e2e91d7a..1255e3d8b 100755
--- a/bin/eslint.js
+++ b/bin/eslint.js
@@ -27,8 +27,7 @@ if (debug) {
 //------------------------------------------------------------------------------
 
 // now we can safely include the other modules that use debug
-const concat = require("concat-stream"),
-    cli = require("../lib/cli"),
+const cli = require("../lib/cli"),
     path = require("path"),
     fs = require("fs");
 
@@ -57,9 +56,7 @@ process.once("uncaughtException", err => {
 });
 
 if (useStdIn) {
-    process.stdin.pipe(concat({ encoding: "string" }, text => {
-        process.exitCode = cli.execute(process.argv, text);
-    }));
+    process.exitCode = cli.execute(process.argv, fs.readFileSync(process.stdin.fd, "utf8"));
 } else if (init) {
     const configInit = require("../lib/config/config-initializer");
 
diff --git a/conf/environments.js b/conf/environments.js
index 13020ebb5..1c2b12eed 100644
--- a/conf/environments.js
+++ b/conf/environments.js
@@ -19,126 +19,10 @@ module.exports = {
         globals: globals.es5
     },
     browser: {
-
-        /*
-         * For backward compatibility.
-         * Remove those on the next major release.
-         */
-        globals: Object.assign(
-            {
-                AutocompleteErrorEvent: false,
-                CDATASection: false,
-                ClientRect: false,
-                ClientRectList: false,
-                CSSAnimation: false,
-                CSSTransition: false,
-                CSSUnknownRule: false,
-                CSSViewportRule: false,
-                Debug: false,
-                DocumentTimeline: false,
-                DOMSettableTokenList: false,
-                ElementTimeControl: false,
-                FederatedCredential: false,
-                FileError: false,
-                HTMLAppletElement: false,
-                HTMLBlockquoteElement: false,
-                HTMLIsIndexElement: false,
-                HTMLKeygenElement: false,
-                HTMLLayerElement: false,
-                IDBEnvironment: false,
-                InputMethodContext: false,
-                MediaKeyError: false,
-                MediaKeyEvent: false,
-                MediaKeys: false,
-                opera: false,
-                PasswordCredential: false,
-                ReadableByteStream: false,
-                SharedKeyframeList: false,
-                showModalDialog: false,
-                SiteBoundCredential: false,
-                SVGAltGlyphDefElement: false,
-                SVGAltGlyphElement: false,
-                SVGAltGlyphItemElement: false,
-                SVGAnimateColorElement: false,
-                SVGAnimatedPathData: false,
-                SVGAnimatedPoints: false,
-                SVGColor: false,
-                SVGColorProfileElement: false,
-                SVGColorProfileRule: false,
-                SVGCSSRule: false,
-                SVGCursorElement: false,
-                SVGDocument: false,
-                SVGElementInstance: false,
-                SVGElementInstanceList: false,
-                SVGEvent: false,
-                SVGExternalResourcesRequired: false,
-                SVGFilterPrimitiveStandardAttributes: false,
-                SVGFitToViewBox: false,
-                SVGFontElement: false,
-                SVGFontFaceElement: false,
-                SVGFontFaceFormatElement: false,
-                SVGFontFaceNameElement: false,
-                SVGFontFaceSrcElement: false,
-                SVGFontFaceUriElement: false,
-                SVGGlyphElement: false,
-                SVGGlyphRefElement: false,
-                SVGHKernElement: false,
-                SVGICCColor: false,
-                SVGLangSpace: false,
-                SVGLocatable: false,
-                SVGMissingGlyphElement: false,
-                SVGPaint: false,
-                SVGPathSeg: false,
-                SVGPathSegArcAbs: false,
-                SVGPathSegArcRel: false,
-                SVGPathSegClosePath: false,
-                SVGPathSegCurvetoCubicAbs: false,
-                SVGPathSegCurvetoCubicRel: false,
-                SVGPathSegCurvetoCubicSmoothAbs: false,
-                SVGPathSegCurvetoCubicSmoothRel: false,
-                SVGPathSegCurvetoQuadraticAbs: false,
-                SVGPathSegCurvetoQuadraticRel: false,
-                SVGPathSegCurvetoQuadraticSmoothAbs: false,
-                SVGPathSegCurvetoQuadraticSmoothRel: false,
-                SVGPathSegLinetoAbs: false,
-                SVGPathSegLinetoHorizontalAbs: false,
-                SVGPathSegLinetoHorizontalRel: false,
-                SVGPathSegLinetoRel: false,
-                SVGPathSegLinetoVerticalAbs: false,
-                SVGPathSegLinetoVerticalRel: false,
-                SVGPathSegList: false,
-                SVGPathSegMovetoAbs: false,
-                SVGPathSegMovetoRel: false,
-                SVGRenderingIntent: false,
-                SVGStylable: false,
-                SVGTests: false,
-                SVGTransformable: false,
-                SVGTRefElement: false,
-                SVGURIReference: false,
-                SVGViewSpec: false,
-                SVGVKernElement: false,
-                SVGZoomAndPan: false,
-                SVGZoomEvent: false,
-                TimeEvent: false,
-                XDomainRequest: false,
-                XMLHttpRequestProgressEvent: false,
-                XPathException: false,
-                XPathNamespace: false,
-                XPathNSResolver: false
-            },
-            globals.browser
-        )
+        globals: globals.browser
     },
     node: {
-
-        /*
-         * For backward compatibility.
-         * Remove those on the next major release.
-         */
-        globals: Object.assign(
-            { arguments: false, GLOBAL: false, root: false },
-            globals.node
-        ),
+        globals: globals.node,
         parserOptions: {
             ecmaFeatures: {
                 globalReturn: true
@@ -169,15 +53,7 @@ module.exports = {
         globals: globals.jasmine
     },
     jest: {
-
-        /*
-         * For backward compatibility.
-         * Remove those on the next major release.
-         */
-        globals: Object.assign(
-            { check: false, gen: false },
-            globals.jest
-        )
+        globals: globals.jest
     },
     phantomjs: {
         globals: globals.phantomjs
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 0acee234a..df07c2e3c 100644
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -39,14 +39,14 @@ module.exports = {
         "dot-notation": "off",
         "eol-last": "off",
         eqeqeq: "off",
-        "for-direction": "off",
+        "for-direction": "error",
         "func-call-spacing": "off",
         "func-name-matching": "off",
         "func-names": "off",
         "func-style": "off",
         "function-paren-newline": "off",
         "generator-star-spacing": "off",
-        "getter-return": "off",
+        "getter-return": "error",
         "global-require": "off",
         "guard-for-in": "off",
         "handle-callback-err": "off",
diff --git a/docs/developer-guide/contributing/new-rules.md b/docs/developer-guide/contributing/new-rules.md
index c3fe9f454..a3513773d 100644
--- a/docs/developer-guide/contributing/new-rules.md
+++ b/docs/developer-guide/contributing/new-rules.md
@@ -19,7 +19,7 @@ Even though these are the formal criteria for inclusion, each rule is evaluated
 
 ## Proposing a Rule
 
-If you want to propose a new rule, [create a pull request](/docs/developer-guide/contributing/pull-requests.md) or [new issue](https://github.com/eslint/eslint/issues/new?template=NEW_RULE.md) and fill out the template.
+If you want to propose a new rule, please see how to [create a pull request](/docs/developer-guide/contributing/pull-requests) or submit an issue by filling out a [new rule template](https://github.com/eslint/eslint/issues/new?template=NEW_RULE.md).
 
 We need all of this information in order to determine whether or not the rule is a good core rule candidate.
 
diff --git a/docs/developer-guide/shareable-configs.md b/docs/developer-guide/shareable-configs.md
index cecc74589..41d8b8f35 100644
--- a/docs/developer-guide/shareable-configs.md
+++ b/docs/developer-guide/shareable-configs.md
@@ -110,7 +110,7 @@ As an example, you can create a file called `my-special-config.js` in the root o
 ```js
 module.exports = {
     rules: {
-        quotes: [2, "double"];
+        quotes: [2, "double"]
     }
 };
 ```
diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md
index 2c4da7d32..8bf17bc29 100644
--- a/docs/developer-guide/working-with-custom-formatters.md
+++ b/docs/developer-guide/working-with-custom-formatters.md
@@ -7,7 +7,7 @@ The simplest formatter will be something like:
 ```javascript
 //my-awesome-formatter.js
 module.exports = function (results) {
-    console.log(JSON.stringify(results, null, 2));
+    return JSON.stringify(results, null, 2);
 }
 ```
 
@@ -43,13 +43,17 @@ The output of the previous command will be something like this
         ],
         "errorCount": 2,
         "warningCount": 0,
+        "fixableErrorCount": 0,
+        "fixableWarningCount": 0,
         "source": "var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n"
     },
     {
         "filePath": "Gruntfile.js",
         "messages": [],
         "errorCount": 0,
-        "warningCount": 0
+        "warningCount": 0,
+        "fixableErrorCount": 0,
+        "fixableWarningCount": 0
     }
 ]
 ```
@@ -89,7 +93,6 @@ A formatter that only cares about the total count of errors and warnings will lo
 
 ```javascript
 module.exports = function ( results ) {
-    var results = results || [ ];
 
     // accumulate the errors and warnings
     var summary = results.reduce( function ( seq, current ) {
@@ -99,8 +102,10 @@ module.exports = function ( results ) {
     }, { errors: 0, warnings: 0 } );
 
     if ( summary.errors > 0 || summary.warnings > 0 ) {
-        console.log( 'Errors: ' + summary.errors + ', Warnings: ' + summary.warnings + '\n' );
+        return 'Errors: ' + summary.errors + ', Warnings: ' + summary.warnings + '\n';
     }
+
+    return '';
 };
 ```
 
@@ -254,7 +259,7 @@ It is a bit more complicated, but using a simple formatter we can get the raw ou
 ```javascript
 // json.js
 module.exports = function ( results ) {
-    console.log( JSON.stringify( results ) );
+    return JSON.stringify( results );
 }
 ```
 
diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md
index bf51f6c22..8b5c0d5ac 100644
--- a/docs/developer-guide/working-with-rules.md
+++ b/docs/developer-guide/working-with-rules.md
@@ -135,6 +135,31 @@ Additionally, the `context` object has the following methods:
 
 **Note:** Earlier versions of ESLint supported additional methods on the `context` object. Those methods were removed in the new format and should not be relied upon.
 
+### context.getScope()
+
+This method returns the scope which has the following types:
+
+| AST Node Type             | Scope Type |
+|:--------------------------|:-----------|
+| `Program`                 | `global`   |
+| `FunctionDeclaration`     | `function` |
+| `FunctionExpression`      | `function` |
+| `ArrowFunctionExpression` | `function` |
+| `ClassDeclaration`        | `class`    |
+| `ClassExpression`         | `class`    |
+| `BlockStatement` ※1      | `block`    |
+| `SwitchStatement` ※1     | `switch`   |
+| `ForStatement` ※2        | `for`      |
+| `ForInStatement` ※2      | `for`      |
+| `ForOfStatement` ※2      | `for`      |
+| `WithStatement`           | `with`     |
+| `CatchClause`             | `catch`    |
+| others                    | ※3        |
+
+**※1** Only if the configured parser provided the block-scope feature. The default parser provides the block-scope feature if `parserOptions.ecmaVersion` is not less than `6`.<br>
+**※2** Only if the `for` statement defines the iteration variable as a block-scoped variable (E.g., `for (let i = 0;;) {}`).<br>
+**※3** The scope of the closest ancestor node which has own scope. If the closest ancestor node has multiple scopes then it chooses the innermost scope (E.g., the `Program` node has a `global` scope and a `module` scope if `Program#sourceType` is `"module"`. The innermost scope is the `module` scope.).
+
 ### context.report()
 
 The main method you'll use is `context.report()`, which publishes a warning or error (depending on the configuration being used). This method accepts a single argument, which is an object containing the following properties:
@@ -371,17 +396,17 @@ Once you have an instance of `SourceCode`, you can use the methods on it to work
 * `commentsExistBetween(nodeOrToken1, nodeOrToken2)` - returns `true` if comments exist between two nodes.
 
 > `skipOptions` is an object which has 3 properties; `skip`, `includeComments`, and `filter`. Default is `{skip: 0, includeComments: false, filter: null}`.
-> - `skip` is a positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
-> - `includeComments` is a boolean value, the flag to include comment tokens into the result.
-> - `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
+> * `skip` is a positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
+> * `includeComments` is a boolean value, the flag to include comment tokens into the result.
+> * `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
 >
 > `countOptions` is an object which has 3 properties; `count`, `includeComments`, and `filter`. Default is `{count: 0, includeComments: false, filter: null}`.
-> - `count` is a positive integer, the maximum number of returning tokens.
-> - `includeComments` is a boolean value, the flag to include comment tokens into the result.
-> - `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
+> * `count` is a positive integer, the maximum number of returning tokens.
+> * `includeComments` is a boolean value, the flag to include comment tokens into the result.
+> * `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
 >
 > `rangeOptions` is an object which has 1 property: `includeComments`.
-> - `includeComments` is a boolean value, the flag to include comment tokens into the result.
+> * `includeComments` is a boolean value, the flag to include comment tokens into the result.
 
 There are also some properties you can access:
 
@@ -427,7 +452,7 @@ module.exports = {
                 },
                 "additionalProperties": false
             }
-        ];
+        ]
     },
 };
 ```
diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md
index 57f92065d..c49f39dd2 100644
--- a/docs/rules/getter-return.md
+++ b/docs/rules/getter-return.md
@@ -74,7 +74,7 @@ class P{
 
 This rule has an object option:
 
-* `"allowImplicit": false` (default) disallows implicitly returning undefined with a return; statement.
+* `"allowImplicit": false` (default) disallows implicitly returning `undefined` with a `return` statement.
 
 Examples of **correct** code for the `{ "allowImplicit": true }` option:
 
diff --git a/docs/rules/id-length.md b/docs/rules/id-length.md
index a28407fec..d49435d0b 100644
--- a/docs/rules/id-length.md
+++ b/docs/rules/id-length.md
@@ -34,7 +34,7 @@ function foo(...x) { }
 var { x } = {};
 var { x: a} = {};
 var { a: [x]} = {};
-({ prop: obj.x }) = {};
+({ prop: obj.x } = {});
 ```
 
 Examples of **correct** code for this rule with the default options:
@@ -62,7 +62,7 @@ function foo(...args) { }
 var { prop } = {};
 var { prop: a } = {};
 var { prop: [x] } = {};
-({ prop: obj.longName }) = {};
+({ prop: obj.longName } = {});
 var data = { "x": 1 };  // excused because of quotes
 data["y"] = 3;  // excused because of calculated property access
 ```
@@ -72,12 +72,12 @@ This rule has a shorthand integer option for the `"min"` object property.
 Examples of **incorrect** code for this rule with a minimum of 4:
 
 ```js
-/*eslint id-length: ["error", 4]*/
+/*eslint id-length: ["error", { "min": 4 }]*/
 /*eslint-env es6*/
 
 var val = 5;
 obj.e = document.body;
-function (e) { };
+function foo (e) { };
 try {
     dangerousStuff();
 } catch (e) {
@@ -91,13 +91,13 @@ function foo(...x) { }
 var { x } = {};
 var { x: a} = {};
 var { a: [x]} = {};
-({ prop: obj.x }) = {};
+({ prop: obj.x } = {});
 ```
 
 Examples of **correct** code for this rule with a minimum of 4:
 
 ```js
-/*eslint id-length: ["error", 4]*/
+/*eslint id-length: ["error", { "min": 4 }]*/
 /*eslint-env es6*/
 
 var value = 5;
@@ -118,7 +118,7 @@ function foobar(...args) { }
 var { prop } = {};
 var { prop: a } = {};
 var { prop: [x] } = {};
-({ prop: obj.name }) = {};
+({ prop: obj.name } = {});
 var data = { "x": 1 };  // excused because of quotes
 data["y"] = 3;  // excused because of calculated property access
 ```
@@ -141,7 +141,7 @@ Examples of **incorrect** code for this rule with the `{ "min": 4 }` option:
 
 var val = 5;
 obj.e = document.body;
-function (e) { };
+function foo (e) { };
 try {
     dangerousStuff();
 } catch (e) {
@@ -155,7 +155,7 @@ function foo(...x) { }
 var { x } = {};
 var { x: a} = {};
 var { a: [x]} = {};
-({ prop: obj.x }) = {};
+({ prop: obj.x } = {});
 ```
 
 Examples of **correct** code for this rule with the `{ "min": 4 }` option:
@@ -182,7 +182,7 @@ function foobar(...args) { }
 var { prop } = {};
 var { prop: a } = {};
 var { prop: [x] } = {};
-({ prop: obj.name }) = {};
+({ prop: obj.name } = {});
 var data = { "x": 1 };  // excused because of quotes
 data["y"] = 3;  // excused because of calculated property access
 ```
@@ -234,8 +234,8 @@ Examples of **correct** code for this rule with the `{ "properties": "never" }`
 /*eslint-env es6*/
 
 var myObj = { a: 1 };
-({ a: obj.x.y.z }) = {};
-({ prop: obj.i }) = {};
+({ a: obj.x.y.z } = {});
+({ prop: obj.i } = {});
 ```
 
 ### exceptions
diff --git a/docs/rules/max-statements-per-line.md b/docs/rules/max-statements-per-line.md
index 8b9be85b4..d7f51ec53 100644
--- a/docs/rules/max-statements-per-line.md
+++ b/docs/rules/max-statements-per-line.md
@@ -3,7 +3,7 @@
 A line of code containing too many statements can be difficult to read. Code is generally read from the top down, especially when scanning, so limiting the number of statements allowed on a single line can be very beneficial for readability and maintainability.
 
 ```js
-function () { var bar; if (condition) { bar = 1; } else { bar = 2; } return true; } // too many statements
+function foo () { var bar; if (condition) { bar = 1; } else { bar = 2; } return true; } // too many statements
 ```
 
 ## Rule Details
diff --git a/docs/rules/no-mixed-spaces-and-tabs.md b/docs/rules/no-mixed-spaces-and-tabs.md
index 4f76b2617..ba34dbe49 100644
--- a/docs/rules/no-mixed-spaces-and-tabs.md
+++ b/docs/rules/no-mixed-spaces-and-tabs.md
@@ -41,7 +41,7 @@ function add(x, y) {
 
 This rule has a string option.
 
-* `"smart-tabs"` allows mixed spaces and tabs when the latter are used for alignment.
+* `"smart-tabs"` allows mixed tabs and spaces when the spaces are used for alignment.
 
 ### smart-tabs
 
diff --git a/docs/rules/no-unused-vars.md b/docs/rules/no-unused-vars.md
index d7502ed5c..996dea181 100644
--- a/docs/rules/no-unused-vars.md
+++ b/docs/rules/no-unused-vars.md
@@ -150,7 +150,7 @@ console.log(secondVar);
 
 The `args` option has three settings:
 
-* `after-used` - only the last argument must be used. This allows you, for instance, to have two named parameters to a function and as long as you use the second argument, ESLint will not warn you about the first. This is the default setting.
+* `after-used` - unused positional arguments that occur before the last used argument will not be checked, but all named arguments and all positional arguments after the last used argument will be checked.
 * `all` - all named arguments must be used.
 * `none` - do not check arguments.
 
@@ -161,9 +161,10 @@ Examples of **incorrect** code for the default `{ "args": "after-used" }` option
 ```js
 /*eslint no-unused-vars: ["error", { "args": "after-used" }]*/
 
-// 1 error
+// 2 errors, for the parameters after the last used parameter (bar)
 // "baz" is defined but never used
-(function(foo, bar, baz) {
+// "qux" is defined but never used
+(function(foo, bar, baz, qux) {
     return bar;
 })();
 ```
@@ -173,8 +174,8 @@ Examples of **correct** code for the default `{ "args": "after-used" }` option:
 ```js
 /*eslint no-unused-vars: ["error", {"args": "after-used"}]*/
 
-(function(foo, bar, baz) {
-    return baz;
+(function(foo, bar, baz, qux) {
+    return qux;
 })();
 ```
 
diff --git a/docs/rules/operator-linebreak.md b/docs/rules/operator-linebreak.md
index 3b4b2f19d..e2a69a1fd 100644
--- a/docs/rules/operator-linebreak.md
+++ b/docs/rules/operator-linebreak.md
@@ -180,8 +180,9 @@ Examples of additional **correct** code for this rule with the `{ "overrides": {
 ```js
 /*eslint operator-linebreak: ["error", "after", { "overrides": { "+=": "before" } }]*/
 
-var thing
-  += 'thing';
+var thing = 'thing';
+thing
+  += 's';
 ```
 
 Examples of additional **correct** code for this rule with the `{ "overrides": { "?": "ignore", ":": "ignore" } }` option:
diff --git a/docs/rules/valid-jsdoc.md b/docs/rules/valid-jsdoc.md
index 69375bf27..670f90fb9 100644
--- a/docs/rules/valid-jsdoc.md
+++ b/docs/rules/valid-jsdoc.md
@@ -158,7 +158,7 @@ This rule has an object option:
 * `"preferType"` enforces consistent type strings specified by an object whose properties mean instead of key use value (for example, `"object": "Object"` means instead of `object` use `Object`)
 * `"requireReturn"` requires a return tag:
     * `true` (default) **even if** the function or method does not have a `return` statement (this option value does not apply to constructors)
-    * `false` **if and only if** the function or method has a `return` statement (this option value does apply to constructors)
+    * `false` **if and only if** the function or method has a `return` statement or returns a value e.g. `async` function (this option value does apply to constructors)
 * `"requireReturnType": false` allows missing type in return tags
 * `"matchDescription"` specifies (as a string) a regular expression to match the description in each JSDoc comment (for example, `".+"` requires a description; this option does not apply to descriptions in parameter or return tags)
 * `"requireParamDescription": false` allows missing description in parameter tags
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 22dcd497f..4b98eb075 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -13,7 +13,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
 
 ## Installation and Usage
 
-Prerequisites: [Node.js](https://nodejs.org/en/) (>=4.x), npm version 2+.
+Prerequisites: [Node.js](https://nodejs.org/en/) (>=6.14), npm version 3+.
 
 There are two ways to install ESLint: globally and locally.
 
diff --git a/docs/user-guide/integrations.md b/docs/user-guide/integrations.md
index 1179fa960..159066348 100644
--- a/docs/user-guide/integrations.md
+++ b/docs/user-guide/integrations.md
@@ -5,7 +5,9 @@
 * Sublime Text 3:
     * [SublimeLinter-eslint](https://github.com/roadhump/SublimeLinter-eslint)
     * [Build Next](https://github.com/albertosantini/sublimetext-buildnext)
-* [Vim](https://github.com/vim-syntastic/syntastic/tree/master/syntax_checkers/javascript)
+* Vim:
+    * [ALE](https://github.com/w0rp/ale)
+    * [Syntastic](https://github.com/vim-syntastic/syntastic/tree/master/syntax_checkers/javascript)
 * Emacs: [Flycheck](http://www.flycheck.org/) supports ESLint with the [javascript-eslint](http://www.flycheck.org/en/latest/languages.html#javascript) checker.
 * Eclipse Orion: ESLint is the [default linter](https://dev.eclipse.org/mhonarc/lists/orion-dev/msg02718.html)
 * Eclipse IDE with [Tern ESLint linter](https://github.com/angelozerr/tern.java/wiki/Tern-Linter-ESLint)
diff --git a/docs/user-guide/migrating-to-5.0.0.md b/docs/user-guide/migrating-to-5.0.0.md
index 95123b57c..2fb584aa9 100644
--- a/docs/user-guide/migrating-to-5.0.0.md
+++ b/docs/user-guide/migrating-to-5.0.0.md
@@ -7,8 +7,10 @@ The lists below are ordered roughly by the number of users each change is expect
 ### Breaking changes for users
 
 1. [Node.js 4 is no longer supported](#drop-node-4)
+1. [New rules have been added to `eslint:recommended`](#eslint-recommended-changes)
 1. [The `experimentalObjectRestSpread` option has been deprecated](#experimental-object-rest-spread)
 1. [Linting nonexistent files from the command line is now a fatal error](#nonexistent-files)
+1. [Deprecated globals have been removed from the `node`, `browser`, and `jest` environments](#deprecated-globals)
 1. [Empty files are now linted](#empty-files)
 1. [Plugins in scoped packages are now resolvable in configs](#scoped-plugins)
 
@@ -16,6 +18,8 @@ The lists below are ordered roughly by the number of users each change is expect
 
 1. [The `parent` property of AST nodes is now set before rules start running](#parent-before-rules)
 1. [When using the default parser, text nodes in JSX elements now have type `JSXText`](#jsx-text-nodes)
+1. [The `context.getScope()` method now returns more proper scopes](#context-get-scope)
+1. [The `_linter` property on rule context objects has been removed](#no-context-linter)
 1. [`RuleTester` now uses strict equality checks in its assertions](#rule-tester-equality)
 1. [Rules are now required to provide messages along with reports](#required-report-messages)
 
@@ -32,12 +36,30 @@ The lists below are ordered roughly by the number of users each change is expect
 As of April 30th, 2018, Node.js 4 will be at EOL and will no longer be receiving security updates. As a result, we have decided to drop support for it in ESLint v5. We now support the following versions of Node.js:
 
 * Node.js 6 (6.14.0 and above)
-* Node.js 8 (8.11.0 and above)
+* Node.js 8 (8.10.0 and above)
 * Anything above Node.js 9.10.0
 
 **To address:** Make sure you upgrade to at least Node.js 6 when using ESLint v5. If you are unable to upgrade, we recommend continuing to use ESLint v4.x until you are able to upgrade Node.js.
 
-*Note: The latest alpha release of ESLint v5 may still function on Node.js 4, but we plan to officially drop support for it before the first stable release.*
+## <a name="eslint-recommended-changes"/> `eslint:recommended` changes
+
+Two new rules have been added to the [`eslint:recommended`](https://eslint.org/docs/user-guide/configuring#using-eslintrecommended) config:
+
+* [`for-direction`](/docs/rules/for-direction) enforces that a `for` loop update clause moves the counter in the right direction.
+* [`getter-return`](/docs/rules/getter-return) enforces that a `return` statement is present in property getters.
+
+**To address:** To mimic the `eslint:recommended` behavior from 4.x, you can disable these rules in a config file:
+
+```json
+{
+  "extends": "eslint:recommended",
+
+  "rules": {
+    "for-direction": "off",
+    "getter-return": "off"
+  }
+}
+```
 
 ## <a name="experimental-object-rest-spread"></a> The `experimentalObjectRestSpread` option has been deprecated
 
@@ -69,8 +91,6 @@ For compatibility, ESLint v5 will treat `ecmaFeatures: { experimentalObjectRestS
 
 **To address:** If you use the `experimentalObjectRestSpread` option, you should be able to upgrade to ESLint v5 without any changes, but you will encounter a deprecation warning. To avoid the warning, use `ecmaVersion: 2018` in your config file rather than `ecmaFeatures: { experimentalObjectRestSpread: true }`. If you would like to disallow the use of other ES2018 features, consider using rules such as [`no-restricted-syntax`](/docs/rules/no-restricted-syntax).
 
-*Note: In the latest alpha release of ESLint v5, `experimentalObjectRestSpread` is not yet implemented as an alias for `ecmaVersion: 2018`, so configs that use `experimentalObjectRestSpread` may temporarily cause parsing errors. We plan to add this alias in a future prerelease.*
-
 ## <a name="nonexistent-files"></a> Linting nonexistent files from the command line is now a fatal error
 
 Previous versions of ESLint silently ignored any nonexistent files and globs provided on the command line:
@@ -92,7 +112,22 @@ Note that this also affects the [`CLIEngine.executeOnFiles()`](https://eslint.or
 
 If you use a boilerplate generator that relies on this behavior (e.g. to generate a script that runs `eslint tests/` in a new project before any test files are actually present), you can work around this issue by adding a dummy file that matches the given pattern (e.g. an empty `tests/index.js` file).
 
-*Note: This change has not yet appeared in the latest alpha release. We plan to add it in a future prerelease.*
+## <a name="deprecated-globals"></a> Deprecated globals have been removed from the `node`, `browser`, and `jest` environments
+
+Some global variables have been deprecated or removed for code running in Node.js, browsers, and Jest. (For example, browsers used to expose an `SVGAltGlyphElement` global variable to JavaScript code, but this global has been removed from web standards and is no longer present in browsers.) As a result, we have removed these globals from the corresponding `eslint` environments, so use of these globals will trigger an error when using rules such as [`no-undef`](/docs/rules/no-undef).
+
+**To address:** If you use deprecated globals in the `node`, `browser`, or `jest` environments, you can add a `globals` section to your configuration to re-enable any globals you need. For example:
+
+```json
+{
+  "env": {
+    "browser": true
+  },
+  "globals": {
+    "SVGAltGlyphElement": false
+  }
+}
+```
 
 ## <a name="empty-files"></a> Empty files are now linted
 
@@ -116,7 +151,7 @@ When it encounters a plugin name in a config starting with `@`, ESLint v5 will r
 
 Previously, ESLint would set the `parent` property on each AST node immediately before running rule listeners for that node. This caused some confusion for rule authors, because the `parent` property would not initially be present on any nodes, and it was sometimes necessary to complicate the structure of a rule to ensure that the `parent` property of a given node would be available when needed.
 
-In ESLint v5, the `parent` property is set on all AST nodes before any rules have access to the AST. This makes it easier to write some rules, because the `parent` property is always available rather than being mutated behind the scenes. However, as a side-effect of having `parent` properties, the AST object has a circular structure the first time a rule sees it (previously, it only had a circular structure after the first rule listeners were called). As a result, a custom rule that enumerates all properties of an node in order to traverse the AST might now loop forever or run out of memory if it does not check for cycles properly.
+In ESLint v5, the `parent` property is set on all AST nodes before any rules have access to the AST. This makes it easier to write some rules, because the `parent` property is always available rather than being mutated behind the scenes. However, as a side-effect of having `parent` properties, the AST object has a circular structure the first time a rule sees it (previously, it only had a circular structure after the first rule listeners were called). As a result, a custom rule that enumerates all properties of a node in order to traverse the AST might now loop forever or run out of memory if it does not check for cycles properly.
 
 **To address:** If you have written a custom rule that enumerates all properties of an AST node, consider excluding the `parent` property or implementing cycle detection to ensure that you obtain the correct result.
 
@@ -126,6 +161,22 @@ When parsing JSX code like `<a>foo</a>`, the default parser will now give the `f
 
 **To address:** If you have written a custom rule that relies on text nodes in JSX elements having the `Literal` type, you should update it to also work with nodes that have the `JSXText` type.
 
+## <a name="context-get-scope"></a> The `context.getScope()` method now returns more proper scopes
+
+Previously, the `context.getScope()` method changed its behavior based on the `parserOptions.ecmaVersion` property. However, this could cause confusing behavior when using a parser that doesn't respond to the `ecmaVersion` option, such as `babel-eslint`.
+
+Additionally, `context.getScope()` incorrectly returned the parent scope of the proper scope on `CatchClause` (in ES5), `ForStatement` (in ≧ES2015), `ForInStatement` (in ≧ES2015), `ForOfStatement`, and `WithStatement` nodes.
+
+In ESLint v5, the `context.getScope()` method has the same behavior regardless of `parserOptions.ecmaVersion` and returns the proper scope. See [the documentation](../developer-guide/working-with-rules#contextgetscope) for more details on which scopes are returned.
+
+**To address:** If you have written a custom rule that uses the `context.getScope()` method in node handlers, you may need to update it to account for the modified scope information.
+
+## <a name="no-context-linter"></a> The `_linter` property on rule context objects has been removed
+
+Previously, rule context objects had an undocumented `_linter` property, which was used internally within ESLint to process reports from rules. Some rules used this property to achieve functionality that was not intended to be possible for rules. For example, several plugins used the `_linter` property in a rule to monitor reports from other rules, for the purpose of checking for unused `/* eslint-disable */` directive comments. Although this functionality was useful for users, it could also cause stability problems for projects using ESLint. For example, an upgrade to a rule in one plugin could unexpectedly cause a rule in another plugin to start reporting errors.
+
+The `_linter` property has been removed in ESLint v5.0, so it is no longer possible to implement rules with this functionality. However, the [`--report-unused-disable-directives`](/docs/user-guide/command-line-interface#--report-unused-disable-directives) CLI flag can be used to flag unused directive comments.
+
 ## <a name="rule-tester-equality"></a> `RuleTester` now uses strict equality checks in its assertions
 
 Previously, `RuleTester` used loose equality when making some of its assertions. For example, if a rule produced the string `"7"` as a result of autofixing, `RuleTester` would allow the number `7` in an `output` assertion, rather than the string `"7"`. In ESLint v5, comparisons from `RuleTester` use strict equality, so an assertion like this will no longer pass.
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 8531d1c1d..9cab3b47b 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -381,6 +381,21 @@ class CLIEngine {
             providedOptions
         );
 
+        /*
+         * if an --ignore-path option is provided, ensure that the ignore
+         * file exists and is not a directory
+         */
+        if (options.ignore && options.ignorePath) {
+            try {
+                if (!fs.statSync(options.ignorePath).isFile()) {
+                    throw new Error(`${options.ignorePath} is not a file`);
+                }
+            } catch (e) {
+                e.message = `Error: Could not load file ${options.ignorePath}\nError: ${e.message}`;
+                throw e;
+            }
+        }
+
         /**
          * Stored options for this instance
          * @type {Object}
@@ -481,7 +496,7 @@ class CLIEngine {
      * @returns {string[]} The equivalent glob patterns.
      */
     resolveFileGlobPatterns(patterns) {
-        return globUtil.resolveFileGlobPatterns(patterns, this.options);
+        return globUtil.resolveFileGlobPatterns(patterns.filter(Boolean), this.options);
     }
 
     /**
@@ -515,7 +530,7 @@ class CLIEngine {
         }
 
         const startTime = Date.now();
-        const fileList = globUtil.listFilesToProcess(this.resolveFileGlobPatterns(patterns), options);
+        const fileList = globUtil.listFilesToProcess(patterns, options);
         const results = fileList.map(fileInfo => {
             if (fileInfo.ignored) {
                 return createIgnoreResult(fileInfo.filename, options.cwd);
diff --git a/lib/config/config-file.js b/lib/config/config-file.js
index 37ac84831..46d561516 100644
--- a/lib/config/config-file.js
+++ b/lib/config/config-file.js
@@ -467,7 +467,7 @@ function resolve(filePath, relativeTo) {
         debug(`Attempting to resolve ${normalizedPackageName}`);
 
         return {
-            filePath: resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)),
+            filePath: require.resolve(normalizedPackageName),
             configName,
             configFullName
         };
diff --git a/lib/config/config-initializer.js b/lib/config/config-initializer.js
index 3e99be9ec..bbeb405d0 100644
--- a/lib/config/config-initializer.js
+++ b/lib/config/config-initializer.js
@@ -394,8 +394,8 @@ function promptUser() {
             message: "How would you like to configure ESLint?",
             default: "prompt",
             choices: [
-                { name: "Answer questions about your style", value: "prompt" },
                 { name: "Use a popular style guide", value: "guide" },
+                { name: "Answer questions about your style", value: "prompt" },
                 { name: "Inspect your JavaScript file(s)", value: "auto" }
             ]
         },
@@ -403,7 +403,11 @@ function promptUser() {
             type: "list",
             name: "styleguide",
             message: "Which style guide do you want to follow?",
-            choices: [{ name: "Google", value: "google" }, { name: "Airbnb", value: "airbnb" }, { name: "Standard", value: "standard" }],
+            choices: [
+                { name: "Airbnb (https://github.com/airbnb/javascript)", value: "airbnb" },
+                { name: "Standard (https://github.com/standard/standard)", value: "standard" },
+                { name: "Google (https://github.com/google/eslint-config-google)", value: "google" }
+            ],
             when(answers) {
                 answers.packageJsonExists = npmUtil.checkPackageJson();
                 return answers.source === "guide" && answers.packageJsonExists;
diff --git a/lib/config/config-validator.js b/lib/config/config-validator.js
index 1a5b3ef13..ed9a34cb0 100644
--- a/lib/config/config-validator.js
+++ b/lib/config/config-validator.js
@@ -9,7 +9,8 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const ajv = require("../util/ajv"),
+const path = require("path"),
+    ajv = require("../util/ajv"),
     lodash = require("lodash"),
     configSchema = require("../../conf/config-schema.js"),
     util = require("util");
@@ -21,6 +22,12 @@ const ruleValidators = new WeakMap();
 //------------------------------------------------------------------------------
 let validateSchema;
 
+// Defitions for deprecation warnings.
+const deprecationWarningMessages = Object.freeze({
+    ESLINT_LEGACY_ECMAFEATURES: "The 'ecmaFeatures' config file property is deprecated, and has no effect.",
+    ESLINT_LEGACY_OBJECT_REST_SPREAD: "The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead."
+});
+
 /**
  * Gets a complete options schema for a rule.
  * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
@@ -194,18 +201,18 @@ function formatErrors(errors) {
  * for each unique file path, but repeated invocations with the same file path have no effect.
  * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
  * @param {string} source The name of the configuration source to report the warning for.
+ * @param {string} errorCode The warning message to show.
  * @returns {void}
  */
-const emitEcmaFeaturesWarning = lodash.memoize(source => {
-
-    /*
-     * util.deprecate seems to be the only way to emit a warning in Node 4.x while respecting the --no-warnings flag.
-     * (In Node 6+, process.emitWarning could be used instead.)
-     */
-    util.deprecate(
-        () => {},
-        `[eslint] The 'ecmaFeatures' config file property is deprecated, and has no effect. (found in ${source})`
-    )();
+const emitDeprecationWarning = lodash.memoize((source, errorCode) => {
+    const rel = path.relative(process.cwd(), source);
+    const message = deprecationWarningMessages[errorCode];
+
+    process.emitWarning(
+        `${message} (found in "${rel}")`,
+        "DeprecationWarning",
+        errorCode
+    );
 });
 
 /**
@@ -221,8 +228,17 @@ function validateConfigSchema(config, source) {
         throw new Error(`ESLint configuration in ${source} is invalid:\n${formatErrors(validateSchema.errors)}`);
     }
 
-    if (Object.prototype.hasOwnProperty.call(config, "ecmaFeatures")) {
-        emitEcmaFeaturesWarning(source);
+    if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
+        emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
+    }
+
+    if (
+        (config.parser || "espree") === "espree" &&
+        config.parserOptions &&
+        config.parserOptions.ecmaFeatures &&
+        config.parserOptions.ecmaFeatures.experimentalObjectRestSpread
+    ) {
+        emitDeprecationWarning(source, "ESLINT_LEGACY_OBJECT_REST_SPREAD");
     }
 }
 
diff --git a/lib/config/plugins.js b/lib/config/plugins.js
index a47322705..37c3be497 100644
--- a/lib/config/plugins.js
+++ b/lib/config/plugins.js
@@ -10,6 +10,7 @@
 
 const debug = require("debug")("eslint:plugins");
 const naming = require("../util/naming");
+const path = require("path");
 
 //------------------------------------------------------------------------------
 // Public Interface
@@ -100,7 +101,8 @@ class Plugins {
                     missingPluginErr.message = `Failed to load plugin ${pluginName}: ${missingPluginErr.message}`;
                     missingPluginErr.messageTemplate = "plugin-missing";
                     missingPluginErr.messageData = {
-                        pluginName: longName
+                        pluginName: longName,
+                        eslintPath: path.resolve(__dirname, "../..")
                     };
                     throw missingPluginErr;
                 }
diff --git a/lib/file-finder.js b/lib/file-finder.js
index 11091a99d..5d4b48a62 100644
--- a/lib/file-finder.js
+++ b/lib/file-finder.js
@@ -134,7 +134,7 @@ class FileFinder {
 
         // Add what has been cached previously to the cache of each directory searched.
         for (let i = 0; i < searched; i++) {
-            [].push.apply(cache[dirs[i]], cache[directory]);
+            cache[dirs[i]].push(...cache[directory]);
         }
 
         yield* cache[dirs[0]];
diff --git a/lib/linter.js b/lib/linter.js
index 2d46b4bd8..9b707aa22 100644
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -284,7 +284,7 @@ function getDirectiveComments(filename, ast, ruleMapper) {
         if (/^eslint-disable-(next-)?line$/.test(match[1]) && comment.loc.start.line === comment.loc.end.line) {
             const directiveType = match[1].slice("eslint-".length);
 
-            [].push.apply(disableDirectives, createDisableDirectives(directiveType, comment.loc.start, directiveValue));
+            disableDirectives.push(...createDisableDirectives(directiveType, comment.loc.start, directiveValue));
         } else if (comment.type === "Block") {
             switch (match[1]) {
                 case "exported":
@@ -297,11 +297,11 @@ function getDirectiveComments(filename, ast, ruleMapper) {
                     break;
 
                 case "eslint-disable":
-                    [].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, directiveValue));
+                    disableDirectives.push(...createDisableDirectives("disable", comment.loc.start, directiveValue));
                     break;
 
                 case "eslint-enable":
-                    [].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, directiveValue));
+                    disableDirectives.push(...createDisableDirectives("enable", comment.loc.start, directiveValue));
                     break;
 
                 case "eslint": {
@@ -410,11 +410,12 @@ function normalizeVerifyOptions(providedOptions) {
 
 /**
  * Combines the provided parserOptions with the options from environments
+ * @param {string} parserName The parser name which uses this options.
  * @param {Object} providedOptions The provided 'parserOptions' key in a config
  * @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments
  * @returns {Object} Resulting parser options after merge
  */
-function resolveParserOptions(providedOptions, enabledEnvironments) {
+function resolveParserOptions(parserName, providedOptions, enabledEnvironments) {
     const parserOptionsFromEnv = enabledEnvironments
         .filter(env => env.parserOptions)
         .reduce((parserOptions, env) => ConfigOps.merge(parserOptions, env.parserOptions), {});
@@ -431,6 +432,16 @@ function resolveParserOptions(providedOptions, enabledEnvironments) {
 
     mergedParserOptions.ecmaVersion = normalizeEcmaVersion(mergedParserOptions.ecmaVersion, isModule);
 
+    // TODO: For backward compatibility. Will remove on v6.0.0.
+    if (
+        parserName === DEFAULT_PARSER_NAME &&
+        mergedParserOptions.ecmaFeatures &&
+        mergedParserOptions.ecmaFeatures.experimentalObjectRestSpread &&
+        (!mergedParserOptions.ecmaVersion || mergedParserOptions.ecmaVersion < 9)
+    ) {
+        mergedParserOptions.ecmaVersion = 9;
+    }
+
     return mergedParserOptions;
 }
 
@@ -604,27 +615,15 @@ function parse(text, providedParserOptions, parserName, parserMap, filePath) {
  * Gets the scope for the current node
  * @param {ScopeManager} scopeManager The scope manager for this AST
  * @param {ASTNode} currentNode The node to get the scope of
- * @param {number} ecmaVersion The `ecmaVersion` setting that this code was parsed with
  * @returns {eslint-scope.Scope} The scope information for this node
  */
-function getScope(scopeManager, currentNode, ecmaVersion) {
-    let initialNode;
+function getScope(scopeManager, currentNode) {
 
-    // if current node introduces a scope, add it to the list
-    if (
-        ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(currentNode.type) >= 0 ||
-        ecmaVersion >= 6 && ["BlockStatement", "SwitchStatement", "CatchClause"].indexOf(currentNode.type) >= 0
-    ) {
-        initialNode = currentNode;
-    } else {
-        initialNode = currentNode.parent;
-    }
+    // On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
+    const inner = currentNode.type !== "Program";
 
-    // Ascend the current node's parents
-    for (let node = initialNode; node; node = node.parent) {
-
-        // Get the innermost scope
-        const scope = scopeManager.acquire(node, true);
+    for (let node = currentNode; node; node = node.parent) {
+        const scope = scopeManager.acquire(node, inner);
 
         if (scope) {
             if (scope.type === "function-expression-name") {
@@ -648,7 +647,7 @@ function getScope(scopeManager, currentNode, ecmaVersion) {
 function markVariableAsUsed(scopeManager, currentNode, parserOptions, name) {
     const hasGlobalReturn = parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn;
     const specialScope = hasGlobalReturn || parserOptions.sourceType === "module";
-    const currentScope = getScope(scopeManager, currentNode, parserOptions.ecmaVersion);
+    const currentScope = getScope(scopeManager, currentNode);
 
     // Special Node.js scope means we need to start one level deeper
     const initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope;
@@ -724,10 +723,8 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
     Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).reduce(
         (contextInfo, methodName) =>
             Object.assign(contextInfo, {
-                [methodName]() {
-                    const sourceCode = this.getSourceCode();
-
-                    return sourceCode[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]].apply(sourceCode, arguments);
+                [methodName](...args) {
+                    return this.getSourceCode()[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]](...args);
                 }
             }),
         {}
@@ -773,26 +770,13 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
                 getAncestors: () => getAncestors(currentNode),
                 getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
                 getFilename: () => filename,
-                getScope: () => getScope(sourceCode.scopeManager, currentNode, parserOptions.ecmaVersion),
+                getScope: () => getScope(sourceCode.scopeManager, currentNode),
                 getSourceCode: () => sourceCode,
                 markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, parserOptions, name),
                 parserOptions,
                 parserPath: parserName,
                 parserServices: sourceCode.parserServices,
-                settings,
-
-                /**
-                 * This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method
-                 * by using the `_linter` property on rule contexts.
-                 *
-                 * This should be removed in a major release after we create a better way to
-                 * lint for unused disable comments.
-                 * https://github.com/eslint/eslint/issues/9193
-                 */
-                _linter: {
-                    report() {},
-                    on: emitter.on
-                }
+                settings
             }
         )
     );
@@ -816,7 +800,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
                 {
                     id: ruleId,
                     options: getRuleOptions(configuredRules[ruleId]),
-                    report() {
+                    report(...args) {
 
                         /*
                          * Create a report translator lazily.
@@ -831,30 +815,12 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
                         if (reportTranslator === null) {
                             reportTranslator = createReportTranslator({ ruleId, severity, sourceCode, messageIds });
                         }
-                        const problem = reportTranslator.apply(null, arguments);
+                        const problem = reportTranslator(...args);
 
                         if (problem.fix && rule.meta && !rule.meta.fixable) {
                             throw new Error("Fixable rules should export a `meta.fixable` property.");
                         }
                         lintingProblems.push(problem);
-
-                        /*
-                         * This is used to avoid breaking rules that used monkeypatch Linter, and relied on
-                         * `linter.report` getting called with report info every time a rule reports a problem.
-                         * To continue to support this, make sure that `context._linter.report` is called every
-                         * time a problem is reported by a rule, even though `context._linter` is no longer a
-                         * `Linter` instance.
-                         *
-                         * This should be removed in a major release after we create a better way to
-                         * lint for unused disable comments.
-                         * https://github.com/eslint/eslint/issues/9193
-                         */
-                        sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle
-                            problem.ruleId,
-                            problem.severity,
-                            { loc: { start: { line: problem.line, column: problem.column - 1 } } },
-                            problem.message
-                        );
                     }
                 }
             )
@@ -956,9 +922,9 @@ module.exports = class Linter {
             .map(envName => this.environments.get(envName))
             .filter(env => env);
 
-        const parserOptions = resolveParserOptions(config.parserOptions || {}, enabledEnvs);
-        const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
         const parserName = config.parser || DEFAULT_PARSER_NAME;
+        const parserOptions = resolveParserOptions(parserName, config.parserOptions || {}, enabledEnvs);
+        const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
         const settings = config.settings || {};
 
         if (!lastSourceCodes.get(this)) {
diff --git a/lib/logging.js b/lib/logging.js
index 22451e535..3eb898c34 100644
--- a/lib/logging.js
+++ b/lib/logging.js
@@ -14,15 +14,15 @@ module.exports = {
      * Cover for console.log
      * @returns {void}
      */
-    info() {
-        console.log.apply(console, arguments);
+    info(...args) {
+        console.log(...args);
     },
 
     /**
      * Cover for console.error
      * @returns {void}
      */
-    error() {
-        console.error.apply(console, arguments);
+    error(...args) {
+        console.error(...args);
     }
 };
diff --git a/lib/report-translator.js b/lib/report-translator.js
index 17d410d2a..f82830586 100644
--- a/lib/report-translator.js
+++ b/lib/report-translator.js
@@ -51,35 +51,35 @@ const interpolate = require("./util/interpolate");
 
 /**
  * Translates a multi-argument context.report() call into a single object argument call
- * @param {...*} arguments A list of arguments passed to `context.report`
+ * @param {...*} args A list of arguments passed to `context.report`
  * @returns {MessageDescriptor} A normalized object containing report information
  */
-function normalizeMultiArgReportCall() {
+function normalizeMultiArgReportCall(...args) {
 
     // If there is one argument, it is considered to be a new-style call already.
-    if (arguments.length === 1) {
+    if (args.length === 1) {
 
         // Shallow clone the object to avoid surprises if reusing the descriptor
-        return Object.assign({}, arguments[0]);
+        return Object.assign({}, args[0]);
     }
 
     // If the second argument is a string, the arguments are interpreted as [node, message, data, fix].
-    if (typeof arguments[1] === "string") {
+    if (typeof args[1] === "string") {
         return {
-            node: arguments[0],
-            message: arguments[1],
-            data: arguments[2],
-            fix: arguments[3]
+            node: args[0],
+            message: args[1],
+            data: args[2],
+            fix: args[3]
         };
     }
 
     // Otherwise, the arguments are interpreted as [node, loc, message, data, fix].
     return {
-        node: arguments[0],
-        loc: arguments[1],
-        message: arguments[2],
-        data: arguments[3],
-        fix: arguments[4]
+        node: args[0],
+        loc: args[1],
+        message: args[2],
+        data: args[3],
+        fix: args[4]
     };
 }
 
@@ -240,8 +240,8 @@ module.exports = function createReportTranslator(metadata) {
      * called every time a rule reports a problem, which happens much less frequently (usually, the vast
      * majority of rules don't report any problems for a given file).
      */
-    return function() {
-        const descriptor = normalizeMultiArgReportCall.apply(null, arguments);
+    return (...args) => {
+        const descriptor = normalizeMultiArgReportCall(...args);
 
         assertValidNodeInfo(descriptor);
 
diff --git a/lib/rules/for-direction.js b/lib/rules/for-direction.js
index c91888da2..817e2c111 100644
--- a/lib/rules/for-direction.js
+++ b/lib/rules/for-direction.js
@@ -14,7 +14,7 @@ module.exports = {
         docs: {
             description: "enforce \"for\" loop update clause moving the counter in the right direction.",
             category: "Possible Errors",
-            recommended: false,
+            recommended: true,
             url: "https://eslint.org/docs/rules/for-direction"
         },
         fixable: null,
diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js
index 58f2a3978..fe40e5f09 100644
--- a/lib/rules/getter-return.js
+++ b/lib/rules/getter-return.js
@@ -47,7 +47,7 @@ module.exports = {
         docs: {
             description: "enforce `return` statements in getters",
             category: "Possible Errors",
-            recommended: false,
+            recommended: true,
             url: "https://eslint.org/docs/rules/getter-return"
         },
         fixable: null,
diff --git a/lib/rules/no-case-declarations.js b/lib/rules/no-case-declarations.js
index 862be4c57..c05795200 100644
--- a/lib/rules/no-case-declarations.js
+++ b/lib/rules/no-case-declarations.js
@@ -50,7 +50,7 @@ module.exports = {
 
                     if (isLexicalDeclaration(statement)) {
                         context.report({
-                            node,
+                            node: statement,
                             messageId: "unexpected"
                         });
                     }
diff --git a/lib/rules/no-irregular-whitespace.js b/lib/rules/no-irregular-whitespace.js
index f1840aaf2..7f9adc10a 100644
--- a/lib/rules/no-irregular-whitespace.js
+++ b/lib/rules/no-irregular-whitespace.js
@@ -225,7 +225,7 @@ module.exports = {
 
                 // If we have any errors remaining report on them
                 errors.forEach(error => {
-                    context.report.apply(context, error);
+                    context.report(...error);
                 });
             };
         } else {
diff --git a/lib/rules/no-return-await.js b/lib/rules/no-return-await.js
index 490ccaeb3..fc3373d3c 100644
--- a/lib/rules/no-return-await.js
+++ b/lib/rules/no-return-await.js
@@ -18,7 +18,6 @@ module.exports = {
             description: "disallow unnecessary `return await`",
             category: "Best Practices",
 
-            // TODO: set to true
             recommended: false,
 
             url: "https://eslint.org/docs/rules/no-return-await"
diff --git a/lib/rules/no-shadow.js b/lib/rules/no-shadow.js
index d01231ff9..17ca1291d 100644
--- a/lib/rules/no-shadow.js
+++ b/lib/rules/no-shadow.js
@@ -179,7 +179,7 @@ module.exports = {
                 while (stack.length) {
                     const scope = stack.pop();
 
-                    stack.push.apply(stack, scope.childScopes);
+                    stack.push(...scope.childScopes);
                     checkForShadows(scope);
                 }
             }
diff --git a/lib/rules/no-undefined.js b/lib/rules/no-undefined.js
index 94b514e91..8491ab5d5 100644
--- a/lib/rules/no-undefined.js
+++ b/lib/rules/no-undefined.js
@@ -68,7 +68,7 @@ module.exports = {
                 while (stack.length) {
                     const scope = stack.pop();
 
-                    stack.push.apply(stack, scope.childScopes);
+                    stack.push(...scope.childScopes);
                     checkScope(scope);
                 }
             }
diff --git a/lib/rules/no-unused-vars.js b/lib/rules/no-unused-vars.js
index 6ba573498..0d5194bc8 100644
--- a/lib/rules/no-unused-vars.js
+++ b/lib/rules/no-unused-vars.js
@@ -457,30 +457,19 @@ module.exports = {
         }
 
         /**
-         * Checks whether the given variable is the last parameter in the non-ignored parameters.
+         * Checks whether the given variable is after the last used parameter.
          *
          * @param {eslint-scope.Variable} variable - The variable to check.
-         * @returns {boolean} `true` if the variable is the last.
+         * @returns {boolean} `true` if the variable is defined after the last
+         * used parameter.
          */
-        function isLastInNonIgnoredParameters(variable) {
+        function isAfterLastUsedArg(variable) {
             const def = variable.defs[0];
+            const params = context.getDeclaredVariables(def.node);
+            const posteriorParams = params.slice(params.indexOf(variable) + 1);
 
-            // This is the last.
-            if (def.index === def.node.params.length - 1) {
-                return true;
-            }
-
-            // if all parameters preceded by this variable are ignored and unused, this is the last.
-            if (config.argsIgnorePattern) {
-                const params = context.getDeclaredVariables(def.node);
-                const posteriorParams = params.slice(params.indexOf(variable) + 1);
-
-                if (posteriorParams.every(v => v.references.length === 0 && config.argsIgnorePattern.test(v.name))) {
-                    return true;
-                }
-            }
-
-            return false;
+            // If any used parameters occur after this parameter, do not report.
+            return !posteriorParams.some(v => v.references.length > 0);
         }
 
         /**
@@ -549,8 +538,8 @@ module.exports = {
                                 continue;
                             }
 
-                            // if "args" option is "after-used", skip all but the last parameter
-                            if (config.args === "after-used" && astUtils.isFunction(def.name.parent) && !isLastInNonIgnoredParameters(variable)) {
+                            // if "args" option is "after-used", skip used variables
+                            if (config.args === "after-used" && astUtils.isFunction(def.name.parent) && !isAfterLastUsedArg(variable)) {
                                 continue;
                             }
                         } else {
diff --git a/lib/rules/object-shorthand.js b/lib/rules/object-shorthand.js
index c5239a71d..71a320a0e 100644
--- a/lib/rules/object-shorthand.js
+++ b/lib/rules/object-shorthand.js
@@ -233,6 +233,10 @@ module.exports = {
             const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
             let keyPrefix = "";
 
+            if (sourceCode.commentsExistBetween(lastKeyToken, node.value)) {
+                return null;
+            }
+
             if (node.value.async) {
                 keyPrefix += "async ";
             }
diff --git a/lib/rules/one-var.js b/lib/rules/one-var.js
index 40b5f0f0a..70223dd2c 100644
--- a/lib/rules/one-var.js
+++ b/lib/rules/one-var.js
@@ -18,6 +18,8 @@ module.exports = {
             url: "https://eslint.org/docs/rules/one-var"
         },
 
+        fixable: "code",
+
         schema: [
             {
                 oneOf: [
@@ -114,6 +116,8 @@ module.exports = {
             }
         }
 
+        const sourceCode = context.getSourceCode();
+
         //--------------------------------------------------------------------------
         // Helpers
         //--------------------------------------------------------------------------
@@ -272,6 +276,77 @@ module.exports = {
             return true;
         }
 
+        /**
+         * Fixer to join VariableDeclaration's into a single declaration
+         * @param   {VariableDeclarator[]} declarations The `VariableDeclaration` to join
+         * @returns {Function}                         The fixer function
+         */
+        function joinDeclarations(declarations) {
+            const declaration = declarations[0];
+            const body = Array.isArray(declaration.parent.parent.body) ? declaration.parent.parent.body : [];
+            const currentIndex = body.findIndex(node => node.range[0] === declaration.parent.range[0]);
+            const previousNode = body[currentIndex - 1];
+
+            return fixer => {
+                const type = sourceCode.getTokenBefore(declaration);
+                const prevSemi = sourceCode.getTokenBefore(type);
+                const res = [];
+
+                if (previousNode && previousNode.kind === sourceCode.getText(type)) {
+                    res.push(fixer.replaceText(prevSemi, ","));
+                    res.push(fixer.replaceText(type, ""));
+                }
+
+                return res;
+            };
+        }
+
+        /**
+         * Fixer to split a VariableDeclaration into individual declarations
+         * @param   {VariableDeclaration}   declaration The `VariableDeclaration` to split
+         * @param   {?Function}             filter      Function to filter the declarations
+         * @returns {Function}                          The fixer function
+         */
+        function splitDeclarations(declaration) {
+            return fixer => declaration.declarations.map(declarator => {
+                const tokenAfterDeclarator = sourceCode.getTokenAfter(declarator);
+                const afterComma = sourceCode.getTokenAfter(tokenAfterDeclarator, { includeComments: true });
+
+                if (tokenAfterDeclarator.value !== ",") {
+                    return null;
+                }
+
+                /*
+                 * `var x,y`
+                 * tokenAfterDeclarator ^^ afterComma
+                 */
+                if (afterComma.range[0] === tokenAfterDeclarator.range[1]) {
+                    return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind} `);
+                }
+
+                /*
+                 * `var x,
+                 * tokenAfterDeclarator ^
+                 *      y`
+                 *      ^ afterComma
+                 */
+                if (afterComma.loc.start.line > tokenAfterDeclarator.loc.end.line || afterComma.type === "Line" || afterComma.type === "Block") {
+                    let lastComment = afterComma;
+
+                    while (lastComment.type === "Line" || lastComment.type === "Block") {
+                        lastComment = sourceCode.getTokenAfter(lastComment, { includeComments: true });
+                    }
+
+                    return fixer.replaceTextRange(
+                        [tokenAfterDeclarator.range[0], lastComment.range[0]],
+                        `;\n${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}\n${declaration.kind} `
+                    );
+                }
+
+                return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind}`);
+            }).filter(x => x);
+        }
+
         /**
          * Checks a given VariableDeclaration node for errors.
          * @param {ASTNode} node The VariableDeclaration node to check
@@ -315,7 +390,8 @@ module.exports = {
                             message: "Combine this with the previous '{{type}}' statement.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: joinDeclarations(declarations)
                         });
                     } else if (options[type].initialized === MODE_CONSECUTIVE && declarationCounts.initialized > 0 && previousDeclCounts.initialized > 0) {
                         context.report({
@@ -323,7 +399,8 @@ module.exports = {
                             message: "Combine this with the previous '{{type}}' statement with initialized variables.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: joinDeclarations(declarations)
                         });
                     } else if (options[type].uninitialized === MODE_CONSECUTIVE &&
                             declarationCounts.uninitialized > 0 &&
@@ -333,7 +410,8 @@ module.exports = {
                             message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: joinDeclarations(declarations)
                         });
                     }
                 }
@@ -347,7 +425,8 @@ module.exports = {
                         message: "Combine this with the previous '{{type}}' statement.",
                         data: {
                             type
-                        }
+                        },
+                        fix: joinDeclarations(declarations)
                     });
                 } else {
                     if (options[type].initialized === MODE_ALWAYS && declarationCounts.initialized > 0) {
@@ -356,7 +435,8 @@ module.exports = {
                             message: "Combine this with the previous '{{type}}' statement with initialized variables.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: joinDeclarations(declarations)
                         });
                     }
                     if (options[type].uninitialized === MODE_ALWAYS && declarationCounts.uninitialized > 0) {
@@ -368,7 +448,8 @@ module.exports = {
                             message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: joinDeclarations(declarations)
                         });
                     }
                 }
@@ -387,7 +468,8 @@ module.exports = {
                             message: "Split '{{type}}' declarations into multiple statements.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: splitDeclarations(node)
                         });
                     } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) {
 
@@ -397,7 +479,8 @@ module.exports = {
                             message: "Split initialized '{{type}}' declarations into multiple statements.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: splitDeclarations(node)
                         });
                     } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) {
 
@@ -407,7 +490,8 @@ module.exports = {
                             message: "Split uninitialized '{{type}}' declarations into multiple statements.",
                             data: {
                                 type
-                            }
+                            },
+                            fix: splitDeclarations(node)
                         });
                     }
                 }
diff --git a/lib/rules/valid-jsdoc.js b/lib/rules/valid-jsdoc.js
index 4038f70e5..971e755c4 100644
--- a/lib/rules/valid-jsdoc.js
+++ b/lib/rules/valid-jsdoc.js
@@ -102,7 +102,7 @@ module.exports = {
         function startFunction(node) {
             fns.push({
                 returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") ||
-                    isTypeClass(node)
+                    isTypeClass(node) || node.async
             });
         }
 
diff --git a/lib/timing.js b/lib/timing.js
index 9452e419b..102a5233d 100644
--- a/lib/timing.js
+++ b/lib/timing.js
@@ -116,10 +116,10 @@ module.exports = (function() {
             data[key] = 0;
         }
 
-        return function() {
+        return function(...args) {
             let t = process.hrtime();
 
-            fn.apply(null, Array.prototype.slice.call(arguments));
+            fn(...args);
             t = process.hrtime(t);
             data[key] += t[0] * 1e3 + t[1] / 1e6;
         };
diff --git a/lib/util/ajv.js b/lib/util/ajv.js
index f9e8b9853..285176da8 100644
--- a/lib/util/ajv.js
+++ b/lib/util/ajv.js
@@ -19,7 +19,8 @@ const ajv = new Ajv({
     meta: false,
     validateSchema: false,
     missingRefs: "ignore",
-    verbose: true
+    verbose: true,
+    schemaId: "auto"
 });
 
 ajv.addMetaSchema(metaSchema);
diff --git a/lib/util/glob-util.js b/lib/util/glob-util.js
index b91ec53e6..36cb9fcb6 100644
--- a/lib/util/glob-util.js
+++ b/lib/util/glob-util.js
@@ -22,6 +22,15 @@ const debug = require("debug")("eslint:glob-util");
 // Helpers
 //------------------------------------------------------------------------------
 
+/**
+ * Checks whether a directory exists at the given location
+ * @param {string} resolvedPath A path from the CWD
+ * @returns {boolean} `true` if a directory exists
+ */
+function directoryExists(resolvedPath) {
+    return fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory();
+}
+
 /**
  * Checks if a provided path is a directory and returns a glob string matching
  * all files under that directory if so, the path itself otherwise.
@@ -64,7 +73,7 @@ function processPath(options) {
         let newPath = pathname;
         const resolvedPath = path.resolve(cwd, pathname);
 
-        if (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory()) {
+        if (directoryExists(resolvedPath)) {
             newPath = pathname.replace(/[/\\]$/, "") + suffix;
         }
 
@@ -72,6 +81,73 @@ function processPath(options) {
     };
 }
 
+/**
+ * The error type when no files match a glob.
+ */
+class NoFilesFoundError extends Error {
+
+    /**
+     * @param {string} pattern - The glob pattern which was not found.
+     */
+    constructor(pattern) {
+        super(`No files matching '${pattern}' were found.`);
+
+        this.messageTemplate = "file-not-found";
+        this.messageData = { pattern };
+    }
+
+}
+
+/**
+ * The error type when there are files matched by a glob, but all of them have been ignored.
+ */
+class AllFilesIgnoredError extends Error {
+
+    /**
+     * @param {string} pattern - The glob pattern which was not found.
+     */
+    constructor(pattern) {
+        super(`All files matched by '${pattern}' are ignored.`);
+        this.messageTemplate = "all-files-ignored";
+        this.messageData = { pattern };
+    }
+}
+
+const NORMAL_LINT = {};
+const SILENTLY_IGNORE = {};
+const IGNORE_AND_WARN = {};
+
+/**
+ * Tests whether a file should be linted or ignored
+ * @param {string} filename The file to be processed
+ * @param {{ignore: (boolean|null)}} options If `ignore` is false, updates the behavior to
+ * not process custom ignore paths, and lint files specified by direct path even if they
+ * match the default ignore path
+ * @param {boolean} isDirectPath True if the file was provided as a direct path
+ * (as opposed to being resolved from a glob)
+ * @param {IgnoredPaths} ignoredPaths An instance of IgnoredPaths to check whether a given
+ * file is ignored.
+ * @returns {(NORMAL_LINT|SILENTLY_IGNORE|IGNORE_AND_WARN)} A directive for how the
+ * file should be processed (either linted normally, or silently ignored, or ignored
+ * with a warning that it is being ignored)
+ */
+function testFileAgainstIgnorePatterns(filename, options, isDirectPath, ignoredPaths) {
+    const shouldProcessCustomIgnores = options.ignore !== false;
+    const shouldLintIgnoredDirectPaths = options.ignore === false;
+    const fileMatchesIgnorePatterns = ignoredPaths.contains(filename, "default") ||
+        (shouldProcessCustomIgnores && ignoredPaths.contains(filename, "custom"));
+
+    if (fileMatchesIgnorePatterns && isDirectPath && !shouldLintIgnoredDirectPaths) {
+        return IGNORE_AND_WARN;
+    }
+
+    if (!fileMatchesIgnorePatterns || (isDirectPath && shouldLintIgnoredDirectPaths)) {
+        return NORMAL_LINT;
+    }
+
+    return SILENTLY_IGNORE;
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
 //------------------------------------------------------------------------------
@@ -86,7 +162,7 @@ function resolveFileGlobPatterns(patterns, options) {
 
     const processPathExtensions = processPath(options);
 
-    return patterns.filter(p => p.length).map(processPathExtensions);
+    return patterns.map(processPathExtensions);
 }
 
 const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/;
@@ -105,9 +181,6 @@ const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/;
  */
 function listFilesToProcess(globPatterns, providedOptions) {
     const options = providedOptions || { ignore: true };
-    const files = [];
-    const addedFilenames = new Set();
-
     const cwd = options.cwd || process.cwd();
 
     const getIgnorePaths = lodash.memoize(
@@ -115,69 +188,79 @@ function listFilesToProcess(globPatterns, providedOptions) {
             new IgnoredPaths(optionsObj)
     );
 
-    /**
-     * Executes the linter on a file defined by the `filename`. Skips
-     * any files that are already linted.
-     * @param {string} filename The file to be processed
-     * @param {boolean} isDirectPath True if the file
-     * was provided as a direct path (as opposed to being resolved from a glob)
-     * @param {IgnoredPaths} ignoredPaths An instance of IgnoredPaths
-     * @returns {void}
+    /*
+     * The test "should use default options if none are provided" (source-code-util.js) checks that 'module.exports.resolveFileGlobPatterns' was called.
+     * So it cannot use the local function "resolveFileGlobPatterns".
      */
-    function addFile(filename, isDirectPath, ignoredPaths) {
-        if (addedFilenames.has(filename)) {
-            return;
-        }
-
-        const shouldProcessCustomIgnores = options.ignore !== false;
-        const shouldLintIgnoredDirectPaths = options.ignore === false;
-        const fileMatchesIgnorePatterns = ignoredPaths.contains(filename, "default") ||
-            (shouldProcessCustomIgnores && ignoredPaths.contains(filename, "custom"));
-
-        if (fileMatchesIgnorePatterns && isDirectPath && !shouldLintIgnoredDirectPaths) {
-            files.push({ filename, ignored: true });
-            addedFilenames.add(filename);
-        }
-
-        if (!fileMatchesIgnorePatterns || (isDirectPath && shouldLintIgnoredDirectPaths)) {
-            files.push({ filename, ignored: false });
-            addedFilenames.add(filename);
-        }
-    }
+    const resolvedGlobPatterns = module.exports.resolveFileGlobPatterns(globPatterns, options);
 
     debug("Creating list of files to process.");
-    globPatterns.forEach(pattern => {
+    const resolvedPathsByGlobPattern = resolvedGlobPatterns.map(pattern => {
         const file = path.resolve(cwd, pattern);
 
         if (fs.existsSync(file) && fs.statSync(file).isFile()) {
             const ignoredPaths = getIgnorePaths(options);
+            const fullPath = fs.realpathSync(file);
+
+            return [{
+                filename: fullPath,
+                behavior: testFileAgainstIgnorePatterns(fullPath, options, true, ignoredPaths)
+            }];
+        }
 
-            addFile(fs.realpathSync(file), true, ignoredPaths);
-        } else {
+        // regex to find .hidden or /.hidden patterns, but not ./relative or ../relative
+        const globIncludesDotfiles = dotfilesPattern.test(pattern);
+        let newOptions = options;
 
-            // regex to find .hidden or /.hidden patterns, but not ./relative or ../relative
-            const globIncludesDotfiles = dotfilesPattern.test(pattern);
-            let newOptions = options;
+        if (!options.dotfiles) {
+            newOptions = Object.assign({}, options, { dotfiles: globIncludesDotfiles });
+        }
 
-            if (!options.dotfiles) {
-                newOptions = Object.assign({}, options, { dotfiles: globIncludesDotfiles });
-            }
+        const ignoredPaths = getIgnorePaths(newOptions);
+        const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
+        const globOptions = {
+            nodir: true,
+            dot: true,
+            cwd
+        };
 
-            const ignoredPaths = getIgnorePaths(newOptions);
-            const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
-            const globOptions = {
-                nodir: true,
-                dot: true,
-                cwd
+        return new GlobSync(pattern, globOptions, shouldIgnore).found.map(globMatch => {
+            const relativePath = path.resolve(cwd, globMatch);
+
+            return {
+                filename: relativePath,
+                behavior: testFileAgainstIgnorePatterns(relativePath, options, false, ignoredPaths)
             };
+        });
+    });
 
-            new GlobSync(pattern, globOptions, shouldIgnore).found.forEach(globMatch => {
-                addFile(path.resolve(cwd, globMatch), false, ignoredPaths);
-            });
+    const allPathDescriptors = resolvedPathsByGlobPattern.reduce((pathsForAllGlobs, pathsForCurrentGlob, index) => {
+        if (pathsForCurrentGlob.every(pathDescriptor => pathDescriptor.behavior === SILENTLY_IGNORE)) {
+            throw new (pathsForCurrentGlob.length ? AllFilesIgnoredError : NoFilesFoundError)(globPatterns[index]);
         }
-    });
 
-    return files;
+        pathsForCurrentGlob.forEach(pathDescriptor => {
+            switch (pathDescriptor.behavior) {
+                case NORMAL_LINT:
+                    pathsForAllGlobs.push({ filename: pathDescriptor.filename, ignored: false });
+                    break;
+                case IGNORE_AND_WARN:
+                    pathsForAllGlobs.push({ filename: pathDescriptor.filename, ignored: true });
+                    break;
+                case SILENTLY_IGNORE:
+
+                    // do nothing
+                    break;
+
+                default:
+                    throw new Error(`Unexpected file behavior for ${pathDescriptor.filename}`);
+            }
+        });
+
+        return pathsForAllGlobs;
+    }, []);
+
+    return lodash.uniqBy(allPathDescriptors, pathDescriptor => pathDescriptor.filename);
 }
 
 module.exports = {
diff --git a/lib/util/module-resolver.js b/lib/util/module-resolver.js
index 470a54f7c..1e9b66330 100644
--- a/lib/util/module-resolver.js
+++ b/lib/util/module-resolver.js
@@ -59,9 +59,7 @@ class ModuleResolver {
          * subsequent calls to this function. Then, move the extraLookupPath to the
          * top of the lookup paths list so it will be searched first.
          */
-        const lookupPaths = this.options.lookupPaths.concat();
-
-        lookupPaths.unshift(extraLookupPath);
+        const lookupPaths = [extraLookupPath, ...this.options.lookupPaths];
 
         /**
          * Module._findPath is an internal method to Node.js, then one they use to
diff --git a/lib/util/safe-emitter.js b/lib/util/safe-emitter.js
index 2fa373cb9..ab212230d 100644
--- a/lib/util/safe-emitter.js
+++ b/lib/util/safe-emitter.js
@@ -27,8 +27,6 @@
  * another module throws an error or registers a listener.
  * 2. It calls listener functions without any `this` value. (`EventEmitter` calls listeners with a
  * `this` value of the emitter instance, which would give listeners access to other listeners.)
- * 3. Events can be emitted with at most 3 arguments. (For example: when using `emitter.emit('foo', a, b, c)`,
- * the arguments `a`, `b`, and `c` will be passed to the listener functions.)
  * @returns {SafeEmitter} An emitter
  */
 module.exports = () => {
@@ -42,9 +40,9 @@ module.exports = () => {
                 listeners[eventName] = [listener];
             }
         },
-        emit(eventName, a, b, c) {
+        emit(eventName, ...args) {
             if (eventName in listeners) {
-                listeners[eventName].forEach(listener => listener(a, b, c));
+                listeners[eventName].forEach(listener => listener(...args));
             }
         },
         eventNames() {
diff --git a/lib/util/source-code-util.js b/lib/util/source-code-util.js
index 815fad911..66d91cd21 100644
--- a/lib/util/source-code-util.js
+++ b/lib/util/source-code-util.js
@@ -78,14 +78,13 @@ function getSourceCodeOfFiles(patterns, providedOptions, providedCallback) {
         callback = providedCallback;
     }
     debug("constructed options:", options);
-    const resolvedPatterns = globUtil.resolveFileGlobPatterns(globPatternsList, options);
 
-    const filenames = globUtil.listFilesToProcess(resolvedPatterns, options)
+    const filenames = globUtil.listFilesToProcess(globPatternsList, options)
         .filter(fileInfo => !fileInfo.ignored)
         .reduce((files, fileInfo) => files.concat(fileInfo.filename), []);
 
     if (filenames.length === 0) {
-        debug(`Did not find any files matching pattern(s): ${resolvedPatterns}`);
+        debug(`Did not find any files matching pattern(s): ${globPatternsList}`);
     }
     filenames.forEach(filename => {
         const sourceCode = getSourceCodeOfFile(filename, options);
diff --git a/messages/all-files-ignored.txt b/messages/all-files-ignored.txt
new file mode 100644
index 000000000..3b741a03e
--- /dev/null
+++ b/messages/all-files-ignored.txt
@@ -0,0 +1,8 @@
+All of the files matching the glob pattern "<%= pattern %>" are ignored.
+
+If you don't want to lint these files, remove the pattern "<%= pattern %>" from the list of arguments passed to ESLint.
+
+If you do want to lint these files, try the following solutions:
+
+* Check your .eslintignore file, or the eslintIgnore property in package.json, to ensure that the files are not configured to be ignored.
+* Explicitly list the files from this glob that you'd like to lint on the command-line, rather than providing a glob as an argument.
diff --git a/messages/file-not-found.txt b/messages/file-not-found.txt
new file mode 100644
index 000000000..97e2d37fa
--- /dev/null
+++ b/messages/file-not-found.txt
@@ -0,0 +1,2 @@
+No files matching the pattern "<%= pattern %>" were found.
+Please check for typing mistakes in the pattern.
diff --git a/messages/plugin-missing.txt b/messages/plugin-missing.txt
index 00c7fe78b..766020b2b 100644
--- a/messages/plugin-missing.txt
+++ b/messages/plugin-missing.txt
@@ -6,4 +6,6 @@ ESLint couldn't find the plugin "<%- pluginName %>". This can happen for a coupl
 
     npm i <%- pluginName %>@latest --save-dev
 
+Path to ESLint package: <%- eslintPath %>
+
 If you still can't figure out the problem, please stop by https://gitter.im/eslint/eslint to chat with the team.
diff --git a/package.json b/package.json
index 5564e268a..e2e82de34 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "5.0.0-alpha.0",
+  "version": "5.0.0-alpha.2",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -34,14 +34,13 @@
   "homepage": "https://eslint.org",
   "bugs": "https://github.com/eslint/eslint/issues/",
   "dependencies": {
-    "ajv": "^5.3.0",
+    "ajv": "^6.0.1",
     "babel-code-frame": "^6.26.0",
     "chalk": "^2.1.0",
-    "concat-stream": "^1.6.2",
-    "cross-spawn": "^5.1.0",
+    "cross-spawn": "^6.0.5",
     "debug": "^3.1.0",
     "doctrine": "^2.1.0",
-    "eslint-scope": "^3.7.1",
+    "eslint-scope": "^4.0.0-alpha.0",
     "eslint-visitor-keys": "^1.0.0",
     "espree": "^4.0.0-alpha.0",
     "esquery": "^1.0.1",
@@ -52,7 +51,7 @@
     "globals": "^11.4.0",
     "ignore": "^3.3.3",
     "imurmurhash": "^0.1.4",
-    "inquirer": "^3.3.0",
+    "inquirer": "^5.2.0",
     "is-resolvable": "^1.1.0",
     "js-yaml": "^3.11.0",
     "json-stable-stringify-without-jsonify": "^1.0.1",
@@ -70,44 +69,45 @@
     "semver": "^5.5.0",
     "strip-ansi": "^4.0.0",
     "strip-json-comments": "^2.0.1",
-    "table": "4.0.2",
+    "table": "^4.0.3",
     "text-table": "^0.2.0"
   },
   "devDependencies": {
+    "babel-core": "^6.26.0",
     "babel-polyfill": "^6.26.0",
     "babel-preset-es2015": "^6.24.1",
-    "babelify": "^7.3.0",
+    "babelify": "^8.0.0",
     "beefy": "^2.1.8",
     "brfs": "^1.5.0",
-    "browserify": "^14.4.0",
+    "browserify": "^16.1.1",
     "chai": "^4.0.1",
     "cheerio": "^0.22.0",
-    "coveralls": "^2.13.1",
-    "dateformat": "^2.2.0",
+    "coveralls": "^3.0.0",
+    "dateformat": "^3.0.3",
     "ejs": "^2.5.8",
     "eslint-plugin-eslint-plugin": "^1.2.0",
-    "eslint-plugin-node": "^5.2.1",
+    "eslint-plugin-node": "^6.0.1",
     "eslint-plugin-rulesdir": "^0.1.0",
     "eslint-release": "^0.11.1",
     "eslint-rule-composer": "^0.1.1",
-    "eslump": "^1.6.1",
+    "eslump": "^1.6.2",
     "esprima": "^4.0.0",
     "istanbul": "^0.4.5",
     "jsdoc": "^3.5.5",
-    "karma": "^1.7.0",
-    "karma-babel-preprocessor": "^6.0.1",
+    "karma": "^2.0.0",
+    "karma-babel-preprocessor": "^7.0.0",
     "karma-mocha": "^1.3.0",
     "karma-mocha-reporter": "^2.2.3",
     "karma-phantomjs-launcher": "^1.0.4",
     "leche": "^2.2.3",
     "load-perf": "^0.2.0",
-    "markdownlint": "^0.6.4",
-    "mocha": "^3.5.3",
-    "mock-fs": "^4.3.0",
+    "markdownlint": "^0.8.1",
+    "mocha": "^5.0.5",
+    "mock-fs": "^4.5.0",
     "npm-license": "^0.3.3",
     "phantomjs-prebuilt": "^2.1.16",
-    "proxyquire": "^1.8.0",
-    "shelljs": "^0.7.8",
+    "proxyquire": "^2.0.1",
+    "shelljs": "^0.8.1",
     "sinon": "^3.3.0",
     "temp": "^0.8.3",
     "through": "^2.3.8"
@@ -121,6 +121,6 @@
   ],
   "license": "MIT",
   "engines": {
-    "node": ">=4"
+    "node": "^6.14.0 || ^8.10.0 || >=9.10.0"
   }
 }
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index a2f9ed742..611594067 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -24,12 +24,10 @@ rules:
     dot-notation: ["error", { allowKeywords: true }]
     eol-last: "error"
     eqeqeq: "error"
-    for-direction: "error"
     func-call-spacing: "error"
     func-style: ["error", "declaration"]
     function-paren-newline: ["error", "consistent"]
     generator-star-spacing: "error"
-    getter-return: "error"
     guard-for-in: "error"
     handle-callback-err: ["error", "err"]
     key-spacing: ["error", { beforeColon: false, afterColon: true }]
@@ -152,11 +150,14 @@ rules:
     prefer-const: "error"
     prefer-numeric-literals: "error"
     prefer-promise-reject-errors: "error"
+    prefer-rest-params: "error"
+    prefer-spread: "error"
     prefer-template: "error"
     quotes: ["error", "double"]
     quote-props: ["error", "as-needed"]
     radix: "error"
     require-jsdoc: "error"
+    rest-spread-spacing: "error"
     semi: "error"
     semi-spacing: ["error", {before: false, after: true}]
     semi-style: "error"
diff --git a/templates/blogpost.md.ejs b/templates/blogpost.md.ejs
index 05261a58f..4a4ad4091 100644
--- a/templates/blogpost.md.ejs
+++ b/templates/blogpost.md.ejs
@@ -7,7 +7,7 @@ tags:
 ---
 # ESLint v<%= version %> released
 
-We just pushed ESLint v<%- version %>, which is a <%- type %> release upgrade of ESLint. This release <% if (type !== "patch") { %>adds some new features and <% } %>fixes several bugs found in the previous release. <% if (type === "major") { %>This release also has some breaking changes, so please read the following closely. <% } %>
+We just pushed ESLint v<%- version %>, which is a <%- type %> release upgrade of ESLint. This release <% if (type !== "patch") { %>adds some new features and <% } %>fixes several bugs found in the previous release.<% if (type === "major") { %>This release also has some breaking changes, so please read the following closely.<% } %>
 
 <%
 const RULE_REGEX = new RegExp(`\`?\\b(${ruleList.join("|")})\\b\`?`, "g");
diff --git a/tools/eslint-fuzzer.js b/tools/eslint-fuzzer.js
index ea84e994b..342dee3e4 100644
--- a/tools/eslint-fuzzer.js
+++ b/tools/eslint-fuzzer.js
@@ -110,7 +110,7 @@ function fuzz(options) {
         const text = codeGenerator({ sourceType });
         const config = {
             rules: lodash.mapValues(ruleConfigs, lodash.sample),
-            parserOptions: { sourceType, ecmaVersion: 2017 }
+            parserOptions: { sourceType, ecmaVersion: 2018 }
         };
 
         let autofixResult;


Test patch:
diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js
index 3650acf91..318fafe1b 100644
--- a/lib/testers/rule-tester.js
+++ b/lib/testers/rule-tester.js
@@ -396,10 +396,10 @@ class RuleTester {
          * @private
          */
         function assertASTDidntChange(beforeAST, afterAST) {
-            if (!lodash.isEqual(beforeAST, afterAST)) {
 
-                // Not using directly to avoid performance problem in node 6.1.0. See #6111
-                assert.deepStrictEqual(beforeAST, afterAST, "Rule should not modify AST.");
+            // Feature detect the Node.js implementation and use that if available.
+            if ((util.isDeepStrictEqual && !util.isDeepStrictEqual(beforeAST, afterAST)) || !lodash.isEqual(beforeAST, afterAST)) {
+                assert.fail(null, null, "Rule should not modify AST.");
             }
         }
 
diff --git a/tests/fixtures/cli-engine/empty/.keep b/tests/fixtures/cli-engine/empty/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/.eslintrc.yml b/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/.eslintrc.yml
new file mode 100644
index 000000000..c64b2c309
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/.eslintrc.yml
@@ -0,0 +1,6 @@
+root: true
+
+parser: ./parser.js
+parserOptions:
+  ecmaFeatures:
+    experimentalObjectRestSpread: true
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/parser.js b/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/parser.js
new file mode 100644
index 000000000..f193589ef
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/another-parser/parser.js
@@ -0,0 +1,1 @@
+module.exports.parse = () => ({ type: "Program", body: [] })
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/basic/.eslintrc.yml b/tests/fixtures/config-file/experimental-object-rest-spread/basic/.eslintrc.yml
new file mode 100644
index 000000000..a5c9e4ebf
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/basic/.eslintrc.yml
@@ -0,0 +1,5 @@
+root: true
+
+parserOptions:
+  ecmaFeatures:
+    experimentalObjectRestSpread: true
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/extends/.eslintrc.yml b/tests/fixtures/config-file/experimental-object-rest-spread/extends/.eslintrc.yml
new file mode 100644
index 000000000..2daef0dea
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/extends/.eslintrc.yml
@@ -0,0 +1,4 @@
+root: true
+
+extends:
+  - ./common.yml
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/extends/common.yml b/tests/fixtures/config-file/experimental-object-rest-spread/extends/common.yml
new file mode 100644
index 000000000..99975a7bd
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/extends/common.yml
@@ -0,0 +1,3 @@
+parserOptions:
+  ecmaFeatures:
+    experimentalObjectRestSpread: true
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/subdir/.eslintrc.yml b/tests/fixtures/config-file/experimental-object-rest-spread/subdir/.eslintrc.yml
new file mode 100644
index 000000000..a5c9e4ebf
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/subdir/.eslintrc.yml
@@ -0,0 +1,5 @@
+root: true
+
+parserOptions:
+  ecmaFeatures:
+    experimentalObjectRestSpread: true
diff --git a/tests/fixtures/config-file/experimental-object-rest-spread/subdir/lib/.eslintrc.yml b/tests/fixtures/config-file/experimental-object-rest-spread/subdir/lib/.eslintrc.yml
new file mode 100644
index 000000000..78dc43786
--- /dev/null
+++ b/tests/fixtures/config-file/experimental-object-rest-spread/subdir/lib/.eslintrc.yml
@@ -0,0 +1,2 @@
+rules:
+  no-undef: off
diff --git a/tests/fixtures/glob-util/empty/.gitkeep b/tests/fixtures/glob-util/empty/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/lib/ast-utils.js b/tests/lib/ast-utils.js
index 538b941cd..c728b8457 100644
--- a/tests/lib/ast-utils.js
+++ b/tests/lib/ast-utils.js
@@ -42,10 +42,10 @@ describe("ast-utils", () => {
      */
     function mustCall(func) {
         callCounts.set(func, 0);
-        return function Wrapper() {
+        return function Wrapper(...args) {
             callCounts.set(func, callCounts.get(func) + 1);
 
-            return func.apply(this, arguments);
+            return func.call(this, ...args);
         };
     }
 
diff --git a/tests/lib/cli-engine.js b/tests/lib/cli-engine.js
index 54f018da0..23e57ca9b 100644
--- a/tests/lib/cli-engine.js
+++ b/tests/lib/cli-engine.js
@@ -46,15 +46,11 @@ describe("CLIEngine", () => {
      * @returns {string} The path inside the fixture directory.
      * @private
      */
-    function getFixturePath() {
-        const args = Array.prototype.slice.call(arguments);
-
-        args.unshift(fixtureDir);
-        let filepath = path.join.apply(path, args);
+    function getFixturePath(...args) {
+        const filepath = path.join(fixtureDir, ...args);
 
         try {
-            filepath = fs.realpathSync(filepath);
-            return filepath;
+            return fs.realpathSync(filepath);
         } catch (e) {
             return filepath;
         }
@@ -107,6 +103,13 @@ describe("CLIEngine", () => {
                 process.chdir(originalDir);
             }
         });
+
+        it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
+            assert.throws(() => {
+                // eslint-disable-next-line no-new
+                new CLIEngine({ ignorePath: fixtureDir });
+            }, `Error: Could not load file ${fixtureDir}\nError: ${fixtureDir} is not a file`);
+        });
     });
 
     describe("executeOnText()", () => {
@@ -565,11 +568,11 @@ describe("CLIEngine", () => {
             /* eslint-disable no-underscore-dangle */
             before(() => {
                 originalFindPath = Module._findPath;
-                Module._findPath = function(id) {
+                Module._findPath = function(id, ...otherArgs) {
                     if (id === "@scope/eslint-plugin") {
                         return path.resolve(__dirname, "../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
                     }
-                    return originalFindPath.apply(this, arguments);
+                    return originalFindPath.call(this, id, ...otherArgs);
                 };
             });
             after(() => {
@@ -771,9 +774,9 @@ describe("CLIEngine", () => {
                 cwd: getFixturePath("cli-engine")
             });
 
-            const report = engine.executeOnFiles(["node_modules"]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["node_modules"]);
+            }, "All files matched by 'node_modules' are ignored.");
         });
 
         // https://github.com/eslint/eslint/issues/5547
@@ -784,9 +787,9 @@ describe("CLIEngine", () => {
                 ignore: false
             });
 
-            const report = engine.executeOnFiles(["node_modules"]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["node_modules"]);
+            }, "All files matched by 'node_modules' are ignored.");
         });
 
         it("should not check .hidden files if they are passed explicitly without --no-ignore flag", () => {
@@ -1033,35 +1036,32 @@ describe("CLIEngine", () => {
 
         });
 
-        it("should return zero messages when given a directory with eslint excluded files in the directory", () => {
+        it("should throw an error when given a directory with all eslint excluded files in the directory", () => {
 
             engine = new CLIEngine({
                 ignorePath: getFixturePath(".eslintignore")
             });
 
-            const report = engine.executeOnFiles([getFixturePath("./")]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles([getFixturePath("./")]);
+            }, `All files matched by '${getFixturePath("./")}' are ignored.`);
         });
 
-        it("should return zero messages when all given files are ignored", () => {
-            engine = new CLIEngine({
-                ignorePath: getFixturePath(".eslintignore")
-            });
-
-            const report = engine.executeOnFiles(["tests/fixtures/"]);
+        it("should throw an error when all given files are ignored", () => {
 
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["tests/fixtures/"]);
+            }, "All files matched by 'tests/fixtures/' are ignored.");
         });
 
-        it("should return zero messages when all given files are ignored event with a `./` prefix", () => {
+        it("should throw an error when all given files are ignored even with a `./` prefix", () => {
             engine = new CLIEngine({
                 ignorePath: getFixturePath(".eslintignore")
             });
 
-            const report = engine.executeOnFiles(["./tests/fixtures/"]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["./tests/fixtures/"]);
+            }, "All files matched by './tests/fixtures/' are ignored.");
         });
 
         // https://github.com/eslint/eslint/issues/3788
@@ -1085,7 +1085,7 @@ describe("CLIEngine", () => {
         });
 
         // https://github.com/eslint/eslint/issues/3812
-        it("should ignore all files when tests/fixtures/ is in ignore file", () => {
+        it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", () => {
             engine = new CLIEngine({
                 ignorePath: getFixturePath("cli-engine/.eslintignore2"),
                 useEslintrc: false,
@@ -1094,19 +1094,19 @@ describe("CLIEngine", () => {
                 }
             });
 
-            const report = engine.executeOnFiles(["./tests/fixtures/cli-engine/"]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["./tests/fixtures/cli-engine/"]);
+            }, "No files matching './tests/fixtures/cli-engine/' were found.");
         });
 
-        it("should return zero messages when all given files are ignored via ignore-pattern", () => {
+        it("should throw an error when all given files are ignored via ignore-pattern", () => {
             engine = new CLIEngine({
                 ignorePattern: "tests/fixtures/single-quoted.js"
             });
 
-            const report = engine.executeOnFiles(["tests/fixtures/*-quoted.js"]);
-
-            assert.strictEqual(report.results.length, 0);
+            assert.throws(() => {
+                engine.executeOnFiles(["tests/fixtures/*-quoted.js"]);
+            }, "All files matched by 'tests/fixtures/*-quoted.js' are ignored.");
         });
 
         it("should return a warning when an explicitly given file is ignored", () => {
@@ -1348,29 +1348,6 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results[0].messages.length, 0);
         });
 
-        it("should not fail if an ignored file cannot be resolved", () => {
-
-            const fakeFS = leche.fake(fs),
-                LocalCLIEngine = proxyquire("../../lib/cli-engine", {
-                    fs: fakeFS
-                });
-
-            fakeFS.realpathSync = function() {
-                throw new Error("this error should not happen");
-            };
-            fakeFS.existsSync = fs.existsSync;
-            fakeFS.unlinkSync = fs.unlinkSync;
-
-            engine = new LocalCLIEngine({
-                ignorePattern: "tests"
-            });
-
-            assert.doesNotThrow(() => {
-                engine.executeOnFiles(["tests/fixtures/file-not-found.js"]);
-            });
-
-        });
-
         describe("Fix Mode", () => {
 
             it("should return fixed text on multiple files when in fix mode", () => {
@@ -2604,6 +2581,45 @@ describe("CLIEngine", () => {
                 });
             });
         });
+
+        describe("Patterns which match no file should throw errors.", () => {
+            beforeEach(() => {
+                engine = new CLIEngine({
+                    cwd: getFixturePath("cli-engine"),
+                    useEslintrc: false
+                });
+            });
+
+            it("one file", () => {
+                assert.throws(() => {
+                    engine.executeOnFiles(["non-exist.js"]);
+                }, "No files matching 'non-exist.js' were found.");
+            });
+
+            it("should throw if the directory exists and is empty", () => {
+                assert.throws(() => {
+                    engine.executeOnFiles(["empty"]);
+                }, "No files matching 'empty' were found.");
+            });
+
+            it("one glob pattern", () => {
+                assert.throws(() => {
+                    engine.executeOnFiles(["non-exist/**/*.js"]);
+                }, "No files matching 'non-exist/**/*.js' were found.");
+            });
+
+            it("two files", () => {
+                assert.throws(() => {
+                    engine.executeOnFiles(["aaa.js", "bbb.js"]);
+                }, "No files matching 'aaa.js' were found.");
+            });
+
+            it("a mix of an existing file and a non-existing file", () => {
+                assert.throws(() => {
+                    engine.executeOnFiles(["console.js", "non-exist.js"]);
+                }, "No files matching 'non-exist.js' were found.");
+            });
+        });
     });
 
     describe("getConfigForFile", () => {
@@ -2980,9 +2996,10 @@ describe("CLIEngine", () => {
     describe("resolveFileGlobPatterns", () => {
 
         leche.withData([
-            [".", "**/*.js"],
-            ["./", "**/*.js"],
-            ["../", "../**/*.js"]
+            [".", ["**/*.js"]],
+            ["./", ["**/*.js"]],
+            ["../", ["../**/*.js"]],
+            ["", []]
         ], (input, expected) => {
 
             it(`should correctly resolve ${input} to ${expected}`, () => {
@@ -2990,7 +3007,7 @@ describe("CLIEngine", () => {
 
                 const result = engine.resolveFileGlobPatterns([input]);
 
-                assert.strictEqual(result[0], expected);
+                assert.deepStrictEqual(result, expected);
 
             });
         });
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index 7c8801b72..2abf0d0ef 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -72,11 +72,8 @@ describe("cli", () => {
      * @returns {string} The path inside the fixture directory.
      * @private
      */
-    function getFixturePath() {
-        const args = Array.prototype.slice.call(arguments);
-
-        args.unshift(fixtureDir);
-        return path.join.apply(path, args);
+    function getFixturePath(...args) {
+        return path.join(fixtureDir, ...args);
     }
 
     // copy into clean area so as not to get "infected" by this project's .eslintrc files
@@ -323,13 +320,13 @@ describe("cli", () => {
     });
 
     describe("when given a directory with eslint excluded files in the directory", () => {
-        it("should not process any files", () => {
+        it("should throw an error and not process any files", () => {
             const ignorePath = getFixturePath(".eslintignore");
             const filePath = getFixturePath(".");
-            const exit = cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
 
-            assert.isTrue(log.info.notCalled);
-            assert.strictEqual(exit, 0);
+            assert.throws(() => {
+                cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
+            }, `All files matched by '${filePath}' are ignored.`);
         });
     });
 
diff --git a/tests/lib/config.js b/tests/lib/config.js
index 9b7458db1..6baae0e05 100644
--- a/tests/lib/config.js
+++ b/tests/lib/config.js
@@ -83,6 +83,14 @@ function assertConfigsEqual(actual, expected) {
     }
 }
 
+/**
+ * Wait for the next tick.
+ * @returns {Promise<void>} -
+ */
+function nextTick() {
+    return new Promise(resolve => process.nextTick(resolve));
+}
+
 //------------------------------------------------------------------------------
 // Tests
 //------------------------------------------------------------------------------
@@ -97,12 +105,8 @@ describe("Config", () => {
      * @returns {string} The path inside the fixture directory.
      * @private
      */
-    function getFixturePath() {
-        const args = Array.prototype.slice.call(arguments);
-
-        args.unshift("config-hierarchy");
-        args.unshift(fixtureDir);
-        return path.join.apply(path, args);
+    function getFixturePath(...args) {
+        return path.join(fixtureDir, "config-hierarchy", ...args);
     }
 
     /**
@@ -184,14 +188,8 @@ describe("Config", () => {
          * @returns {string} The path inside the fixture directory.
          * @private
          */
-        function getFakeFixturePath() {
-            const args = Array.prototype.slice.call(arguments);
-
-            args.unshift("config-hierarchy");
-            args.unshift("fixtures");
-            args.unshift("eslint");
-            args.unshift(process.cwd());
-            return path.join.apply(path, args);
+        function getFakeFixturePath(...args) {
+            return path.join(process.cwd(), "eslint", "fixtures", "config-hierarchy", ...args);
         }
 
         before(() => {
@@ -834,14 +832,8 @@ describe("Config", () => {
              * @returns {string} The path inside the fixture directory.
              * @private
              */
-            function getFakeFixturePath() {
-                const args = Array.prototype.slice.call(arguments);
-
-                args.unshift("config-hierarchy");
-                args.unshift("fixtures");
-                args.unshift("eslint");
-                args.unshift(process.cwd());
-                return path.join.apply(path, args);
+            function getFakeFixturePath(...args) {
+                return path.join(process.cwd(), "eslint", "fixtures", "config-hierarchy", ...args);
             }
 
             /**
@@ -979,14 +971,8 @@ describe("Config", () => {
              * @returns {string} The path inside the fixture directory.
              * @private
              */
-            function getFakeFixturePath() {
-                const args = Array.prototype.slice.call(arguments);
-
-                args.unshift("config-hierarchy");
-                args.unshift("fixtures");
-                args.unshift("eslint");
-                args.unshift(process.cwd());
-                return path.join.apply(path, args);
+            function getFakeFixturePath(...args) {
+                return path.join(process.cwd(), "eslint", "fixtures", "config-hierarchy", ...args);
             }
 
             /**
@@ -1108,7 +1094,6 @@ describe("Config", () => {
             });
         });
 
-
         describe("with overrides", () => {
 
             /**
@@ -1117,15 +1102,8 @@ describe("Config", () => {
              * @returns {string} The path inside the fixture directory.
              * @private
              */
-            function getFakeFixturePath() {
-                const pathSegments = Array.from(arguments);
-
-                pathSegments.unshift("config-hierarchy");
-                pathSegments.unshift("fixtures");
-                pathSegments.unshift("eslint");
-                pathSegments.unshift(process.cwd());
-
-                return path.join.apply(path, pathSegments);
+            function getFakeFixturePath(...pathSegments) {
+                return path.join(process.cwd(), "eslint", "fixtures", "config-hierarchy", ...pathSegments);
             }
 
             before(() => {
@@ -1388,6 +1366,112 @@ describe("Config", () => {
                 assertConfigsEqual(actual, expected);
             });
         });
+
+        describe("deprecation warnings", () => {
+            let warning = null;
+
+            function onWarning(w) { // eslint-disable-line require-jsdoc
+
+                // Node.js 6.x does not have 'w.code' property.
+                if (!w.hasOwnProperty("code") || typeof w.code === "string" && w.code.startsWith("ESLINT_")) {
+                    warning = w;
+                }
+            }
+
+            beforeEach(() => {
+                warning = null;
+                process.on("warning", onWarning);
+            });
+            afterEach(() => {
+                process.removeListener("warning", onWarning);
+            });
+
+            it("should emit a deprecation warning if 'ecmaFeatures' is given.", () => Promise.resolve()
+                .then(() => {
+                    const cwd = path.resolve(__dirname, "../fixtures/config-file/ecma-features/");
+                    const config = new Config({ cwd }, linter);
+
+                    config.getConfig("test.js");
+
+                    // Wait for "warning" event.
+                    return nextTick();
+                })
+                .then(() => {
+                    assert.notStrictEqual(warning, null);
+                    assert.strictEqual(
+                        warning.message,
+                        `The 'ecmaFeatures' config file property is deprecated, and has no effect. (found in "tests${path.sep}fixtures${path.sep}config-file${path.sep}ecma-features${path.sep}.eslintrc.yml")`
+                    );
+                }));
+
+            it("should emit a deprecation warning if 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' is given.", () => Promise.resolve()
+                .then(() => {
+                    const cwd = path.resolve(__dirname, "../fixtures/config-file/experimental-object-rest-spread/basic/");
+                    const config = new Config({ cwd }, linter);
+
+                    config.getConfig("test.js");
+
+                    // Wait for "warning" event.
+                    return nextTick();
+                })
+                .then(() => {
+                    assert.notStrictEqual(warning, null);
+                    assert.strictEqual(
+                        warning.message,
+                        `The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead. (found in "tests${path.sep}fixtures${path.sep}config-file${path.sep}experimental-object-rest-spread${path.sep}basic${path.sep}.eslintrc.yml")`
+                    );
+                }));
+
+            it("should emit a deprecation warning if 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' is given in a parent config.", () => Promise.resolve()
+                .then(() => {
+                    const cwd = path.resolve(__dirname, "../fixtures/config-file/experimental-object-rest-spread/subdir/");
+                    const config = new Config({ cwd }, linter);
+
+                    config.getConfig("lib/test.js");
+
+                    // Wait for "warning" event.
+                    return nextTick();
+                })
+                .then(() => {
+                    assert.notStrictEqual(warning, null);
+                    assert.strictEqual(
+                        warning.message,
+                        `The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead. (found in "tests${path.sep}fixtures${path.sep}config-file${path.sep}experimental-object-rest-spread${path.sep}subdir${path.sep}.eslintrc.yml")`
+                    );
+                }));
+
+            it("should emit a deprecation warning if 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' is given in a shareable config.", () => Promise.resolve()
+                .then(() => {
+                    const cwd = path.resolve(__dirname, "../fixtures/config-file/experimental-object-rest-spread/extends/");
+                    const config = new Config({ cwd }, linter);
+
+                    config.getConfig("test.js");
+
+                    // Wait for "warning" event.
+                    return nextTick();
+                })
+                .then(() => {
+                    assert.notStrictEqual(warning, null);
+                    assert.strictEqual(
+                        warning.message,
+                        `The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead. (found in "tests${path.sep}fixtures${path.sep}config-file${path.sep}experimental-object-rest-spread${path.sep}extends${path.sep}common.yml")`
+                    );
+                }));
+
+            it("should NOT emit a deprecation warning even if 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' is given, if parser is not espree.", () => Promise.resolve()
+                .then(() => {
+                    const cwd = path.resolve(__dirname, "../fixtures/config-file/experimental-object-rest-spread/another-parser/");
+                    const config = new Config({ cwd }, linter);
+
+                    config.getConfig("test.js");
+
+                    // Wait for "warning" event.
+                    return nextTick();
+                })
+                .then(() => {
+                    assert.strictEqual(warning, null);
+                }));
+        });
     });
 
     describe("Plugin Environments", () => {
diff --git a/tests/lib/config/config-file.js b/tests/lib/config/config-file.js
index 91c6508d4..287a7d67d 100644
--- a/tests/lib/config/config-file.js
+++ b/tests/lib/config/config-file.js
@@ -8,7 +8,8 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const assert = require("chai").assert,
+const Module = require("module"),
+    assert = require("chai").assert,
     leche = require("leche"),
     sinon = require("sinon"),
     path = require("path"),
@@ -127,6 +128,29 @@ function createStubModuleResolver(mapping) {
     };
 }
 
+/**
+ * Overrides the native module resolver to resolve with the given mappings.
+ * @param {Object<string,string>} mapping A mapping of module name to path.
+ * @returns {void}
+ * @private
+ */
+function overrideNativeResolve(mapping) {
+    let originalFindPath;
+
+    beforeEach(() => {
+        originalFindPath = Module._findPath; // eslint-disable-line no-underscore-dangle
+        Module._findPath = function(request, paths, isMain) { // eslint-disable-line no-underscore-dangle
+            if (mapping.hasOwnProperty(request)) {
+                return mapping[request];
+            }
+            return originalFindPath.call(this, request, paths, isMain);
+        };
+    });
+    afterEach(() => {
+        Module._findPath = originalFindPath; // eslint-disable-line no-underscore-dangle
+    });
+}
+
 //------------------------------------------------------------------------------
 // Tests
 //------------------------------------------------------------------------------
@@ -145,6 +169,10 @@ describe("ConfigFile", () => {
 
     describe("applyExtends()", () => {
 
+        overrideNativeResolve({
+            "eslint-plugin-test": getProjectModulePath("eslint-plugin-test")
+        });
+
         it("should apply extension 'foo' when specified from root directory config", () => {
 
             const resolvedPath = path.resolve(PROJECT_PATH, "./node_modules/eslint-config-foo/index.js");
@@ -864,6 +892,10 @@ describe("ConfigFile", () => {
 
         describe("Plugins", () => {
 
+            overrideNativeResolve({
+                "eslint-plugin-test": getProjectModulePath("eslint-plugin-test")
+            });
+
             it("should load information from a YML file and load plugins", () => {
 
                 const stubConfig = new Config({}, new Linter());
@@ -895,9 +927,6 @@ describe("ConfigFile", () => {
                 const resolvedPath = path.resolve(PROJECT_PATH, "./node_modules/eslint-plugin-test/index.js");
 
                 const configDeps = {
-                    "../util/module-resolver": createStubModuleResolver({
-                        "eslint-plugin-test": resolvedPath
-                    }),
                     "require-uncached"(filename) {
                         return configDeps[filename];
                     }
@@ -1000,6 +1029,9 @@ describe("ConfigFile", () => {
     describe("resolve()", () => {
 
         describe("Relative to CWD", () => {
+            overrideNativeResolve({
+                "eslint-plugin-foo": getProjectModulePath("eslint-plugin-foo")
+            });
 
             leche.withData([
                 [".eslintrc", path.resolve(".eslintrc")],
@@ -1035,6 +1067,10 @@ describe("ConfigFile", () => {
 
             const relativePath = path.resolve("./foo/bar");
 
+            overrideNativeResolve({
+                "@foo/eslint-plugin-bar": getProjectModulePath("@foo/eslint-plugin-bar")
+            });
+
             leche.withData([
                 [".eslintrc", path.resolve("./foo/bar", ".eslintrc"), relativePath],
                 ["eslint-config-foo", getRelativeModulePath("eslint-config-foo", relativePath), relativePath],
@@ -1042,7 +1078,7 @@ describe("ConfigFile", () => {
                 ["eslint-configfoo", getRelativeModulePath("eslint-config-eslint-configfoo", relativePath), relativePath],
                 ["@foo/eslint-config", getRelativeModulePath("@foo/eslint-config", relativePath), relativePath],
                 ["@foo/bar", getRelativeModulePath("@foo/eslint-config-bar", relativePath), relativePath],
-                ["plugin:@foo/bar/baz", getRelativeModulePath("@foo/eslint-plugin-bar", relativePath), relativePath]
+                ["plugin:@foo/bar/baz", getProjectModulePath("@foo/eslint-plugin-bar"), relativePath]
             ], (input, expected, relativeTo) => {
                 it(`should return ${expected} when passed ${input}`, () => {
 
@@ -1050,9 +1086,7 @@ describe("ConfigFile", () => {
                         "eslint-config-foo": getRelativeModulePath("eslint-config-foo", relativePath),
                         "eslint-config-eslint-configfoo": getRelativeModulePath("eslint-config-eslint-configfoo", relativePath),
                         "@foo/eslint-config": getRelativeModulePath("@foo/eslint-config", relativePath),
-                        "@foo/eslint-config-bar": getRelativeModulePath("@foo/eslint-config-bar", relativePath),
-                        "eslint-plugin-foo": getRelativeModulePath("eslint-plugin-foo", relativePath),
-                        "@foo/eslint-plugin-bar": getRelativeModulePath("@foo/eslint-plugin-bar", relativePath)
+                        "@foo/eslint-config-bar": getRelativeModulePath("@foo/eslint-config-bar", relativePath)
                     };
 
                     const StubbedConfigFile = proxyquire("../../../lib/config/config-file", {
diff --git a/tests/lib/config/config-initializer.js b/tests/lib/config/config-initializer.js
index e1a24dc36..72c7d2e99 100644
--- a/tests/lib/config/config-initializer.js
+++ b/tests/lib/config/config-initializer.js
@@ -64,15 +64,11 @@ describe("configInitializer", () => {
      * @returns {string} The path inside the fixture directory.
      * @private
      */
-    function getFixturePath() {
-        const args = Array.prototype.slice.call(arguments);
-
-        args.unshift(fixtureDir);
-        let filepath = path.join.apply(path, args);
+    function getFixturePath(...args) {
+        const filepath = path.join(fixtureDir, ...args);
 
         try {
-            filepath = fs.realpathSync(filepath);
-            return filepath;
+            return fs.realpathSync(filepath);
         } catch (e) {
             return filepath;
         }
@@ -316,6 +312,7 @@ describe("configInitializer", () => {
         describe("auto", () => {
             const completeSpy = sinon.spy();
             let config;
+            let sandbox;
 
             before(() => {
                 const patterns = [
@@ -334,23 +331,21 @@ describe("configInitializer", () => {
                     commonjs: false
                 };
 
-                const sandbox = sinon.sandbox.create();
-
+                sandbox = sinon.sandbox.create();
                 sandbox.stub(console, "log"); // necessary to replace, because of progress bar
 
                 process.chdir(fixtureDir);
+                config = init.processAnswers(answers);
+                sandbox.restore();
+            });
 
-                try {
-                    config = init.processAnswers(answers);
-                    process.chdir(originalDir);
-                } catch (err) {
-
-                    // if processAnswers crashes, we need to be sure to restore cwd
-                    process.chdir(originalDir);
-                    throw err;
-                } finally {
-                    sandbox.restore(); // restore console.log()
-                }
+            after(() => {
+                sandbox.restore();
+            });
+
+            afterEach(() => {
+                process.chdir(originalDir);
+                sandbox.restore();
             });
 
             it("should create a config", () => {
@@ -371,25 +366,21 @@ describe("configInitializer", () => {
             it("should throw on fatal parsing error", () => {
                 const filename = getFixturePath("parse-error");
 
-                sinon.stub(autoconfig, "extendFromRecommended");
+                sandbox.stub(autoconfig, "extendFromRecommended");
                 answers.patterns = filename;
                 process.chdir(fixtureDir);
                 assert.throws(() => {
                     config = init.processAnswers(answers);
                 }, "Parsing error: Unexpected token ;");
-                process.chdir(originalDir);
-                autoconfig.extendFromRecommended.restore();
             });
 
             it("should throw if no files are matched from patterns", () => {
-                sinon.stub(autoconfig, "extendFromRecommended");
+                sandbox.stub(autoconfig, "extendFromRecommended");
                 answers.patterns = "not-a-real-filename";
                 process.chdir(fixtureDir);
                 assert.throws(() => {
                     config = init.processAnswers(answers);
-                }, "Automatic Configuration failed.  No files were able to be parsed.");
-                process.chdir(originalDir);
-                autoconfig.extendFromRecommended.restore();
+                }, "No files matching 'not-a-real-filename' were found.");
             });
         });
     });
diff --git a/tests/lib/ignored-paths.js b/tests/lib/ignored-paths.js
index d7e077fe1..42fe5e0e3 100644
--- a/tests/lib/ignored-paths.js
+++ b/tests/lib/ignored-paths.js
@@ -95,11 +95,8 @@ function countDefaultPatterns(ignoredPaths) {
  * @returns {string} The path inside the fixture directory.
  * @private
  */
-function getFixturePath() {
-    const args = Array.prototype.slice.call(arguments);
-
-    args.unshift(fs.realpathSync(fixtureDir));
-    return path.join.apply(path, args);
+function getFixturePath(...args) {
+    return path.join(fs.realpathSync(fixtureDir), ...args);
 }
 
 //------------------------------------------------------------------------------
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index e83e7934e..c73c49c3f 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -1760,31 +1760,6 @@ describe("Linter", () => {
         });
     });
 
-    describe("when evaluating rules that monkeypatch Linter", () => {
-        it("should call `context._linter.report` appropriately", () => {
-            linter.defineRule("foo", context => ({
-                Program() {
-                    context.report({ loc: { line: 5, column: 4 }, message: "foo" });
-                }
-            }));
-
-            const spy = sandbox.spy((ruleId, severity, node, message) => {
-                assert.strictEqual(ruleId, "foo");
-                assert.strictEqual(severity, 2);
-                assert.deepStrictEqual(node.loc, { start: { line: 5, column: 4 } });
-                assert.strictEqual(message, "foo");
-            });
-
-            linter.defineRule("bar", context => {
-                context._linter.report = spy; // eslint-disable-line no-underscore-dangle
-                return {};
-            });
-
-            linter.verify("foo", { rules: { foo: "error", bar: "error" } });
-            assert(spy.calledOnce);
-        });
-    });
-
     describe("when evaluating code with comments to enable and disable all reporting", () => {
         it("should report a violation", () => {
 
@@ -3517,6 +3492,266 @@ describe("Linter", () => {
             linter.verify("x", { rules: { "foo-bar-baz": "error" } });
             assert(spy.calledOnce);
         });
+
+        it("should parse ES2018 code for backward compatibility if 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' is given.", () => {
+            const messages = linter.verify(
+                "async function* f() { let {a, ...rest} = { a, ...obj }; }",
+                { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }
+            );
+
+            assert(messages.length === 0);
+        });
+    });
+
+    describe("context.getScope()", () => {
+
+        /**
+         * Get the scope on the node `astSelector` specified.
+         * @param {string} code The source code to verify.
+         * @param {string} astSelector The AST selector to get scope.
+         * @param {number} [ecmaVersion=5] The ECMAScript version.
+         * @returns {{node: ASTNode, scope: escope.Scope}} Gotten scope.
+         */
+        function getScope(code, astSelector, ecmaVersion = 5) {
+            let node, scope;
+
+            linter.defineRule("get-scope", context => ({
+                [astSelector](node0) {
+                    node = node0;
+                    scope = context.getScope();
+                }
+            }));
+            linter.verify(
+                code,
+                {
+                    parserOptions: { ecmaVersion },
+                    rules: { "get-scope": 2 }
+                }
+            );
+
+            return { node, scope };
+        }
+
+        it("should return 'function' scope on FunctionDeclaration (ES5)", () => {
+            const { node, scope } = getScope("function f() {}", "FunctionDeclaration");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node);
+        });
+
+        it("should return 'function' scope on FunctionExpression (ES5)", () => {
+            const { node, scope } = getScope("!function f() {}", "FunctionExpression");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node);
+        });
+
+        it("should return 'function' scope on the body of FunctionDeclaration (ES5)", () => {
+            const { node, scope } = getScope("function f() {}", "BlockStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent);
+        });
+
+        it("should return 'function' scope on the body of FunctionDeclaration (ES2015)", () => {
+            const { node, scope } = getScope("function f() {}", "BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent);
+        });
+
+        it("should return 'function' scope on BlockStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { { var b; } }", "BlockStatement > BlockStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "b"]);
+        });
+
+        it("should return 'block' scope on BlockStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { { let a; var b; } }", "BlockStatement > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.upper.type, "function");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["a"]);
+            assert.deepStrictEqual(scope.variableScope.variables.map(v => v.name), ["arguments", "b"]);
+        });
+
+        it("should return 'block' scope on nested BlockStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { { let a; { let b; var c; } } }", "BlockStatement > BlockStatement > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.upper.type, "block");
+            assert.strictEqual(scope.upper.upper.type, "function");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["b"]);
+            assert.deepStrictEqual(scope.upper.variables.map(v => v.name), ["a"]);
+            assert.deepStrictEqual(scope.variableScope.variables.map(v => v.name), ["arguments", "c"]);
+        });
+
+        it("should return 'function' scope on SwitchStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { switch (a) { case 0: var b; } }", "SwitchStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "b"]);
+        });
+
+        it("should return 'switch' scope on SwitchStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { switch (a) { case 0: let b; } }", "SwitchStatement", 2015);
+
+            assert.strictEqual(scope.type, "switch");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["b"]);
+        });
+
+        it("should return 'function' scope on SwitchCase in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { switch (a) { case 0: var b; } }", "SwitchCase");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "b"]);
+        });
+
+        it("should return 'switch' scope on SwitchCase in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { switch (a) { case 0: let b; } }", "SwitchCase", 2015);
+
+            assert.strictEqual(scope.type, "switch");
+            assert.strictEqual(scope.block, node.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["b"]);
+        });
+
+        it("should return 'catch' scope on CatchClause in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { try {} catch (e) { var a; } }", "CatchClause");
+
+            assert.strictEqual(scope.type, "catch");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["e"]);
+        });
+
+        it("should return 'catch' scope on CatchClause in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { try {} catch (e) { let a; } }", "CatchClause", 2015);
+
+            assert.strictEqual(scope.type, "catch");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["e"]);
+        });
+
+        it("should return 'catch' scope on the block of CatchClause in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { try {} catch (e) { var a; } }", "CatchClause > BlockStatement");
+
+            assert.strictEqual(scope.type, "catch");
+            assert.strictEqual(scope.block, node.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["e"]);
+        });
+
+        it("should return 'block' scope on the block of CatchClause in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { try {} catch (e) { let a; } }", "CatchClause > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["a"]);
+        });
+
+        it("should return 'function' scope on ForStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { for (var i = 0; i < 10; ++i) {} }", "ForStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "i"]);
+        });
+
+        it("should return 'for' scope on ForStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let i = 0; i < 10; ++i) {} }", "ForStatement", 2015);
+
+            assert.strictEqual(scope.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["i"]);
+        });
+
+        it("should return 'function' scope on the block body of ForStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { for (var i = 0; i < 10; ++i) {} }", "ForStatement > BlockStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "i"]);
+        });
+
+        it("should return 'block' scope on the block body of ForStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let i = 0; i < 10; ++i) {} }", "ForStatement > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.upper.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), []);
+            assert.deepStrictEqual(scope.upper.variables.map(v => v.name), ["i"]);
+        });
+
+        it("should return 'function' scope on ForInStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { for (var key in obj) {} }", "ForInStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "key"]);
+        });
+
+        it("should return 'for' scope on ForInStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let key in obj) {} }", "ForInStatement", 2015);
+
+            assert.strictEqual(scope.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["key"]);
+        });
+
+        it("should return 'function' scope on the block body of ForInStatement in functions (ES5)", () => {
+            const { node, scope } = getScope("function f() { for (var key in obj) {} }", "ForInStatement > BlockStatement");
+
+            assert.strictEqual(scope.type, "function");
+            assert.strictEqual(scope.block, node.parent.parent.parent);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["arguments", "key"]);
+        });
+
+        it("should return 'block' scope on the block body of ForInStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let key in obj) {} }", "ForInStatement > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.upper.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), []);
+            assert.deepStrictEqual(scope.upper.variables.map(v => v.name), ["key"]);
+        });
+
+        it("should return 'for' scope on ForOfStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let x of xs) {} }", "ForOfStatement", 2015);
+
+            assert.strictEqual(scope.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), ["x"]);
+        });
+
+        it("should return 'block' scope on the block body of ForOfStatement in functions (ES2015)", () => {
+            const { node, scope } = getScope("function f() { for (let x of xs) {} }", "ForOfStatement > BlockStatement", 2015);
+
+            assert.strictEqual(scope.type, "block");
+            assert.strictEqual(scope.upper.type, "for");
+            assert.strictEqual(scope.block, node);
+            assert.deepStrictEqual(scope.variables.map(v => v.name), []);
+            assert.deepStrictEqual(scope.upper.variables.map(v => v.name), ["x"]);
+        });
+
+        // Doesn't work for now because of https://github.com/eslint/eslint/issues/10245.
+        xit("should shadow the same name variable by the iteration variable.", () => {
+            const { node, scope } = getScope("let x; for (let x of x) {}", "ForOfStatement", 2015);
+
+            assert.strictEqual(scope.type, "for");
+            assert.strictEqual(scope.upper.type, "global");
+            assert.strictEqual(scope.block, node);
+            assert.strictEqual(scope.upper.variables[0].references.length, 0);
+            assert.strictEqual(scope.references[0].identifier, node.left.declarations[0].id);
+            assert.strictEqual(scope.references[1].identifier, node.right);
+            assert.strictEqual(scope.references[1].resolved, scope.variables[0]);
+        });
     });
 
     describe("Variables and references", () => {
diff --git a/tests/lib/rules/no-case-declarations.js b/tests/lib/rules/no-case-declarations.js
index d72ad515d..676caba63 100644
--- a/tests/lib/rules/no-case-declarations.js
+++ b/tests/lib/rules/no-case-declarations.js
@@ -41,42 +41,42 @@ ruleTester.run("no-case-declarations", rule, {
         {
             code: "switch (a) { case 1: let x = 1; break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "VariableDeclaration" }]
         },
         {
             code: "switch (a) { default: let x = 2; break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "VariableDeclaration" }]
         },
         {
             code: "switch (a) { case 1: const x = 1; break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "VariableDeclaration" }]
         },
         {
             code: "switch (a) { default: const x = 2; break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "VariableDeclaration" }]
         },
         {
             code: "switch (a) { case 1: function f() {} break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "FunctionDeclaration" }]
         },
         {
             code: "switch (a) { default: function f() {} break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "FunctionDeclaration" }]
         },
         {
             code: "switch (a) { case 1: class C {} break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "ClassDeclaration" }]
         },
         {
             code: "switch (a) { default: class C {} break; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "unexpected" }]
+            errors: [{ messageId: "unexpected", type: "ClassDeclaration" }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js
index 3f529aa39..f188f8ce3 100644
--- a/tests/lib/rules/no-unused-vars.js
+++ b/tests/lib/rules/no-unused-vars.js
@@ -596,25 +596,59 @@ ruleTester.run("no-unused-vars", rule, {
         {
             code: "(function(a, b, c) {})",
             options: [{ argsIgnorePattern: "c" }],
-            errors: [{ message: "'b' is defined but never used. Allowed unused args must match /c/." }]
+            errors: [
+                {
+                    message: "'a' is defined but never used. Allowed unused args must match /c/."
+                },
+                {
+                    message: "'b' is defined but never used. Allowed unused args must match /c/."
+                }
+            ]
         },
         {
             code: "(function(a, b, {c, d}) {})",
             options: [{ argsIgnorePattern: "[cd]" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: "'b' is defined but never used. Allowed unused args must match /[cd]/." }]
+            errors: [
+                {
+                    message: "'a' is defined but never used. Allowed unused args must match /[cd]/."
+                },
+                {
+                    message: "'b' is defined but never used. Allowed unused args must match /[cd]/."
+                }
+            ]
         },
         {
             code: "(function(a, b, {c, d}) {})",
             options: [{ argsIgnorePattern: "c" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: "'d' is defined but never used. Allowed unused args must match /c/." }]
+            errors: [
+                {
+                    message: "'a' is defined but never used. Allowed unused args must match /c/."
+                },
+                {
+                    message: "'b' is defined but never used. Allowed unused args must match /c/."
+                },
+                {
+                    message: "'d' is defined but never used. Allowed unused args must match /c/."
+                }
+            ]
         },
         {
             code: "(function(a, b, {c, d}) {})",
             options: [{ argsIgnorePattern: "d" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: "'c' is defined but never used. Allowed unused args must match /d/." }]
+            errors: [
+                {
+                    message: "'a' is defined but never used. Allowed unused args must match /d/."
+                },
+                {
+                    message: "'b' is defined but never used. Allowed unused args must match /d/."
+                },
+                {
+                    message: "'c' is defined but never used. Allowed unused args must match /d/."
+                }
+            ]
         },
         {
             code: "/*global\rfoo*/",
diff --git a/tests/lib/rules/object-shorthand.js b/tests/lib/rules/object-shorthand.js
index 31abe8faa..c52f43af0 100644
--- a/tests/lib/rules/object-shorthand.js
+++ b/tests/lib/rules/object-shorthand.js
@@ -427,6 +427,16 @@ ruleTester.run("object-shorthand", rule, {
             output: "var x = {\n  *f() {\n    /* comment */\n    a(b);\n    }\n  }",
             errors: [METHOD_ERROR]
         },
+        {
+            code: "var x = {\n  f: /* comment */ function() {\n  }\n  }",
+            output: null,
+            errors: [METHOD_ERROR]
+        },
+        {
+            code: "var x = {\n f /* comment */: function() {\n  }\n  }",
+            output: null,
+            errors: [METHOD_ERROR]
+        },
         {
             code: "var x = {y: function() {}}",
             output: "var x = {y() {}}",
diff --git a/tests/lib/rules/one-var.js b/tests/lib/rules/one-var.js
index b8f3a913f..50a2ecf1d 100644
--- a/tests/lib/rules/one-var.js
+++ b/tests/lib/rules/one-var.js
@@ -473,12 +473,24 @@ ruleTester.run("one-var", rule, {
         {
             code: "var a = 1, b = 2; var c; var d; var e = 3, f = 4;",
             options: [{ initialized: "consecutive", uninitialized: "never" }]
+        },
+        {
+            code: "var a; somethingElse(); var b;",
+            output: null,
+            options: [{ var: "never" }],
+            errors: null
+        },
+        {
+            code: "var foo = 1;\nlet bar = function() { var x; };\nvar baz = 2;",
+            output: null,
+            options: [{ var: "never" }],
+            errors: null
         }
-
     ],
     invalid: [
         {
             code: "function foo() { var bar = true, baz = false; }",
+            output: "function foo() { var bar = true; var baz = false; }",
             options: ["never"],
             errors: [{
                 message: "Split 'var' declarations into multiple statements.",
@@ -487,6 +499,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar = true; var baz = false; }",
+            output: "function foo() { var bar = true,  baz = false; }",
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -495,6 +508,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 1; for (var b = 2;;) {}",
+            output: null,
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -503,6 +517,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var foo = true, bar = false; }",
+            output: "function foo() { var foo = true; var bar = false; }",
             options: [{ initialized: "never" }],
             errors: [
                 {
@@ -513,6 +528,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var foo, bar; }",
+            output: "function foo() { var foo; var bar; }",
             options: [{ uninitialized: "never" }],
             errors: [
                 {
@@ -523,6 +539,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar, baz; var a = true; var b = false; var c, d;}",
+            output: "function foo() { var bar, baz; var a = true; var b = false,  c, d;}",
             options: [{ uninitialized: "always", initialized: "never" }],
             errors: [
                 {
@@ -533,6 +550,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar = true, baz = false; var a; var b; var c = true, d = false; }",
+            output: "function foo() { var bar = true, baz = false; var a; var b,  c = true, d = false; }",
             options: [{ uninitialized: "never", initialized: "always" }],
             errors: [
                 {
@@ -543,6 +561,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar = true, baz = false; var a, b;}",
+            output: "function foo() { var bar = true; var baz = false; var a; var b;}",
             options: [{ uninitialized: "never", initialized: "never" }],
             errors: [
                 {
@@ -557,6 +576,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar = true; var baz = false; var a; var b;}",
+            output: "function foo() { var bar = true,  baz = false,  a,  b;}",
             options: [{ uninitialized: "always", initialized: "always" }],
             errors: [
                 {
@@ -575,6 +595,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var a = [1, 2, 3]; var [b, c, d] = a; }",
+            output: "function foo() { var a = [1, 2, 3],  [b, c, d] = a; }",
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -583,6 +604,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { let a = 1; let b = 2; }",
+            output: "function foo() { let a = 1,  b = 2; }",
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'let' statement.",
@@ -591,6 +613,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { const a = 1; const b = 2; }",
+            output: "function foo() { const a = 1,  b = 2; }",
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'const' statement.",
@@ -599,6 +622,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { let a = 1; let b = 2; }",
+            output: "function foo() { let a = 1,  b = 2; }",
             options: [{ let: "always" }],
             errors: [{
                 message: "Combine this with the previous 'let' statement.",
@@ -607,6 +631,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { const a = 1; const b = 2; }",
+            output: "function foo() { const a = 1,  b = 2; }",
             options: [{ const: "always" }],
             errors: [{
                 message: "Combine this with the previous 'const' statement.",
@@ -615,6 +640,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { let a = 1, b = 2; }",
+            output: "function foo() { let a = 1; let b = 2; }",
             options: [{ let: "never" }],
             errors: [{
                 message: "Split 'let' declarations into multiple statements.",
@@ -623,6 +649,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { let a = 1, b = 2; }",
+            output: "function foo() { let a = 1; let b = 2; }",
             options: [{ initialized: "never" }],
             errors: [{
                 message: "Split initialized 'let' declarations into multiple statements.",
@@ -631,6 +658,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { let a, b; }",
+            output: "function foo() { let a; let b; }",
             options: [{ uninitialized: "never" }],
             errors: [{
                 message: "Split uninitialized 'let' declarations into multiple statements.",
@@ -639,6 +667,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { const a = 1, b = 2; }",
+            output: "function foo() { const a = 1; const b = 2; }",
             options: [{ initialized: "never" }],
             errors: [{
                 message: "Split initialized 'const' declarations into multiple statements.",
@@ -647,6 +676,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { const a = 1, b = 2; }",
+            output: "function foo() { const a = 1; const b = 2; }",
             options: [{ const: "never" }],
             errors: [{
                 message: "Split 'const' declarations into multiple statements.",
@@ -655,6 +685,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let foo = true; switch(foo) { case true: let bar = 2; break; case false: let baz = 3; break; }",
+            output: null,
             options: [{ var: "always", let: "always", const: "never" }],
             errors: [{
                 message: "Combine this with the previous 'let' statement.",
@@ -665,6 +696,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var one = 1, two = 2;\nvar three;",
+            output: "var one = 1, two = 2,\n three;",
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -675,6 +707,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var i = [0], j;",
+            output: "var i = [0]; var j;",
             options: [{ initialized: "never" }],
             errors: [{
                 message: "Split initialized 'var' declarations into multiple statements.",
@@ -683,6 +716,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var i = [0], j;",
+            output: "var i = [0]; var j;",
             options: [{ uninitialized: "never" }],
             errors: [{
                 message: "Split uninitialized 'var' declarations into multiple statements.",
@@ -691,6 +725,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "for (var x of foo) {}; for (var y of foo) {}",
+            output: null,
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -699,6 +734,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "for (var x in foo) {}; for (var y in foo) {}",
+            output: null,
             options: ["always"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -707,6 +743,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var foo = function() { var bar = true; var baz = false; }",
+            output: "var foo = function() { var bar = true,  baz = false; }",
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
                 type: "VariableDeclaration",
@@ -716,6 +753,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "function foo() { var bar = true; if (qux) { var baz = false; } else { var quxx = 42; } }",
+            output: null,
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
                 type: "VariableDeclaration",
@@ -730,6 +768,8 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var foo = () => { var bar = true; var baz = false; }",
+            output: "var foo = () => { var bar = true,  baz = false; }",
+            parserOptions: { ecmaVersion: 6 },
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
                 type: "VariableDeclaration",
@@ -739,6 +779,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var foo = function() { var bar = true; if (qux) { var baz = false; } }",
+            output: null,
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
                 type: "VariableDeclaration",
@@ -748,6 +789,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var foo; var bar;",
+            output: "var foo,  bar;",
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
                 type: "VariableDeclaration",
@@ -757,6 +799,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var x = 1, y = 2; for (var z in foo) {}",
+            output: "var x = 1; var y = 2; for (var z in foo) {}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Split initialized 'var' declarations into multiple statements.",
@@ -767,6 +810,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var x = 1, y = 2; for (var z of foo) {}",
+            output: "var x = 1; var y = 2; for (var z of foo) {}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Split initialized 'var' declarations into multiple statements.",
@@ -777,6 +821,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var x; var y; for (var z in foo) {}",
+            output: "var x,  y; for (var z in foo) {}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -787,6 +832,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var x; var y; for (var z of foo) {}",
+            output: "var x,  y; for (var z of foo) {}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -797,6 +843,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var x; for (var y in foo) {var bar = y; var a; for (var z of bar) {}}",
+            output: "var x; for (var y in foo) {var bar = y,  a; for (var z of bar) {}}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -807,6 +854,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 1; var b = 2; var x, y; for (var z of foo) {var c = 3, baz = z; for (var d in baz) {}}",
+            output: "var a = 1; var b = 2; var x, y; for (var z of foo) {var c = 3; var baz = z; for (var d in baz) {}}",
             options: [{ initialized: "never", uninitialized: "always" }],
             errors: [{
                 message: "Split initialized 'var' declarations into multiple statements.",
@@ -815,8 +863,88 @@ ruleTester.run("one-var", rule, {
                 column: 53
             }]
         },
+        {
+            code: "var {foo} = 1, [bar] = 2;",
+            output: "var {foo} = 1; var [bar] = 2;",
+            options: [{ initialized: "never" }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                message: "Split initialized 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "const foo = 1,\n    bar = 2;",
+            output: "const foo = 1;\n\n    \nconst bar = 2;",
+            options: [{ initialized: "never" }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                message: "Split initialized 'const' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "var foo = 1,\n    bar = 2;",
+            output: "var foo = 1;\n\n    \nvar bar = 2;",
+            options: [{ initialized: "never" }],
+            errors: [{
+                message: "Split initialized 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "var foo = 1, // comment\n    bar = 2;",
+            output: "var foo = 1;\n // comment\n    \nvar bar = 2;",
+            options: [{ initialized: "never" }],
+            errors: [{
+                message: "Split initialized 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "var f, k /* test */, l;",
+            output: "var f; var k /* test */; var l;",
+            options: ["never"],
+            errors: [{
+                message: "Split 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "var f,          /* test */ l;",
+            output: "var f;\n          /* test */ \nvar l;",
+            options: ["never"],
+            errors: [{
+                message: "Split 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "var f, k /* test \n some more comment \n even more */, l = 1, P;",
+            output: "var f; var k /* test \n some more comment \n even more */; var l = 1; var P;",
+            options: ["never"],
+            errors: [{
+                message: "Split 'var' declarations into multiple statements.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 1
+            }]
+        },
         {
             code: "var foo = require('foo'), bar;",
+            output: null,
             options: [{ separateRequires: true, var: "always" }],
             parserOptions: { env: { node: true } },
             errors: [{
@@ -828,6 +956,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var foo, bar = require('bar');",
+            output: null,
             options: [{ separateRequires: true, var: "always" }],
             parserOptions: { env: { node: true } },
             errors: [{
@@ -839,6 +968,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let foo, bar = require('bar');",
+            output: null,
             options: [{ separateRequires: true, let: "always" }],
             parserOptions: { env: { node: true } },
             errors: [{
@@ -850,6 +980,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const foo = 0, bar = require('bar');",
+            output: null,
             options: [{ separateRequires: true, const: "always" }],
             parserOptions: { env: { node: true } },
             errors: [{
@@ -861,6 +992,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const foo = require('foo'); const bar = require('bar');",
+            output: "const foo = require('foo'),  bar = require('bar');",
             options: [{ separateRequires: true, const: "always" }],
             parserOptions: { env: { node: true } },
             errors: [{
@@ -874,6 +1006,7 @@ ruleTester.run("one-var", rule, {
         // https://github.com/eslint/eslint/issues/4680
         {
             code: "var a = 1, b; var c;",
+            output: "var a = 1, b,  c;",
             options: ["consecutive"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -884,6 +1017,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0, b = 1; var c = 2;",
+            output: "var a = 0, b = 1,  c = 2;",
             options: ["consecutive"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -894,6 +1028,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 1, b; let c;",
+            output: "let a = 1, b,  c;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -905,6 +1040,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0, b = 1; let c = 2;",
+            output: "let a = 0, b = 1,  c = 2;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -916,6 +1052,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0, b = 1; const c = 2;",
+            output: "const a = 0, b = 1,  c = 2;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -927,6 +1064,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; var b = 1; var c = 2; const d = 3;",
+            output: "const a = 0; var b = 1,  c = 2; const d = 3;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -938,6 +1076,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; let b = 1; let c = 2; const d = 3;",
+            output: "const a = 0; let b = 1,  c = 2; const d = 3;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -949,6 +1088,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; const b = 1; const c = 1; var d = 2;",
+            output: "let a = 0; const b = 1,  c = 1; var d = 2;",
             options: ["consecutive"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -960,6 +1100,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0; var b; var c; var d = 1",
+            output: "var a = 0; var b,  c; var d = 1",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -970,6 +1111,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0; var b = 1; var c; var d;",
+            output: "var a = 0,  b = 1; var c,  d;",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with initialized variables.",
@@ -986,6 +1128,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; let b; let c; let d = 1;",
+            output: "let a = 0; let b,  c; let d = 1;",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -997,6 +1140,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; let b = 1; let c; let d;",
+            output: "let a = 0,  b = 1; let c,  d;",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1014,6 +1158,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; let b; let c; const d = 1;",
+            output: "const a = 0; let b,  c; const d = 1;",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1025,6 +1170,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; const b = 1; let c; let d;",
+            output: "const a = 0,  b = 1; let c,  d;",
             options: [{ initialized: "consecutive", uninitialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1042,6 +1188,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0; var b = 1; var c, d;",
+            output: "var a = 0,  b = 1; var c; var d;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with initialized variables.",
@@ -1058,6 +1205,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0; var b, c; var d = 1;",
+            output: "var a = 0; var b; var c; var d = 1;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             errors: [{
                 message: "Split uninitialized 'var' declarations into multiple statements.",
@@ -1068,6 +1216,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; let b = 1; let c, d;",
+            output: "let a = 0,  b = 1; let c; let d;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1085,6 +1234,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; let b, c; let d = 1;",
+            output: "let a = 0; let b; let c; let d = 1;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1096,6 +1246,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; const b = 1; let c, d;",
+            output: "const a = 0,  b = 1; let c; let d;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1113,6 +1264,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; let b, c; const d = 1;",
+            output: "const a = 0; let b; let c; const d = 1;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1124,6 +1276,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a; var b; var c = 0; var d = 1;",
+            output: "var a,  b; var c = 0,  d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -1140,6 +1293,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a; var b = 0; var c = 1; var d;",
+            output: "var a; var b = 0,  c = 1; var d;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with initialized variables.",
@@ -1150,6 +1304,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; let c = 0; let d = 1;",
+            output: "let a,  b; let c = 0,  d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1167,6 +1322,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b = 0; let c = 1; let d;",
+            output: "let a; let b = 0,  c = 1; let d;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1178,6 +1334,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; const c = 0; const d = 1;",
+            output: "let a,  b; const c = 0,  d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1195,6 +1352,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; const b = 0; const c = 1; let d;",
+            output: "let a; const b = 0,  c = 1; let d;",
             options: [{ uninitialized: "consecutive", initialized: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1206,6 +1364,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a; var b; var c = 0, d = 1;",
+            output: "var a,  b; var c = 0; var d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with uninitialized variables.",
@@ -1222,6 +1381,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a; var b = 0, c = 1; var d;",
+            output: "var a; var b = 0; var c = 1; var d;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             errors: [{
                 message: "Split initialized 'var' declarations into multiple statements.",
@@ -1232,6 +1392,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; let c = 0, d = 1;",
+            output: "let a,  b; let c = 0; let d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1249,6 +1410,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b = 0, c = 1; let d;",
+            output: "let a; let b = 0; let c = 1; let d;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1260,6 +1422,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; const c = 0, d = 1;",
+            output: "let a,  b; const c = 0; const d = 1;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1277,6 +1440,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; const b = 0, c = 1; let d;",
+            output: "let a; const b = 0; const c = 1; let d;",
             options: [{ uninitialized: "consecutive", initialized: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1288,6 +1452,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 0; var b = 1;",
+            output: "var a = 0,  b = 1;",
             options: [{ var: "consecutive" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -1298,6 +1463,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a = 0; let b = 1;",
+            output: "let a = 0,  b = 1;",
             options: [{ let: "consecutive" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1309,6 +1475,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; const b = 1;",
+            output: "const a = 0,  b = 1;",
             options: [{ const: "consecutive" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1320,6 +1487,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; const c = 0; const d = 1;",
+            output: "let a,  b; const c = 0,  d = 1;",
             options: [{ let: "consecutive", const: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1337,6 +1505,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; const b = 0; const c = 1; let d;",
+            output: "let a; const b = 0,  c = 1; let d;",
             options: [{ let: "consecutive", const: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1348,6 +1517,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; let b; const c = 0, d = 1;",
+            output: "let a,  b; const c = 0; const d = 1;",
             options: [{ let: "consecutive", const: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1365,6 +1535,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a; const b = 0, c = 1; let d;",
+            output: "let a; const b = 0; const c = 1; let d;",
             options: [{ let: "consecutive", const: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1376,6 +1547,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; const b = 1; let c; let d;",
+            output: "const a = 0,  b = 1; let c,  d;",
             options: [{ const: "consecutive", let: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1393,6 +1565,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; let b; let c; const d = 1;",
+            output: "const a = 0; let b,  c; const d = 1;",
             options: [{ const: "consecutive", let: "always" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1404,6 +1577,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; const b = 1; let c, d;",
+            output: "const a = 0,  b = 1; let c; let d;",
             options: [{ const: "consecutive", let: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1421,6 +1595,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "const a = 0; let b, c; const d = 1;",
+            output: "const a = 0; let b; let c; const d = 1;",
             options: [{ const: "consecutive", let: "never" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1432,6 +1607,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var bar; var baz;",
+            output: "var bar,  baz;",
             options: ["consecutive"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -1442,6 +1618,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var bar = 1; var baz = 2; qux(); var qux = 3; var quux;",
+            output: "var bar = 1,  baz = 2; qux(); var qux = 3,  quux;",
             options: ["consecutive"],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -1458,6 +1635,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "let a, b; let c; var d, e;",
+            output: "let a, b,  c; var d; var e;",
             options: [{ var: "never", let: "consecutive", const: "consecutive" }],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
@@ -1475,6 +1653,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a; var b;",
+            output: "var a,  b;",
             options: [{ var: "consecutive" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement.",
@@ -1485,6 +1664,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 1; var b = 2; var c, d; var e = 3; var f = 4;",
+            output: "var a = 1,  b = 2; var c; var d; var e = 3,  f = 4;",
             options: [{ initialized: "consecutive", uninitialized: "never" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with initialized variables.",
@@ -1507,6 +1687,7 @@ ruleTester.run("one-var", rule, {
         },
         {
             code: "var a = 1; var b = 2; foo(); var c = 3; var d = 4;",
+            output: "var a = 1,  b = 2; foo(); var c = 3,  d = 4;",
             options: [{ initialized: "consecutive" }],
             errors: [{
                 message: "Combine this with the previous 'var' statement with initialized variables.",
diff --git a/tests/lib/rules/valid-jsdoc.js b/tests/lib/rules/valid-jsdoc.js
index d6e0219c5..7304192be 100644
--- a/tests/lib/rules/valid-jsdoc.js
+++ b/tests/lib/rules/valid-jsdoc.js
@@ -267,6 +267,32 @@ ruleTester.run("valid-jsdoc", rule, {
             options: [{ requireReturn: false }]
         },
 
+        // async function
+        {
+            code:
+              "/**\n" +
+              " * An async function. Options requires return.\n" +
+              " * @returns {Promise} that is empty\n" +
+              " */\n" +
+              "async function a() {}",
+            options: [{ requireReturn: true }],
+            parserOptions: {
+                ecmaVersion: 2017
+            }
+        },
+        {
+            code:
+              "/**\n" +
+              " * An async function. Options do not require return.\n" +
+              " * @returns {Promise} that is empty\n" +
+              " */\n" +
+              "async function a() {}",
+            options: [{ requireReturn: false }],
+            parserOptions: {
+                ecmaVersion: 2017
+            }
+        },
+
         // type validations
         {
             code:
diff --git a/tests/lib/testers/rule-tester.js b/tests/lib/testers/rule-tester.js
index 6456359a7..a3f8073c2 100644
--- a/tests/lib/testers/rule-tester.js
+++ b/tests/lib/testers/rule-tester.js
@@ -9,11 +9,20 @@
 //------------------------------------------------------------------------------
 // Requirements
 //------------------------------------------------------------------------------
-
 const sinon = require("sinon"),
     EventEmitter = require("events"),
     RuleTester = require("../../../lib/testers/rule-tester"),
-    assert = require("chai").assert;
+    assert = require("chai").assert,
+    nodeAssert = require("assert");
+
+const NODE_ASSERT_STRICT_EQUAL_OPERATOR = (() => {
+    try {
+        nodeAssert.strictEqual(1, 2);
+    } catch (err) {
+        return err.operator;
+    }
+    throw new Error("unexpected successful assertion");
+})();
 
 //------------------------------------------------------------------------------
 // Rewire Things
@@ -53,6 +62,23 @@ describe("RuleTester", () => {
 
     let ruleTester;
 
+    /**
+     * @description A helper function to verify Node.js core error messages.
+     * @param {string} actual The actual input
+     * @param {string} expected The expected input
+     * @returns {Function} Error callback to verify that the message is correct
+     *                     for the actual and expected input.
+     */
+    function assertErrorMatches(actual, expected) {
+        const err = new nodeAssert.AssertionError({
+            actual,
+            expected,
+            operator: NODE_ASSERT_STRICT_EQUAL_OPERATOR
+        });
+
+        return err.message;
+    }
+
     beforeEach(() => {
         RuleTester.resetDefaultConfig();
         ruleTester = new RuleTester();
@@ -126,7 +152,7 @@ describe("RuleTester", () => {
                     { code: "var foo = bar;", errors: [{ message: "Bad error message." }] }
                 ]
             });
-        }, /Bad var\.((.*==)|(.*strictEqual)).*Bad error message/);
+        }, assertErrorMatches("Bad var.", "Bad error message."));
     });
 
     it("should throw an error when the error message regex does not match", () => {
@@ -167,7 +193,7 @@ describe("RuleTester", () => {
                     { code: "var foo = bar;", errors: ["Bad error message."] }
                 ]
             });
-        }, /Bad var\.((.*==)|(.*strictEqual)).*Bad error message/);
+        }, assertErrorMatches("Bad var.", "Bad error message."));
     });
 
     it("should throw an error when the error is a string and it does not match error message", () => {
diff --git a/tests/lib/util/glob-util.js b/tests/lib/util/glob-util.js
index d4ac651b8..516b1bc83 100644
--- a/tests/lib/util/glob-util.js
+++ b/tests/lib/util/glob-util.js
@@ -26,11 +26,8 @@ let fixtureDir;
  * @returns {string} The path inside the fixture directory.
  * @private
  */
-function getFixturePath() {
-    const args = Array.prototype.slice.call(arguments);
-
-    args.unshift(fs.realpathSync(fixtureDir));
-    return path.join.apply(path, args);
+function getFixturePath(...args) {
+    return path.join(fs.realpathSync(fixtureDir), ...args);
 }
 
 //------------------------------------------------------------------------------
@@ -143,17 +140,6 @@ describe("globUtil", () => {
 
             assert.deepStrictEqual(result, ["one-js-file/example.js"]);
         });
-
-        it("should ignore empty patterns", () => {
-            const patterns = [""];
-            const opts = {
-                cwd: getFixturePath()
-            };
-            const result = globUtil.resolveFileGlobPatterns(patterns, opts);
-
-            assert.deepStrictEqual(result, []);
-        });
-
     });
 
     describe("listFilesToProcess()", () => {
@@ -207,13 +193,14 @@ describe("globUtil", () => {
             ]);
         });
 
-        it("should not return hidden files for standard glob patterns", () => {
+        it("should ignore hidden files for standard glob patterns", () => {
             const patterns = [getFixturePath("glob-util", "hidden", "**/*.js")];
-            const result = globUtil.listFilesToProcess(patterns, {
-                cwd: getFixturePath()
-            });
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, {
+                    cwd: getFixturePath()
+                });
+            }, `All files matched by '${patterns[0]}' are ignored.`);
         });
 
         it("should return hidden files if included in glob pattern", () => {
@@ -230,14 +217,15 @@ describe("globUtil", () => {
             ]);
         });
 
-        it("should silently ignore default ignored files if not passed explicitly", () => {
+        it("should ignore default ignored files if not passed explicitly", () => {
             const directory = getFixturePath("glob-util", "hidden");
             const patterns = [directory];
-            const result = globUtil.listFilesToProcess(patterns, {
-                cwd: getFixturePath()
-            });
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, {
+                    cwd: getFixturePath()
+                });
+            }, `All files matched by '${directory}' are ignored.`);
         });
 
         it("should ignore and warn for default ignored files when passed explicitly", () => {
@@ -251,15 +239,16 @@ describe("globUtil", () => {
             assert.deepStrictEqual(result[0], { filename, ignored: true });
         });
 
-        it("should silently ignore default ignored files if not passed explicitly even if ignore is false", () => {
+        it("should ignore default ignored files if not passed explicitly even if ignore is false", () => {
             const directory = getFixturePath("glob-util", "hidden");
             const patterns = [directory];
-            const result = globUtil.listFilesToProcess(patterns, {
-                cwd: getFixturePath(),
-                ignore: false
-            });
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, {
+                    cwd: getFixturePath(),
+                    ignore: false
+                });
+            }, `All files matched by '${directory}' are ignored.`);
         });
 
         it("should not ignore default ignored files when passed explicitly if ignore is false", () => {
@@ -274,20 +263,46 @@ describe("globUtil", () => {
             assert.deepStrictEqual(result[0], { filename, ignored: false });
         });
 
-        it("should not return a file which does not exist", () => {
-            const patterns = ["tests/fixtures/glob-util/hidden/bar.js"];
-            const result = globUtil.listFilesToProcess(patterns);
+        it("should throw an error for a file which does not exist", () => {
+            const filename = getFixturePath("glob-util", "hidden", "bar.js");
+            const patterns = [filename];
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, {
+                    cwd: getFixturePath(),
+                    allowMissingGlobs: true
+                });
+            }, `No files matching '${filename}' were found.`);
         });
 
-        it("should not return an ignored file", () => {
+        it("should throw if a folder that does not have any applicable files is linted", () => {
+            const filename = getFixturePath("glob-util", "empty");
+            const patterns = [filename];
+
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, {
+                    cwd: getFixturePath()
+                });
+            }, `No files matching '${filename}' were found.`);
+        });
+
+        it("should throw if only ignored files match a glob", () => {
+            const pattern = getFixturePath("glob-util", "ignored");
+            const options = { ignore: true, ignorePath: getFixturePath("glob-util", "ignored", ".eslintignore") };
+
+            assert.throws(() => {
+                globUtil.listFilesToProcess([pattern], options);
+            }, `All files matched by '${pattern}' are ignored.`);
+        });
+
+        it("should throw an error if no files match a glob", () => {
 
             // Relying here on the .eslintignore from the repo root
             const patterns = ["tests/fixtures/glob-util/ignored/**/*.js"];
-            const result = globUtil.listFilesToProcess(patterns);
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns);
+            }, `No files matching '${patterns[0]}' were found.`);
         });
 
         it("should return an ignored file, if ignore option is turned off", () => {
@@ -298,20 +313,22 @@ describe("globUtil", () => {
             assert.strictEqual(result.length, 1);
         });
 
-        it("should not return a file from a glob if it matches a pattern in an ignore file", () => {
+        it("should ignore a file from a glob if it matches a pattern in an ignore file", () => {
             const options = { ignore: true, ignorePath: getFixturePath("glob-util", "ignored", ".eslintignore") };
             const patterns = [getFixturePath("glob-util", "ignored", "**/*.js")];
-            const result = globUtil.listFilesToProcess(patterns, options);
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, options);
+            }, `All files matched by '${patterns[0]}' are ignored.`);
         });
 
-        it("should not return a file from a glob if matching a specified ignore pattern", () => {
+        it("should ignore a file from a glob if matching a specified ignore pattern", () => {
             const options = { ignore: true, ignorePattern: "foo.js", cwd: getFixturePath() };
             const patterns = [getFixturePath("glob-util", "ignored", "**/*.js")];
-            const result = globUtil.listFilesToProcess(patterns, options);
 
-            assert.strictEqual(result.length, 0);
+            assert.throws(() => {
+                globUtil.listFilesToProcess(patterns, options);
+            }, `All files matched by '${patterns[0]}' are ignored.`);
         });
 
         it("should return a file only once if listed in more than 1 pattern", () => {
diff --git a/tests/lib/util/source-code-util.js b/tests/lib/util/source-code-util.js
index 44bb6613d..1a406e5d3 100644
--- a/tests/lib/util/source-code-util.js
+++ b/tests/lib/util/source-code-util.js
@@ -35,11 +35,8 @@ describe("SourceCodeUtil", () => {
      * @returns {string} The path inside the fixture directory.
      * @private
      */
-    function getFixturePath() {
-        const args = Array.prototype.slice.call(arguments);
-
-        args.unshift(fixtureDir);
-        let filepath = path.join.apply(path, args);
+    function getFixturePath(...args) {
+        let filepath = path.join(fixtureDir, ...args);
 
         try {
             filepath = fs.realpathSync(filepath);
@@ -158,11 +155,12 @@ describe("SourceCodeUtil", () => {
             assert.property(sourceCode, barFilename);
         });
 
-        it("should should not include non-existent filesnames in results", () => {
+        it("should should not include non-existent filenames in results", () => {
             const filename = getFixturePath("missing.js");
-            const sourceCode = getSourceCodeOfFiles(filename, { cwd: fixtureDir });
 
-            assert.notProperty(sourceCode, filename);
+            assert.throws(() => {
+                getSourceCodeOfFiles(filename, { cwd: fixtureDir });
+            }, `No files matching '${filename}' were found.`);
         });
 
         it("should throw for files with parsing errors", () => {
@@ -251,9 +249,8 @@ describe("SourceCodeUtil", () => {
             const firstFn = getFixturePath("foo.js");
             const secondFn = getFixturePath("bar.js");
             const thirdFn = getFixturePath("nested/foo.js");
-            const missingFn = getFixturePath("missing.js");
 
-            getSourceCodeOfFiles([firstFn, secondFn, thirdFn, missingFn], { cwd: fixtureDir }, callback);
+            getSourceCodeOfFiles([firstFn, secondFn, thirdFn], { cwd: fixtureDir }, callback);
             assert(callback.calledWith(3));
         });