Repository: eslint/eslint
Pull request #8341 (2017-03-26 23:44:21)

Fix: Space-infix-ops should ignore type annotations in TypeScript
Typescript allows type annotations in variable declarations. This commit
ensures they are skipped over and not considered when checking Variable
Declaration nodes.

**What is the purpose of this pull request? (put an "X" next to item)**
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
**Tell us about your environment**

* **ESLint Version:**
master
* **Node Version:**
node v4
* **npm Version:**
npm v4

**What parser (default, Babel-ESLint, etc.) are you using?**
typescript-eslint-parser 2.0

**Please show your full configuration:**
```
    "env": {
        "es6": true,
        "node": true,
        "mocha": true
    },
    "parser": "typescript-eslint-parser",
    "parserOptions": {
        "sourceType": "module",
        "ecmaFeatures": {
            "jsx": true
        }
    },
    "rules": {
        "space-infix-ops": "error"
    }
```

**What did you do? Please include the actual source code causing the issue.**
```ts
var a: Foo = '';
```
This code is causes the space-infix-ops rule to fail since it contains a colon(:) inbetween the variable identifier node and the initialization node.
**What did you expect to happen?**
It should ignore type annotations and only check for a space between the type annotation and the equal(=) sign.
**What actually happened? Please include the actual, raw output from ESLint.**
Eslint flags the colon(:) as an error and requires a space in-between it and the variable identifier

**What changes did you make? (Give an overview)**
I changed the way we check variable declaration by checking tokens between the type annotation, if it exists, and the initalizer.

**Is there anything you'd like reviewers to focus on?**
To make sure I did not miss any cases that would cause false positives. There is also this issue:
https://github.com/eslint/eslint/issues/7162 But it has a false positive in JSX, which I cannot reproduce in typescript. I can look into and add a solution to this PR.



eslintbot: LGTM
mention-bot: @soda0289, thanks for your PR! By analyzing the history of the files in this pull request, we identified @gyandeeps, @michaelficarra and @Kirill89 to be potential reviewers.
soda0289: I will add some more tests for invalid cases with type annotations. For example:
```ts
var a: Foo='';
function (a: number=0){}
```

eslintbot: LGTM
soda0289: I have added the tests. The rule can now identify valid and invalid uses for variable declarations and assignment expressions.
kaicataldo: My only concern is that we're starting to add Typescript specific tests into core. Should we also be adding Babel/Flow tests then as well?
soda0289: I think these kind of integration tests, between the AST produced by typescript/babel parser and eslint rules, could be moved to the parser themselves. It is important we have tests for all the changes we make to rules, but maybe we could get away with smaller unit tests. Where we only test the node listener functions in the plugin with a mock node and mock rule context. Or create a more generic AST that is aligned with what estree defines. 
kaicataldo: I really like the idea of creating a way to test these kinds of things in babel-eslint/typescript-eslint-parser :+1:
mattdell: Does this require more work fro @soda0289 or does it just needs 1 more approval from @kaicataldo ?

I'm keen to rid my code of `// eslint-disable-line space-infix-ops` everywhere.
kaicataldo: @eslint/eslint-team any other thoughts on this? I'm still of the mind that the unit tests in ESLint should be parser agnostic, but I don't want to block this from landing. Having a way to tes witht a more generic AST could be nice.
soda0289: @kaicataldo I also think we should change this to a more generic AST. I will make this change tonight.
eslintbot: LGTM
soda0289: @kaicataldo I tried to make the tests more generic by removing the TS prefix on the types and placing the fixtures in a type-annotations folder. The one created from babel flow I didn't change, just moved to the type-annotation folder.
mattdell: Anything left for this? Looks all green to me.
JamesHenry: @kaicataldo @soda0289 It seems like the concerns on this one were addressed?
eslintbot: LGTM
soda0289: @kaicataldo Think it should be more generic now. I could always try to make unit tests but not really sure where to start with those.
kaicataldo: We'll most likely be updating more rules like this in the future - might be nice to figure out a way to use the parsers themselves in tests. I think this is a fine for now though :+1:

Patch:
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 000000000..c1ca392fe
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,1 @@
+package-lock = false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e54322fbe..7626f8970 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+v4.0.0 - June 11, 2017
+
+* 4aefb49 Chore: avoid using deprecated rules on ESLint codebase (#8708) (Teddy Katz)
+* 389feba Chore: upgrade deps. (#8684) (薛定谔的猫)
+* 3da7b5e Fix: Semi-Style only check for comments when tokens exist (fixes #8696) (#8697) (Reyad Attiyat)
+* 3cfe9ee Fix: Add space between async and param on fix (fixes #8682) (#8693) (Reyad Attiyat)
+* c702858 Chore: enable no-multiple-empty-lines on ESLint codebase (#8694) (Teddy Katz)
+* 34c4020 Update: Add support for parens on left side for-loops (fixes: #8393) (#8679) (Victor Hom)
+* 735cd09 Docs: Correct the comment in an example for `no-mixed-requires` (#8686) (Fangzhou Li)
+* 026f048 Chore: remove dead code from prefer-const (#8683) (Teddy Katz)
+
 v4.0.0-rc.0 - June 2, 2017
 
 * 0058b0f8 Update: add --fix to no-debugger (#8660) (薛定谔的猫)
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index 03a1dd794..f48670896 100644
--- a/docs/developer-guide/nodejs-api.md
+++ b/docs/developer-guide/nodejs-api.md
@@ -147,6 +147,37 @@ console.log(code.text);     // "var foo = bar;"
 
 In this way, you can retrieve the text and AST used for the last run of `linter.verify()`.
 
+### verifyAndFix()
+
+This method is similar to verify except that it also runs autofixing logic, similar to the `--fix` flag on the command line. The result object will contain the autofixed code, along with any remaining linting messages for the code that were not autofixed.
+
+```js
+var Linter = require("eslint").Linter;
+var linter = new Linter();
+
+var messages = linter.verifyAndFix("var foo", {
+    rules: {
+        semi: 2
+    }
+}, { filename: "foo.js" });
+```
+
+Output object from this method:
+
+```js
+{
+    fixed: true,
+    text: "var foo;",
+    messages: []
+}
+```
+
+The information available is:
+
+* `fixed` - True, if the code was fixed.
+* `text` - Fixed code text (might be the same as input if no fixes were applied).
+* `messages` - Collection of all messages for the given code (It has the same information as explained above under `verify` block).
+
 ## linter
 
 The `eslint.linter` object (deprecated) is an instance of the `Linter` class as defined [above](#Linter). `eslint.linter` exists for backwards compatibility, but we do not recommend using it because any mutations to it are shared among every module that uses `eslint`. Instead, please create your own instance of `eslint.Linter`.
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 3f59e8672..86469a5af 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -775,6 +775,22 @@ You can also use your `.gitignore` file:
 
 Any file that follows the standard ignore file format can be used. Keep in mind that specifying `--ignore-path` means that any existing `.eslintignore` file will not be used. Note that globbing rules in `.eslintignore` follow those of `.gitignore`.
 
+### Using eslintIgnore in package.json
+
+If an `.eslintignore` file is not found and an alternate file is not specified, eslint will look in package.json for an `eslintIgnore` key to check for files to ignore.
+
+    {
+      "name": "mypackage",
+      "version": "0.0.1",
+      "eslintConfig": {
+          "env": {
+              "browser": true,
+              "node": true
+          }
+      },
+      "eslintIgnore": ["hello.js", "world.js"]
+    }
+
 ### Ignored File Warnings
 
 When you pass directories to ESLint, files and directories are silently ignored. If you pass a specific file to ESLint, then you will see a warning indicating that the file was skipped. For example, suppose you have an `.eslintignore` file that looks like this:
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 46628c1e4..f53c2e76a 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -23,11 +23,9 @@ const fs = require("fs"),
     Config = require("./config"),
     fileEntryCache = require("file-entry-cache"),
     globUtil = require("./util/glob-util"),
-    SourceCodeFixer = require("./util/source-code-fixer"),
     validator = require("./config/config-validator"),
     stringify = require("json-stable-stringify"),
     hash = require("./util/hash"),
-
     pkg = require("../package.json");
 
 const debug = require("debug")("eslint:cli-engine");
@@ -132,80 +130,6 @@ function calculateStatsPerRun(results) {
     });
 }
 
-/**
- * Performs multiple autofix passes over the text until as many fixes as possible
- * have been applied.
- * @param {string} text The source text to apply fixes to.
- * @param {Object} config The ESLint config object to use.
- * @param {Object} options The ESLint options object to use.
- * @param {string} options.filename The filename from which the text was read.
- * @param {boolean} options.allowInlineConfig Flag indicating if inline comments
- *      should be allowed.
- * @param {Linter} linter Linter context
- * @returns {Object} The result of the fix operation as returned from the
- *      SourceCodeFixer.
- * @private
- */
-function multipassFix(text, config, options, linter) {
-    const MAX_PASSES = 10;
-    let messages = [],
-        fixedResult,
-        fixed = false,
-        passNumber = 0;
-
-    /**
-     * This loop continues until one of the following is true:
-     *
-     * 1. No more fixes have been applied.
-     * 2. Ten passes have been made.
-     *
-     * That means anytime a fix is successfully applied, there will be another pass.
-     * Essentially, guaranteeing a minimum of two passes.
-     */
-    do {
-        passNumber++;
-
-        debug(`Linting code for ${options.filename} (pass ${passNumber})`);
-        messages = linter.verify(text, config, options);
-
-        debug(`Generating fixed text for ${options.filename} (pass ${passNumber})`);
-        fixedResult = SourceCodeFixer.applyFixes(linter.getSourceCode(), messages);
-
-        // stop if there are any syntax errors.
-        // 'fixedResult.output' is a empty string.
-        if (messages.length === 1 && messages[0].fatal) {
-            break;
-        }
-
-        // keep track if any fixes were ever applied - important for return value
-        fixed = fixed || fixedResult.fixed;
-
-        // update to use the fixed output instead of the original text
-        text = fixedResult.output;
-
-    } while (
-        fixedResult.fixed &&
-        passNumber < MAX_PASSES
-    );
-
-
-    /*
-     * If the last result had fixes, we need to lint again to be sure we have
-     * the most up-to-date information.
-     */
-    if (fixedResult.fixed) {
-        fixedResult.messages = linter.verify(text, config, options);
-    }
-
-
-    // ensure the last result properly reflects if fixes were done
-    fixedResult.fixed = fixed;
-    fixedResult.output = text;
-
-    return fixedResult;
-
-}
-
 /**
  * Processes an source code using ESLint.
  * @param {string} text The source code to check.
@@ -269,10 +193,10 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, linte
     } else {
 
         if (fix) {
-            fixedResult = multipassFix(text, config, {
+            fixedResult = linter.verifyAndFix(text, config, {
                 filename,
                 allowInlineConfig
-            }, linter);
+            });
             messages = fixedResult.messages;
         } else {
             messages = linter.verify(text, config, {
@@ -685,7 +609,6 @@ class CLIEngine {
         const startTime = Date.now();
 
 
-
         patterns = this.resolveFileGlobPatterns(patterns);
         const fileList = globUtil.listFilesToProcess(patterns, options);
 
diff --git a/lib/config/config-file.js b/lib/config/config-file.js
index 71ef45d3a..c9fcc9dff 100644
--- a/lib/config/config-file.js
+++ b/lib/config/config-file.js
@@ -513,7 +513,6 @@ function resolve(filePath, relativeTo) {
     return { filePath };
 
 
-
 }
 
 /**
diff --git a/lib/config/config-initializer.js b/lib/config/config-initializer.js
index ed4bde875..e87cb79b6 100644
--- a/lib/config/config-initializer.js
+++ b/lib/config/config-initializer.js
@@ -62,42 +62,47 @@ function writeFile(config, format) {
  * @returns {void}
  */
 function installModules(config) {
-    let modules = [];
+    const modules = {};
 
     // Create a list of modules which should be installed based on config
     if (config.plugins) {
-        modules = modules.concat(config.plugins.map(name => `eslint-plugin-${name}`));
+        for (const plugin of config.plugins) {
+            modules[`eslint-plugin-${plugin}`] = "latest";
+        }
     }
     if (config.extends && config.extends.indexOf("eslint:") === -1) {
-        modules.push(`eslint-config-${config.extends}`);
+        const moduleName = `eslint-config-${config.extends}`;
+
+        log.info(`Checking peerDependencies of ${moduleName}`);
+        modules[moduleName] = "latest";
+        Object.assign(
+            modules,
+            npmUtil.fetchPeerDependencies(`${moduleName}@latest`)
+        );
     }
 
-    // Determine which modules are already installed
-    if (modules.length === 0) {
+    // If no modules, do nothing.
+    if (Object.keys(modules).length === 0) {
         return;
     }
 
     // Add eslint to list in case user does not have it installed locally
-    modules.unshift("eslint");
+    modules.eslint = modules.eslint || "latest";
 
-    const installStatus = npmUtil.checkDevDeps(modules);
+    // Mark to show messages if it's new installation of eslint.
+    const installStatus = npmUtil.checkDevDeps(["eslint"]);
 
-    // Install packages which aren't already installed
-    const modulesToInstall = Object.keys(installStatus).filter(module => {
-        const notInstalled = installStatus[module] === false;
+    if (installStatus.eslint === false) {
+        log.info("Local ESLint installation not found.");
+        config.installedESLint = true;
+    }
 
-        if (module === "eslint" && notInstalled) {
-            log.info("Local ESLint installation not found.");
-            config.installedESLint = true;
-        }
+    // Install packages
+    const modulesToInstall = Object.keys(modules).map(name => `${name}@${modules[name]}`);
 
-        return notInstalled;
-    });
+    log.info(`Installing ${modulesToInstall.join(", ")}`);
 
-    if (modulesToInstall.length > 0) {
-        log.info(`Installing ${modulesToInstall.join(", ")}`);
-        npmUtil.installSyncSaveDev(modulesToInstall);
-    }
+    npmUtil.installSyncSaveDev(modulesToInstall);
 }
 
 /**
@@ -265,9 +270,9 @@ function processAnswers(answers) {
 function getConfigForStyleGuide(guide) {
     const guides = {
         google: { extends: "google" },
-        airbnb: { extends: "airbnb", plugins: ["react", "jsx-a11y", "import"] },
-        "airbnb-base": { extends: "airbnb-base", plugins: ["import"] },
-        standard: { extends: "standard", plugins: ["standard", "promise"] }
+        airbnb: { extends: "airbnb" },
+        "airbnb-base": { extends: "airbnb-base" },
+        standard: { extends: "standard" }
     };
 
     if (!guides[guide]) {
diff --git a/lib/ignored-paths.js b/lib/ignored-paths.js
index 0d9152495..2923ee1a6 100644
--- a/lib/ignored-paths.js
+++ b/lib/ignored-paths.js
@@ -16,7 +16,6 @@ const fs = require("fs"),
 
 const debug = require("debug")("eslint:ignored-paths");
 
-
 //------------------------------------------------------------------------------
 // Constants
 //------------------------------------------------------------------------------
@@ -37,25 +36,42 @@ const DEFAULT_OPTIONS = {
     cwd: process.cwd()
 };
 
-
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
 
-
 /**
- * Find an ignore file in the current directory.
+ * Find a file in the current directory.
  * @param {string} cwd Current working directory
+ * @param {string} name File name
  * @returns {string} Path of ignore file or an empty string.
  */
-function findIgnoreFile(cwd) {
+function findFile(cwd, name) {
     cwd = cwd || DEFAULT_OPTIONS.cwd;
 
-    const ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME);
+    const ignoreFilePath = path.resolve(cwd, name);
 
     return fs.existsSync(ignoreFilePath) && fs.statSync(ignoreFilePath).isFile() ? ignoreFilePath : "";
 }
 
+/**
+ * Find an ignore file in the current directory.
+ * @param {string} cwd Current working directory
+ * @returns {string} Path of ignore file or an empty string.
+ */
+function findIgnoreFile(cwd) {
+    return findFile(cwd, ESLINT_IGNORE_FILENAME);
+}
+
+/**
+ * Find an package.json file in the current directory.
+ * @param {string} cwd Current working directory
+ * @returns {string} Path of package.json file or an empty string.
+ */
+function findPackageJSONFile(cwd) {
+    return findFile(cwd, "package.json");
+}
+
 /**
  * Merge options with defaults
  * @param {Object} options Options to merge with DEFAULT_OPTIONS constant
@@ -80,6 +96,7 @@ class IgnoredPaths {
      */
     constructor(options) {
         options = mergeDefaultOptions(options);
+        this.cache = {};
 
         /**
          * add pattern to node-ignore instance
@@ -91,17 +108,6 @@ class IgnoredPaths {
             return ig.addPattern(pattern);
         }
 
-        /**
-         * add ignore file to node-ignore instance
-         * @param {Object} ig, instance of node-ignore
-         * @param {string} filepath, file to add to ig
-         * @returns {array} raw ignore rules
-         */
-        function addIgnoreFile(ig, filepath) {
-            ig.ignoreFiles.push(filepath);
-            return ig.add(fs.readFileSync(filepath, "utf8"));
-        }
-
         this.defaultPatterns = [].concat(DEFAULT_IGNORE_DIRS, options.patterns || []);
         this.baseDir = options.cwd;
 
@@ -155,8 +161,39 @@ class IgnoredPaths {
             if (ignorePath) {
                 debug(`Adding ${ignorePath}`);
                 this.baseDir = path.dirname(path.resolve(options.cwd, ignorePath));
-                addIgnoreFile(this.ig.custom, ignorePath);
-                addIgnoreFile(this.ig.default, ignorePath);
+                this.addIgnoreFile(this.ig.custom, ignorePath);
+                this.addIgnoreFile(this.ig.default, ignorePath);
+            } else {
+                try {
+
+                    // if the ignoreFile does not exist, check package.json for eslintIgnore
+                    const packageJSONPath = findPackageJSONFile(options.cwd);
+
+                    if (packageJSONPath) {
+                        let packageJSONOptions;
+
+                        try {
+                            packageJSONOptions = JSON.parse(fs.readFileSync(packageJSONPath, "utf8"));
+                        } catch (e) {
+                            debug("Could not read package.json file to check eslintIgnore property");
+                            throw e;
+                        }
+
+                        if (packageJSONOptions.eslintIgnore) {
+                            if (Array.isArray(packageJSONOptions.eslintIgnore)) {
+                                packageJSONOptions.eslintIgnore.forEach(pattern => {
+                                    addPattern(this.ig.custom, pattern);
+                                    addPattern(this.ig.default, pattern);
+                                });
+                            } else {
+                                throw new Error("Package.json eslintIgnore property requires an array of paths");
+                            }
+                        }
+                    }
+                } catch (e) {
+                    debug("Could not find package.json to check eslintIgnore property");
+                    throw e;
+                }
             }
 
             if (options.ignorePattern) {
@@ -168,6 +205,29 @@ class IgnoredPaths {
         this.options = options;
     }
 
+    /**
+     * read ignore filepath
+     * @param {string} filePath, file to add to ig
+     * @returns {array} raw ignore rules
+     */
+    readIgnoreFile(filePath) {
+        if (typeof this.cache[filePath] === "undefined") {
+            this.cache[filePath] = fs.readFileSync(filePath, "utf8");
+        }
+        return this.cache[filePath];
+    }
+
+    /**
+     * add ignore file to node-ignore instance
+     * @param {Object} ig, instance of node-ignore
+     * @param {string} filePath, file to add to ig
+     * @returns {array} raw ignore rules
+     */
+    addIgnoreFile(ig, filePath) {
+        ig.ignoreFiles.push(filePath);
+        return ig.add(this.readIgnoreFile(filePath));
+    }
+
     /**
      * Determine whether a file path is included in the default or custom ignore patterns
      * @param {string} filepath Path to check
diff --git a/lib/linter.js b/lib/linter.js
index 25af05223..0b0d06a86 100755
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -27,9 +27,11 @@ const assert = require("assert"),
     Rules = require("./rules"),
     timing = require("./timing"),
     astUtils = require("./ast-utils"),
+    pkg = require("../package.json"),
+    SourceCodeFixer = require("./util/source-code-fixer");
 
-    pkg = require("../package.json");
-
+const debug = require("debug")("eslint:linter");
+const MAX_AUTOFIX_PASSES = 10;
 
 //------------------------------------------------------------------------------
 // Typedefs
@@ -1185,6 +1187,74 @@ class Linter extends EventEmitter {
     getDeclaredVariables(node) {
         return (this.scopeManager && this.scopeManager.getDeclaredVariables(node)) || [];
     }
+
+    /**
+     * Performs multiple autofix passes over the text until as many fixes as possible
+     * have been applied.
+     * @param {string} text The source text to apply fixes to.
+     * @param {Object} config The ESLint config object to use.
+     * @param {Object} options The ESLint options object to use.
+     * @param {string} options.filename The filename from which the text was read.
+     * @param {boolean} options.allowInlineConfig Flag indicating if inline comments
+     *      should be allowed.
+     * @returns {Object} The result of the fix operation as returned from the
+     *      SourceCodeFixer.
+     */
+    verifyAndFix(text, config, options) {
+        let messages = [],
+            fixedResult,
+            fixed = false,
+            passNumber = 0;
+
+        /**
+         * This loop continues until one of the following is true:
+         *
+         * 1. No more fixes have been applied.
+         * 2. Ten passes have been made.
+         *
+         * That means anytime a fix is successfully applied, there will be another pass.
+         * Essentially, guaranteeing a minimum of two passes.
+         */
+        do {
+            passNumber++;
+
+            debug(`Linting code for ${options.filename} (pass ${passNumber})`);
+            messages = this.verify(text, config, options);
+
+            debug(`Generating fixed text for ${options.filename} (pass ${passNumber})`);
+            fixedResult = SourceCodeFixer.applyFixes(this.getSourceCode(), messages);
+
+            // stop if there are any syntax errors.
+            // 'fixedResult.output' is a empty string.
+            if (messages.length === 1 && messages[0].fatal) {
+                break;
+            }
+
+            // keep track if any fixes were ever applied - important for return value
+            fixed = fixed || fixedResult.fixed;
+
+            // update to use the fixed output instead of the original text
+            text = fixedResult.output;
+
+        } while (
+            fixedResult.fixed &&
+            passNumber < MAX_AUTOFIX_PASSES
+        );
+
+        /*
+         * If the last result had fixes, we need to lint again to be sure we have
+         * the most up-to-date information.
+         */
+        if (fixedResult.fixed) {
+            fixedResult.messages = this.verify(text, config, options);
+        }
+
+        // ensure the last result properly reflects if fixes were done
+        fixedResult.fixed = fixed;
+        fixedResult.output = text;
+
+        return fixedResult;
+    }
 }
 
 // methods that exist on SourceCode object
diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js
index c292d1b49..60a043bb3 100644
--- a/lib/rules/arrow-parens.js
+++ b/lib/rules/arrow-parens.js
@@ -50,14 +50,31 @@ module.exports = {
 
         const sourceCode = context.getSourceCode();
 
-
         /**
          * Determines whether a arrow function argument end with `)`
          * @param {ASTNode} node The arrow function node.
          * @returns {void}
          */
         function parens(node) {
-            const token = sourceCode.getFirstToken(node, node.async ? 1 : 0);
+            const isAsync = node.async;
+            const firstTokenOfParam = sourceCode.getFirstToken(node, isAsync ? 1 : 0);
+
+            /**
+             * Remove the parenthesis around a parameter
+             * @param {Fixer} fixer Fixer
+             * @returns {string} fixed parameter
+             */
+            function fixParamsWithParenthesis(fixer) {
+                const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
+                const closingParenToken = sourceCode.getTokenAfter(paramToken);
+                const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
+                const shouldAddSpaceForAsync = asyncToken && (asyncToken.end === firstTokenOfParam.start);
+
+                return fixer.replaceTextRange([
+                    firstTokenOfParam.range[0],
+                    closingParenToken.range[1]
+                ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
+            }
 
             // "as-needed", { "requireForBlockBody": true }: x => x
             if (
@@ -68,19 +85,11 @@ module.exports = {
                 node.body.type !== "BlockStatement" &&
                 !node.returnType
             ) {
-                if (astUtils.isOpeningParenToken(token)) {
+                if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
                     context.report({
                         node,
                         message: requireForBlockBodyMessage,
-                        fix(fixer) {
-                            const paramToken = context.getTokenAfter(token);
-                            const closingParenToken = context.getTokenAfter(paramToken);
-
-                            return fixer.replaceTextRange([
-                                token.range[0],
-                                closingParenToken.range[1]
-                            ], paramToken.value);
-                        }
+                        fix: fixParamsWithParenthesis
                     });
                 }
                 return;
@@ -90,12 +99,12 @@ module.exports = {
                 requireForBlockBody &&
                 node.body.type === "BlockStatement"
             ) {
-                if (!astUtils.isOpeningParenToken(token)) {
+                if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
                     context.report({
                         node,
                         message: requireForBlockBodyNoParensMessage,
                         fix(fixer) {
-                            return fixer.replaceText(token, `(${token.value})`);
+                            return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
                         }
                     });
                 }
@@ -109,26 +118,18 @@ module.exports = {
                 !node.params[0].typeAnnotation &&
                 !node.returnType
             ) {
-                if (astUtils.isOpeningParenToken(token)) {
+                if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
                     context.report({
                         node,
                         message: asNeededMessage,
-                        fix(fixer) {
-                            const paramToken = context.getTokenAfter(token);
-                            const closingParenToken = context.getTokenAfter(paramToken);
-
-                            return fixer.replaceTextRange([
-                                token.range[0],
-                                closingParenToken.range[1]
-                            ], paramToken.value);
-                        }
+                        fix: fixParamsWithParenthesis
                     });
                 }
                 return;
             }
 
-            if (token.type === "Identifier") {
-                const after = sourceCode.getTokenAfter(token);
+            if (firstTokenOfParam.type === "Identifier") {
+                const after = sourceCode.getTokenAfter(firstTokenOfParam);
 
                 // (x) => x
                 if (after.value !== ")") {
@@ -136,7 +137,7 @@ module.exports = {
                         node,
                         message,
                         fix(fixer) {
-                            return fixer.replaceText(token, `(${token.value})`);
+                            return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
                         }
                     });
                 }
diff --git a/lib/rules/indent.js b/lib/rules/indent.js
index 82268975d..5a8feee8f 100644
--- a/lib/rules/indent.js
+++ b/lib/rules/indent.js
@@ -816,7 +816,6 @@ module.exports = {
 
             offsets.ignoreToken(operator);
             offsets.ignoreToken(tokensAfterOperator[0]);
-            offsets.setDesiredOffset(tokensAfterOperator[0], sourceCode.getFirstToken(node), 1);
             offsets.setDesiredOffsets(tokensAfterOperator, tokensAfterOperator[0], 1);
         }
 
@@ -882,6 +881,13 @@ module.exports = {
 
                 // We only want to handle parens around expressions, so exclude parentheses that are in function parameters and function call arguments.
                 if (!parameterParens.has(leftParen) && !parameterParens.has(rightParen)) {
+                    const parenthesizedTokens = new Set(sourceCode.getTokensBetween(leftParen, rightParen));
+
+                    parenthesizedTokens.forEach(token => {
+                        if (!parenthesizedTokens.has(offsets.getFirstDependency(token))) {
+                            offsets.setDesiredOffset(token, leftParen, 1);
+                        }
+                    });
                     offsets.setDesiredOffset(sourceCode.getTokenAfter(leftParen), leftParen, 1);
                 }
 
@@ -1114,28 +1120,29 @@ module.exports = {
                 const tokenBeforeObject = sourceCode.getTokenBefore(node.object, token => astUtils.isNotOpeningParenToken(token) || parameterParens.has(token));
                 const firstObjectToken = tokenBeforeObject ? sourceCode.getTokenAfter(tokenBeforeObject) : sourceCode.ast.tokens[0];
                 const lastObjectToken = sourceCode.getTokenBefore(firstNonObjectToken);
+                const firstPropertyToken = node.computed ? firstNonObjectToken : secondNonObjectToken;
 
                 if (node.computed) {
 
                     // For computed MemberExpressions, match the closing bracket with the opening bracket.
                     offsets.matchIndentOf(firstNonObjectToken, sourceCode.getLastToken(node));
+                    offsets.setDesiredOffsets(getTokensAndComments(node.property), firstNonObjectToken, 1);
                 }
 
-                if (typeof options.MemberExpression === "number") {
-                    const firstPropertyToken = node.computed ? firstNonObjectToken : secondNonObjectToken;
+                /*
+                 * If the object ends on the same line that the property starts, match against the last token
+                 * of the object, to ensure that the MemberExpression is not indented.
+                 *
+                 * Otherwise, match against the first token of the object, e.g.
+                 * foo
+                 *   .bar
+                 *   .baz // <-- offset by 1 from `foo`
+                 */
+                const offsetBase = lastObjectToken.loc.end.line === firstPropertyToken.loc.start.line
+                    ? lastObjectToken
+                    : firstObjectToken;
 
-                    /*
-                     * If the object ends on the same line that the property starts, match against the last token
-                     * of the object, to ensure that the MemberExpression is not indented.
-                     *
-                     * Otherwise, match against the first token of the object, e.g.
-                     * foo
-                     *   .bar
-                     *   .baz // <-- offset by 1 from `foo`
-                     */
-                    const offsetBase = lastObjectToken.loc.end.line === firstPropertyToken.loc.start.line
-                        ? lastObjectToken
-                        : firstObjectToken;
+                if (typeof options.MemberExpression === "number") {
 
                     // Match the dot (for non-computed properties) or the opening bracket (for computed properties) against the object.
                     offsets.setDesiredOffset(firstNonObjectToken, offsetBase, options.MemberExpression);
@@ -1150,6 +1157,9 @@ module.exports = {
                     // If the MemberExpression option is off, ignore the dot and the first token of the property.
                     offsets.ignoreToken(firstNonObjectToken);
                     offsets.ignoreToken(secondNonObjectToken);
+
+                    // To ignore the property indentation, ensure that the property tokens depend on the ignored tokens.
+                    offsets.matchIndentOf(offsetBase, firstNonObjectToken);
                     offsets.matchIndentOf(firstNonObjectToken, secondNonObjectToken);
                 }
             },
diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js
index 409fb451f..03f45a6c6 100644
--- a/lib/rules/key-spacing.js
+++ b/lib/rules/key-spacing.js
@@ -634,6 +634,5 @@ module.exports = {
         };
 
 
-
     }
 };
diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js
index 0a6a0d0f1..d0d79c6a3 100644
--- a/lib/rules/no-extra-parens.js
+++ b/lib/rules/no-extra-parens.js
@@ -255,6 +255,23 @@ module.exports = {
                 !astUtils.canTokensBeAdjacent(tokenBeforeLeftParen, firstToken);
         }
 
+        /**
+         * Determines whether a node should be followed by an additional space when removing parens
+         * @param {ASTNode} node node to evaluate; must be surrounded by parentheses
+         * @returns {boolean} `true` if a space should be inserted after the node
+         * @private
+         */
+        function requiresTrailingSpace(node) {
+            const nextTwoTokens = sourceCode.getTokensAfter(node, { count: 2 });
+            const rightParenToken = nextTwoTokens[0];
+            const tokenAfterRightParen = nextTwoTokens[1];
+            const tokenBeforeRightParen = sourceCode.getLastToken(node);
+
+            return rightParenToken && tokenAfterRightParen &&
+                !sourceCode.isSpaceBetweenTokens(rightParenToken, tokenAfterRightParen) &&
+                !astUtils.canTokensBeAdjacent(tokenBeforeRightParen, tokenAfterRightParen);
+        }
+
         /**
          * Report the node
          * @param {ASTNode} node node to evaluate
@@ -279,7 +296,7 @@ module.exports = {
                     return fixer.replaceTextRange([
                         leftParenToken.range[0],
                         rightParenToken.range[1]
-                    ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource);
+                    ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource + (requiresTrailingSpace(node) ? " " : ""));
                 }
             });
         }
@@ -488,12 +505,18 @@ module.exports = {
                 if (hasExcessParens(node.right)) {
                     report(node.right);
                 }
+                if (hasExcessParens(node.left)) {
+                    report(node.left);
+                }
             },
 
             ForOfStatement(node) {
                 if (hasExcessParens(node.right)) {
                     report(node.right);
                 }
+                if (hasExcessParens(node.left)) {
+                    report(node.left);
+                }
             },
 
             ForStatement(node) {
diff --git a/lib/rules/semi-style.js b/lib/rules/semi-style.js
index fa258754d..97fcc3ac8 100644
--- a/lib/rules/semi-style.js
+++ b/lib/rules/semi-style.js
@@ -79,7 +79,7 @@ module.exports = {
                             : "the beginning of the next line"
                     },
                     fix(fixer) {
-                        if (commentsExistBetween(prevToken, nextToken)) {
+                        if (prevToken && nextToken && commentsExistBetween(prevToken, nextToken)) {
                             return null;
                         }
 
diff --git a/lib/rules/space-infix-ops.js b/lib/rules/space-infix-ops.js
index d919a1225..ad514b28f 100644
--- a/lib/rules/space-infix-ops.js
+++ b/lib/rules/space-infix-ops.js
@@ -106,11 +106,10 @@ module.exports = {
          * @private
          */
         function checkBinary(node) {
-            if (node.left.typeAnnotation) {
-                return;
-            }
+            const leftNode = (node.left.typeAnnotation) ? node.left.typeAnnotation : node.left;
+            const rightNode = node.right;
 
-            const nonSpacedNode = getFirstNonSpacedToken(node.left, node.right);
+            const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
 
             if (nonSpacedNode) {
                 if (!(int32Hint && sourceCode.getText(node).substr(-2) === "|0")) {
@@ -143,8 +142,11 @@ module.exports = {
          * @private
          */
         function checkVar(node) {
-            if (node.init) {
-                const nonSpacedNode = getFirstNonSpacedToken(node.id, node.init);
+            const leftNode = (node.id.typeAnnotation) ? node.id.typeAnnotation : node.id;
+            const rightNode = node.init;
+
+            if (rightNode) {
+                const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
 
                 if (nonSpacedNode) {
                     report(node, nonSpacedNode);
diff --git a/lib/util/npm-util.js b/lib/util/npm-util.js
index 4859fabc9..057dbfea4 100644
--- a/lib/util/npm-util.js
+++ b/lib/util/npm-util.js
@@ -56,6 +56,20 @@ function installSyncSaveDev(packages) {
     childProcess.execSync(`npm i --save-dev ${packages}`, { stdio: "inherit", encoding: "utf8" });
 }
 
+/**
+ * Fetch `peerDependencies` of the given package by `npm show` command.
+ * @param {string} packageName The package name to fetch peerDependencies.
+ * @returns {string[]} Gotten peerDependencies.
+ */
+function fetchPeerDependencies(packageName) {
+    const fetchedText = childProcess.execSync(
+        `npm show --json ${packageName} peerDependencies`,
+        { encoding: "utf8" }
+    ).trim();
+
+    return JSON.parse(fetchedText || "{}");
+}
+
 /**
  * Check whether node modules are include in a project's package.json.
  *
@@ -140,6 +154,7 @@ function checkPackageJson(startDir) {
 
 module.exports = {
     installSyncSaveDev,
+    fetchPeerDependencies,
     checkDeps,
     checkDevDeps,
     checkPackageJson
diff --git a/lib/util/patterns/letters.js b/lib/util/patterns/letters.js
index b212cfc9e..eb255d8f0 100644
--- a/lib/util/patterns/letters.js
+++ b/lib/util/patterns/letters.js
@@ -34,4 +34,3 @@
 "use strict";
 
 module.exports = /[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/;
-
diff --git a/package.json b/package.json
index 9bd70eab4..26dbdd8c8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "4.0.0-rc.0",
+  "version": "4.0.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -37,22 +37,22 @@
     "babel-code-frame": "^6.22.0",
     "chalk": "^1.1.3",
     "concat-stream": "^1.6.0",
-    "debug": "^2.6.3",
+    "debug": "^2.6.8",
     "doctrine": "^2.0.0",
-    "eslint-scope": "^3.6.0",
-    "espree": "^3.4.2",
+    "eslint-scope": "^3.7.1",
+    "espree": "^3.4.3",
     "esquery": "^1.0.0",
     "estraverse": "^4.2.0",
     "esutils": "^2.0.2",
     "file-entry-cache": "^2.0.0",
-    "glob": "^7.1.1",
-    "globals": "^9.16.0",
-    "ignore": "^3.2.6",
+    "glob": "^7.1.2",
+    "globals": "^9.17.0",
+    "ignore": "^3.3.3",
     "imurmurhash": "^0.1.4",
     "inquirer": "^3.0.6",
     "is-my-json-valid": "^2.16.0",
     "is-resolvable": "^1.0.0",
-    "js-yaml": "^3.8.2",
+    "js-yaml": "^3.8.4",
     "json-stable-stringify": "^1.0.1",
     "levn": "^0.3.0",
     "lodash": "^4.17.4",
@@ -61,7 +61,7 @@
     "optionator": "^0.8.2",
     "path-is-inside": "^1.0.2",
     "pluralize": "^4.0.0",
-    "progress": "^1.1.8",
+    "progress": "^2.0.0",
     "require-uncached": "^1.0.3",
     "strip-json-comments": "~2.0.1",
     "table": "^4.0.1",
@@ -69,40 +69,40 @@
   },
   "devDependencies": {
     "babel-polyfill": "^6.23.0",
-    "babel-preset-es2015": "^6.24.0",
+    "babel-preset-es2015": "^6.24.1",
     "babelify": "^7.3.0",
     "beefy": "^2.1.8",
     "brfs": "1.4.3",
-    "browserify": "^14.1.0",
-    "chai": "^3.5.0",
+    "browserify": "^14.4.0",
+    "chai": "^4.0.1",
     "cheerio": "^0.22.0",
-    "coveralls": "^2.12.0",
+    "coveralls": "^2.13.1",
     "dateformat": "^2.0.0",
     "ejs": "^2.5.6",
-    "eslint-plugin-eslint-plugin": "^0.7.1",
-    "eslint-plugin-node": "^4.2.1",
+    "eslint-plugin-eslint-plugin": "^0.7.2",
+    "eslint-plugin-node": "^5.0.0",
     "eslint-release": "^0.10.1",
     "esprima": "^3.1.3",
     "esprima-fb": "^15001.1001.0-dev-harmony-fb",
     "istanbul": "^0.4.5",
     "jsdoc": "^3.4.3",
-    "karma": "^1.5.0",
+    "karma": "^1.7.0",
     "karma-babel-preprocessor": "^6.0.1",
     "karma-mocha": "^1.3.0",
-    "karma-mocha-reporter": "^2.2.2",
+    "karma-mocha-reporter": "^2.2.3",
     "karma-phantomjs-launcher": "^1.0.4",
     "leche": "^2.1.2",
     "load-perf": "^0.2.0",
-    "markdownlint": "^0.4.0",
-    "mocha": "^3.2.0",
-    "mock-fs": "^4.2.0",
+    "markdownlint": "^0.5.0",
+    "mocha": "^3.4.2",
+    "mock-fs": "^4.3.0",
     "npm-license": "^0.3.3",
     "phantomjs-prebuilt": "^2.1.14",
-    "proxyquire": "^1.7.11",
+    "proxyquire": "^1.8.0",
     "semver": "^5.3.0",
     "shelljs": "^0.7.7",
     "shelljs-nodecli": "~0.1.1",
-    "sinon": "^2.0.0",
+    "sinon": "^2.3.2",
     "temp": "^0.8.3",
     "through": "^2.3.8"
   },
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index 815a82bdd..9180f7525 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -36,7 +36,6 @@ rules:
     }]
     max-statements-per-line: "error"
     new-cap: "error"
-    newline-after-var: "error"
     new-parens: "error"
     no-alert: "error"
     no-array-constructor: "error"
@@ -61,7 +60,7 @@ rules:
     no-mixed-spaces-and-tabs: ["error", false]
     no-multi-spaces: "error"
     no-multi-str: "error"
-    no-native-reassign: "off"
+    no-multiple-empty-lines: ["error", {max: 2, maxBOF: 0, maxEOF: 0}]
     no-nested-ternary: "error"
     no-new: "error"
     no-new-func: "error"
@@ -100,6 +99,19 @@ rules:
     object-shorthand: "error"
     one-var-declaration-per-line: "error"
     operator-linebreak: "error"
+    padding-line-between-statements: [
+        "error",
+        {
+            blankLine: "always",
+            prev: ["const", "let", "var"],
+            next: "*"
+        },
+        {
+            blankLine: "any",
+            prev: ["const", "let", "var"],
+            next: ["const", "let", "var"]
+        }
+    ]
     prefer-arrow-callback: "error"
     prefer-const: "error"
     prefer-promise-reject-errors: "error"


Test patch:
diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js
index a0df6e05b..d66cd175a 100644
--- a/lib/testers/rule-tester.js
+++ b/lib/testers/rule-tester.js
@@ -456,7 +456,6 @@ class RuleTester {
             const messages = result.messages;
 
 
-
             if (typeof item.errors === "number") {
                 assert.equal(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
                     item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
diff --git a/tests/fixtures/ignored-paths/bad-package-json-ignore/package.json b/tests/fixtures/ignored-paths/bad-package-json-ignore/package.json
new file mode 100644
index 000000000..37174a849
--- /dev/null
+++ b/tests/fixtures/ignored-paths/bad-package-json-ignore/package.json
@@ -0,0 +1,11 @@
+{
+    "name": "mypackage",
+    "version": "0.0.1",
+    "eslintConfig": {
+        "env": {
+            "browser": true,
+            "node": true
+        }
+    },
+    "eslintIgnore": "hello.js"
+}
diff --git a/tests/fixtures/ignored-paths/package-json-ignore/package.json b/tests/fixtures/ignored-paths/package-json-ignore/package.json
new file mode 100644
index 000000000..05436bdb5
--- /dev/null
+++ b/tests/fixtures/ignored-paths/package-json-ignore/package.json
@@ -0,0 +1,11 @@
+{
+    "name": "mypackage",
+    "version": "0.0.1",
+    "eslintConfig": {
+        "env": {
+            "browser": true,
+            "node": true
+        }
+    },
+    "eslintIgnore": ["hello.js", "world.js"]
+}
diff --git a/tests/fixtures/ignored-paths/package.json b/tests/fixtures/ignored-paths/package.json
new file mode 100644
index 000000000..05436bdb5
--- /dev/null
+++ b/tests/fixtures/ignored-paths/package.json
@@ -0,0 +1,11 @@
+{
+    "name": "mypackage",
+    "version": "0.0.1",
+    "eslintConfig": {
+        "env": {
+            "browser": true,
+            "node": true
+        }
+    },
+    "eslintIgnore": ["hello.js", "world.js"]
+}
diff --git a/tests/fixtures/parsers/type-annotations/function-declaration-type-annotation-no-space.js b/tests/fixtures/parsers/type-annotations/function-declaration-type-annotation-no-space.js
new file mode 100644
index 000000000..452ce84a9
--- /dev/null
+++ b/tests/fixtures/parsers/type-annotations/function-declaration-type-annotation-no-space.js
@@ -0,0 +1,486 @@
+/**
+ * Source code:
+ * function foo(a: number=0): Foo { }
+ */
+
+exports.parse = () => ({
+    "type": "Program",
+    "range": [
+        0,
+        34
+    ],
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 1,
+            "column": 34
+        }
+    },
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "range": [
+                0,
+                34
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 34
+                }
+            },
+            "id": {
+                "type": "Identifier",
+                "range": [
+                    9,
+                    12
+                ],
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    }
+                },
+                "name": "foo"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [
+                {
+                    "type": "AssignmentPattern",
+                    "range": [
+                        13,
+                        24
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 13
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 24
+                        }
+                    },
+                    "left": {
+                        "type": "Identifier",
+                        "range": [
+                            13,
+                            14
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 13
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 14
+                            }
+                        },
+                        "name": "a",
+                        "typeAnnotation": {
+                            "type": "TypeAnnotation",
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 16
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 22
+                                }
+                            },
+                            "range": [
+                                16,
+                                22
+                            ],
+                            "typeAnnotation": {
+                                "type": "NumberKeyword",
+                                "range": [
+                                    16,
+                                    22
+                                ],
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 16
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 22
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "right": {
+                        "type": "Literal",
+                        "range": [
+                            23,
+                            24
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 23
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 24
+                            }
+                        },
+                        "value": 0,
+                        "raw": "0"
+                    }
+                }
+            ],
+            "body": {
+                "type": "BlockStatement",
+                "range": [
+                    31,
+                    34
+                ],
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 31
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 34
+                    }
+                },
+                "body": []
+            },
+            "returnType": {
+                "type": "TypeAnnotation",
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 27
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 30
+                    }
+                },
+                "range": [
+                    27,
+                    30
+                ],
+                "typeAnnotation": {
+                    "type": "TypeReference",
+                    "range": [
+                        27,
+                        30
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 27
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 30
+                        }
+                    },
+                    "typeName": {
+                        "type": "Identifier",
+                        "range": [
+                            27,
+                            30
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 27
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 30
+                            }
+                        },
+                        "name": "Foo"
+                    }
+                }
+            }
+        }
+    ],
+    "sourceType": "script",
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "range": [
+                0,
+                8
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "range": [
+                9,
+                12
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "range": [
+                12,
+                13
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 13,
+            "end": 14,
+            "range": [
+                13,
+                14
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 14,
+            "end": 15,
+            "range": [
+                14,
+                15
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 14
+                },
+                "end": {
+                    "line": 1,
+                    "column": 15
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "number",
+            "start": 16,
+            "end": 22,
+            "range": [
+                16,
+                22
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 16
+                },
+                "end": {
+                    "line": 1,
+                    "column": 22
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "=",
+            "start": 22,
+            "end": 23,
+            "range": [
+                22,
+                23
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 22
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            }
+        },
+        {
+            "type": "Numeric",
+            "value": "0",
+            "start": 23,
+            "end": 24,
+            "range": [
+                23,
+                24
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 23
+                },
+                "end": {
+                    "line": 1,
+                    "column": 24
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 24,
+            "end": 25,
+            "range": [
+                24,
+                25
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 24
+                },
+                "end": {
+                    "line": 1,
+                    "column": 25
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 25,
+            "end": 26,
+            "range": [
+                25,
+                26
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 25
+                },
+                "end": {
+                    "line": 1,
+                    "column": 26
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "Foo",
+            "start": 27,
+            "end": 30,
+            "range": [
+                27,
+                30
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 27
+                },
+                "end": {
+                    "line": 1,
+                    "column": 30
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 31,
+            "end": 32,
+            "range": [
+                31,
+                32
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 31
+                },
+                "end": {
+                    "line": 1,
+                    "column": 32
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 33,
+            "end": 34,
+            "range": [
+                33,
+                34
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 33
+                },
+                "end": {
+                    "line": 1,
+                    "column": 34
+                }
+            }
+        }
+    ],
+    "comments": []
+});
diff --git a/tests/fixtures/parsers/type-annotations/function-expression-type-annotation.js b/tests/fixtures/parsers/type-annotations/function-expression-type-annotation.js
new file mode 100644
index 000000000..8f4f94c32
--- /dev/null
+++ b/tests/fixtures/parsers/type-annotations/function-expression-type-annotation.js
@@ -0,0 +1,585 @@
+/**
+ * Source code:
+ * const foo = function(a: number = 0): Bar { };
+ */
+
+exports.parse = () => ({
+    "type": "Program",
+    "range": [
+        0,
+        45
+    ],
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 1,
+            "column": 45
+        }
+    },
+    "body": [
+        {
+            "type": "VariableDeclaration",
+            "range": [
+                0,
+                45
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 45
+                }
+            },
+            "declarations": [
+                {
+                    "type": "VariableDeclarator",
+                    "range": [
+                        6,
+                        44
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 6
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 44
+                        }
+                    },
+                    "id": {
+                        "type": "Identifier",
+                        "range": [
+                            6,
+                            9
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 6
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 9
+                            }
+                        },
+                        "name": "foo"
+                    },
+                    "init": {
+                        "type": "FunctionExpression",
+                        "range": [
+                            12,
+                            44
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 12
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 44
+                            }
+                        },
+                        "id": null,
+                        "generator": false,
+                        "params": [
+                            {
+                                "type": "AssignmentPattern",
+                                "range": [
+                                    21,
+                                    34
+                                ],
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 21
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 34
+                                    }
+                                },
+                                "left": {
+                                    "type": "Identifier",
+                                    "range": [
+                                        21,
+                                        22
+                                    ],
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 21
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 22
+                                        }
+                                    },
+                                    "name": "a",
+                                    "typeAnnotation": {
+                                        "type": "TypeAnnotation",
+                                        "loc": {
+                                            "start": {
+                                                "line": 1,
+                                                "column": 24
+                                            },
+                                            "end": {
+                                                "line": 1,
+                                                "column": 30
+                                            }
+                                        },
+                                        "range": [
+                                            24,
+                                            30
+                                        ],
+                                        "typeAnnotation": {
+                                            "type": "NumberKeyword",
+                                            "range": [
+                                                24,
+                                                30
+                                            ],
+                                            "loc": {
+                                                "start": {
+                                                    "line": 1,
+                                                    "column": 24
+                                                },
+                                                "end": {
+                                                    "line": 1,
+                                                    "column": 30
+                                                }
+                                            }
+                                        }
+                                    }
+                                },
+                                "right": {
+                                    "type": "Literal",
+                                    "range": [
+                                        33,
+                                        34
+                                    ],
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 33
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 34
+                                        }
+                                    },
+                                    "value": 0,
+                                    "raw": "0"
+                                }
+                            }
+                        ],
+                        "body": {
+                            "type": "BlockStatement",
+                            "range": [
+                                41,
+                                44
+                            ],
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 41
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 44
+                                }
+                            },
+                            "body": []
+                        },
+                        "async": false,
+                        "expression": false,
+                        "returnType": {
+                            "type": "TypeAnnotation",
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 37
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 40
+                                }
+                            },
+                            "range": [
+                                37,
+                                40
+                            ],
+                            "typeAnnotation": {
+                                "type": "TypeReference",
+                                "range": [
+                                    37,
+                                    40
+                                ],
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 37
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 40
+                                    }
+                                },
+                                "typeName": {
+                                    "type": "Identifier",
+                                    "range": [
+                                        37,
+                                        40
+                                    ],
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 37
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 40
+                                        }
+                                    },
+                                    "name": "Bar"
+                                }
+                            }
+                        }
+                    }
+                }
+            ],
+            "kind": "const"
+        }
+    ],
+    "sourceType": "script",
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "const",
+            "start": 0,
+            "end": 5,
+            "range": [
+                0,
+                5
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 5
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 6,
+            "end": 9,
+            "range": [
+                6,
+                9
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 6
+                },
+                "end": {
+                    "line": 1,
+                    "column": 9
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "=",
+            "start": 10,
+            "end": 11,
+            "range": [
+                10,
+                11
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 10
+                },
+                "end": {
+                    "line": 1,
+                    "column": 11
+                }
+            }
+        },
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 12,
+            "end": 20,
+            "range": [
+                12,
+                20
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 20
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 20,
+            "end": 21,
+            "range": [
+                20,
+                21
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 20
+                },
+                "end": {
+                    "line": 1,
+                    "column": 21
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 21,
+            "end": 22,
+            "range": [
+                21,
+                22
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 21
+                },
+                "end": {
+                    "line": 1,
+                    "column": 22
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 22,
+            "end": 23,
+            "range": [
+                22,
+                23
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 22
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "number",
+            "start": 24,
+            "end": 30,
+            "range": [
+                24,
+                30
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 24
+                },
+                "end": {
+                    "line": 1,
+                    "column": 30
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "=",
+            "start": 31,
+            "end": 32,
+            "range": [
+                31,
+                32
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 31
+                },
+                "end": {
+                    "line": 1,
+                    "column": 32
+                }
+            }
+        },
+        {
+            "type": "Numeric",
+            "value": "0",
+            "start": 33,
+            "end": 34,
+            "range": [
+                33,
+                34
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 33
+                },
+                "end": {
+                    "line": 1,
+                    "column": 34
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 34,
+            "end": 35,
+            "range": [
+                34,
+                35
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 34
+                },
+                "end": {
+                    "line": 1,
+                    "column": 35
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 35,
+            "end": 36,
+            "range": [
+                35,
+                36
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 35
+                },
+                "end": {
+                    "line": 1,
+                    "column": 36
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "Bar",
+            "start": 37,
+            "end": 40,
+            "range": [
+                37,
+                40
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 37
+                },
+                "end": {
+                    "line": 1,
+                    "column": 40
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 41,
+            "end": 42,
+            "range": [
+                41,
+                42
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 41
+                },
+                "end": {
+                    "line": 1,
+                    "column": 42
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 43,
+            "end": 44,
+            "range": [
+                43,
+                44
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 43
+                },
+                "end": {
+                    "line": 1,
+                    "column": 44
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ";",
+            "start": 44,
+            "end": 45,
+            "range": [
+                44,
+                45
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 44
+                },
+                "end": {
+                    "line": 1,
+                    "column": 45
+                }
+            }
+        }
+    ],
+    "comments": []
+});
+
diff --git a/tests/fixtures/parsers/flow-stub-parser.js b/tests/fixtures/parsers/type-annotations/function-parameter-type-annotation.js
similarity index 98%
rename from tests/fixtures/parsers/flow-stub-parser.js
rename to tests/fixtures/parsers/type-annotations/function-parameter-type-annotation.js
index 70178cccd..341df31d8 100644
--- a/tests/fixtures/parsers/flow-stub-parser.js
+++ b/tests/fixtures/parsers/type-annotations/function-parameter-type-annotation.js
@@ -1,6 +1,9 @@
+/**
+ * Source code:
+ * function foo(a: number = 0) { }
+ */
 
-exports.parse = function() {
-    return {
+exports.parse = () => ({
       "type": "Program",
       "loc": {
         "source": null,
@@ -387,5 +390,4 @@ exports.parse = function() {
           ]
         }
       ]
-    };
-};
+});
diff --git a/tests/fixtures/parsers/type-annotations/function-return-type-annotation.js b/tests/fixtures/parsers/type-annotations/function-return-type-annotation.js
new file mode 100644
index 000000000..73900d058
--- /dev/null
+++ b/tests/fixtures/parsers/type-annotations/function-return-type-annotation.js
@@ -0,0 +1,297 @@
+/**
+ * Source code:
+ * function foo(): Bar { }
+ */
+
+exports.parse = () => ({
+    "type": "Program",
+    "range": [
+        0,
+        23
+    ],
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 1,
+            "column": 23
+        }
+    },
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "range": [
+                0,
+                23
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            },
+            "id": {
+                "type": "Identifier",
+                "range": [
+                    9,
+                    12
+                ],
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    }
+                },
+                "name": "foo"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [],
+            "body": {
+                "type": "BlockStatement",
+                "range": [
+                    20,
+                    23
+                ],
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 20
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 23
+                    }
+                },
+                "body": []
+            },
+            "returnType": {
+                "type": "TypeAnnotation",
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 16
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 19
+                    }
+                },
+                "range": [
+                    16,
+                    19
+                ],
+                "typeAnnotation": {
+                    "type": "TypeReference",
+                    "range": [
+                        16,
+                        19
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 16
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 19
+                        }
+                    },
+                    "typeName": {
+                        "type": "Identifier",
+                        "range": [
+                            16,
+                            19
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 16
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 19
+                            }
+                        },
+                        "name": "Bar"
+                    }
+                }
+            }
+        }
+    ],
+    "sourceType": "script",
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "range": [
+                0,
+                8
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "range": [
+                9,
+                12
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "range": [
+                12,
+                13
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 13,
+            "end": 14,
+            "range": [
+                13,
+                14
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 14,
+            "end": 15,
+            "range": [
+                14,
+                15
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 14
+                },
+                "end": {
+                    "line": 1,
+                    "column": 15
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "Bar",
+            "start": 16,
+            "end": 19,
+            "range": [
+                16,
+                19
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 16
+                },
+                "end": {
+                    "line": 1,
+                    "column": 19
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 20,
+            "end": 21,
+            "range": [
+                20,
+                21
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 20
+                },
+                "end": {
+                    "line": 1,
+                    "column": 21
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 22,
+            "end": 23,
+            "range": [
+                22,
+                23
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 22
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            }
+        }
+    ],
+    "comments": []
+});
diff --git a/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation-no-space.js b/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation-no-space.js
new file mode 100644
index 000000000..d551f4e95
--- /dev/null
+++ b/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation-no-space.js
@@ -0,0 +1,293 @@
+/**
+ * Source code:
+ * var a: Foo= b;
+ */
+
+exports.parse = () => ({
+    "type": "Program",
+    "range": [
+        0,
+        14
+    ],
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 1,
+            "column": 14
+        }
+    },
+    "body": [
+        {
+            "type": "VariableDeclaration",
+            "range": [
+                0,
+                14
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            },
+            "declarations": [
+                {
+                    "type": "VariableDeclarator",
+                    "range": [
+                        4,
+                        13
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 4
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 13
+                        }
+                    },
+                    "id": {
+                        "type": "Identifier",
+                        "range": [
+                            4,
+                            5
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 4
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 5
+                            }
+                        },
+                        "name": "a",
+                        "typeAnnotation": {
+                            "type": "TypeAnnotation",
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 7
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 10
+                                }
+                            },
+                            "range": [
+                                7,
+                                10
+                            ],
+                            "typeAnnotation": {
+                                "type": "TypeReference",
+                                "range": [
+                                    7,
+                                    10
+                                ],
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 7
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 10
+                                    }
+                                },
+                                "typeName": {
+                                    "type": "Identifier",
+                                    "range": [
+                                        7,
+                                        10
+                                    ],
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 7
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 10
+                                        }
+                                    },
+                                    "name": "Foo"
+                                }
+                            }
+                        }
+                    },
+                    "init": {
+                        "type": "Identifier",
+                        "range": [
+                            12,
+                            13
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 12
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 13
+                            }
+                        },
+                        "name": "b"
+                    }
+                }
+            ],
+            "kind": "var"
+        }
+    ],
+    "sourceType": "script",
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "var",
+            "start": 0,
+            "end": 3,
+            "range": [
+                0,
+                3
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 3
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 4,
+            "end": 5,
+            "range": [
+                4,
+                5
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 4
+                },
+                "end": {
+                    "line": 1,
+                    "column": 5
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 5,
+            "end": 6,
+            "range": [
+                5,
+                6
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 5
+                },
+                "end": {
+                    "line": 1,
+                    "column": 6
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "Foo",
+            "start": 7,
+            "end": 10,
+            "range": [
+                7,
+                10
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 7
+                },
+                "end": {
+                    "line": 1,
+                    "column": 10
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "=",
+            "start": 10,
+            "end": 11,
+            "range": [
+                10,
+                11
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 10
+                },
+                "end": {
+                    "line": 1,
+                    "column": 11
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 12,
+            "end": 13,
+            "range": [
+                12,
+                13
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ";",
+            "start": 13,
+            "end": 14,
+            "range": [
+                13,
+                14
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            }
+        }
+    ],
+    "comments": []
+});
diff --git a/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation.js b/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation.js
new file mode 100644
index 000000000..abe1be762
--- /dev/null
+++ b/tests/fixtures/parsers/type-annotations/variable-declaration-init-type-annotation.js
@@ -0,0 +1,294 @@
+/**
+ * Source code:
+ * var foo: Bar = '';
+ */
+
+exports.parse = () => ({
+    "type": "Program",
+    "range": [
+        0,
+        18
+    ],
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 1,
+            "column": 18
+        }
+    },
+    "body": [
+        {
+            "type": "VariableDeclaration",
+            "range": [
+                0,
+                18
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 18
+                }
+            },
+            "declarations": [
+                {
+                    "type": "VariableDeclarator",
+                    "range": [
+                        4,
+                        17
+                    ],
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 4
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 17
+                        }
+                    },
+                    "id": {
+                        "type": "Identifier",
+                        "range": [
+                            4,
+                            7
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 4
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 7
+                            }
+                        },
+                        "name": "foo",
+                        "typeAnnotation": {
+                            "type": "TypeAnnotation",
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 9
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 12
+                                }
+                            },
+                            "range": [
+                                9,
+                                12
+                            ],
+                            "typeAnnotation": {
+                                "type": "TypeReference",
+                                "range": [
+                                    9,
+                                    12
+                                ],
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 9
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 12
+                                    }
+                                },
+                                "typeName": {
+                                    "type": "Identifier",
+                                    "range": [
+                                        9,
+                                        12
+                                    ],
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 9
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 12
+                                        }
+                                    },
+                                    "name": "Bar"
+                                }
+                            }
+                        }
+                    },
+                    "init": {
+                        "type": "Literal",
+                        "range": [
+                            15,
+                            17
+                        ],
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 15
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 17
+                            }
+                        },
+                        "value": "",
+                        "raw": "''"
+                    }
+                }
+            ],
+            "kind": "var"
+        }
+    ],
+    "sourceType": "script",
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "var",
+            "start": 0,
+            "end": 3,
+            "range": [
+                0,
+                3
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 3
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 4,
+            "end": 7,
+            "range": [
+                4,
+                7
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 4
+                },
+                "end": {
+                    "line": 1,
+                    "column": 7
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 7,
+            "end": 8,
+            "range": [
+                7,
+                8
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 7
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            }
+        },
+        {
+            "type": "Identifier",
+            "value": "Bar",
+            "start": 9,
+            "end": 12,
+            "range": [
+                9,
+                12
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": "=",
+            "start": 13,
+            "end": 14,
+            "range": [
+                13,
+                14
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            }
+        },
+        {
+            "type": "String",
+            "value": "''",
+            "start": 15,
+            "end": 17,
+            "range": [
+                15,
+                17
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 15
+                },
+                "end": {
+                    "line": 1,
+                    "column": 17
+                }
+            }
+        },
+        {
+            "type": "Punctuator",
+            "value": ";",
+            "start": 17,
+            "end": 18,
+            "range": [
+                17,
+                18
+            ],
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 17
+                },
+                "end": {
+                    "line": 1,
+                    "column": 18
+                }
+            }
+        }
+    ],
+    "comments": []
+});
diff --git a/tests/lib/config.js b/tests/lib/config.js
index a2acd0380..1942a1c08 100644
--- a/tests/lib/config.js
+++ b/tests/lib/config.js
@@ -725,7 +725,6 @@ describe("Config", () => {
         });
 
 
-
         it("should load user config globals", () => {
             const configPath = path.resolve(__dirname, "..", "fixtures", "globals", "conf.yaml"),
                 configHelper = new Config({ configFile: configPath, useEslintrc: false }, linter);
diff --git a/tests/lib/config/config-initializer.js b/tests/lib/config/config-initializer.js
index d313dca5f..1a7d0a906 100644
--- a/tests/lib/config/config-initializer.js
+++ b/tests/lib/config/config-initializer.js
@@ -32,6 +32,7 @@ describe("configInitializer", () => {
     let fixtureDir,
         npmCheckStub,
         npmInstallStub,
+        npmFetchPeerDependenciesStub,
         init;
 
     const log = {
@@ -75,6 +76,14 @@ describe("configInitializer", () => {
             status[pkg] = false;
             return status;
         }, {}));
+        npmFetchPeerDependenciesStub = sinon
+            .stub(npmUtil, "fetchPeerDependencies")
+            .returns({
+                eslint: "^3.19.0",
+                "eslint-plugin-jsx-a11y": "^5.0.1",
+                "eslint-plugin-import": "^2.2.0",
+                "eslint-plugin-react": "^7.0.1"
+            });
         init = proxyquire("../../../lib/config/config-initializer", requireStubs);
     });
 
@@ -83,6 +92,7 @@ describe("configInitializer", () => {
         log.error.reset();
         npmInstallStub.restore();
         npmCheckStub.restore();
+        npmFetchPeerDependenciesStub.restore();
     });
 
     after(() => {
@@ -185,19 +195,19 @@ describe("configInitializer", () => {
             it("should support the airbnb style guide", () => {
                 const config = init.getConfigForStyleGuide("airbnb");
 
-                assert.deepEqual(config, { extends: "airbnb", installedESLint: true, plugins: ["react", "jsx-a11y", "import"] });
+                assert.deepEqual(config, { extends: "airbnb", installedESLint: true });
             });
 
             it("should support the airbnb base style guide", () => {
                 const config = init.getConfigForStyleGuide("airbnb-base");
 
-                assert.deepEqual(config, { extends: "airbnb-base", installedESLint: true, plugins: ["import"] });
+                assert.deepEqual(config, { extends: "airbnb-base", installedESLint: true });
             });
 
             it("should support the standard style guide", () => {
                 const config = init.getConfigForStyleGuide("standard");
 
-                assert.deepEqual(config, { extends: "standard", installedESLint: true, plugins: ["standard", "promise"] });
+                assert.deepEqual(config, { extends: "standard", installedESLint: true });
             });
 
             it("should throw when encountering an unsupported style guide", () => {
@@ -209,13 +219,31 @@ describe("configInitializer", () => {
             it("should install required sharable config", () => {
                 init.getConfigForStyleGuide("google");
                 assert(npmInstallStub.calledOnce);
-                assert.deepEqual(npmInstallStub.firstCall.args[0][1], "eslint-config-google");
+                assert(npmInstallStub.firstCall.args[0].some(name => name.startsWith("eslint-config-google@")));
             });
 
             it("should install ESLint if not installed locally", () => {
                 init.getConfigForStyleGuide("google");
                 assert(npmInstallStub.calledOnce);
-                assert.deepEqual(npmInstallStub.firstCall.args[0][0], "eslint");
+                assert(npmInstallStub.firstCall.args[0].some(name => name.startsWith("eslint@")));
+            });
+
+            it("should install peerDependencies of the sharable config", () => {
+                init.getConfigForStyleGuide("airbnb");
+
+                assert(npmFetchPeerDependenciesStub.calledOnce);
+                assert(npmFetchPeerDependenciesStub.firstCall.args[0] === "eslint-config-airbnb@latest");
+                assert(npmInstallStub.calledOnce);
+                assert.deepEqual(
+                    npmInstallStub.firstCall.args[0],
+                    [
+                        "eslint-config-airbnb@latest",
+                        "eslint@^3.19.0",
+                        "eslint-plugin-jsx-a11y@^5.0.1",
+                        "eslint-plugin-import@^2.2.0",
+                        "eslint-plugin-react@^7.0.1"
+                    ]
+                );
             });
         });
 
diff --git a/tests/lib/eslint.js b/tests/lib/eslint.js
index 7366484c5..b01069aac 100644
--- a/tests/lib/eslint.js
+++ b/tests/lib/eslint.js
@@ -469,7 +469,6 @@ describe("eslint", () => {
     });
 
 
-
     describe("when calling getScope", () => {
         const code = "function foo() { q: for(;;) { break q; } } function bar () { var q = t; } var baz = (() => { return 1; });";
 
diff --git a/tests/lib/ignored-paths.js b/tests/lib/ignored-paths.js
index 07d96672d..1ef1f29cd 100644
--- a/tests/lib/ignored-paths.js
+++ b/tests/lib/ignored-paths.js
@@ -164,6 +164,51 @@ describe("IgnoredPaths", () => {
                 )
             );
         });
+
+        it("should use package.json's eslintIgnore files if no specified .eslintignore file", () => {
+            const ignoredPaths = new IgnoredPaths({ ignore: true, cwd: getFixturePath("package-json-ignore") });
+
+            assert.isTrue(ignoredPaths.contains("hello.js"));
+            assert.isTrue(ignoredPaths.contains("world.js"));
+        });
+
+        it("should not use package.json's eslintIgnore files if specified .eslintignore file", () => {
+            const ignoredPaths = new IgnoredPaths({ ignore: true, cwd: getFixturePath() });
+
+            assert.isFalse(ignoredPaths.contains("hello.js"));
+            assert.isFalse(ignoredPaths.contains("world.js"));
+            assert.isTrue(ignoredPaths.contains("sampleignorepattern"));
+        });
+
+        it("should error if package.json's eslintIgnore is not an array of file paths", () => {
+            assert.throws(() => {
+                const ignoredPaths = new IgnoredPaths({ ignore: true, cwd: getFixturePath("bad-package-json-ignore") });
+
+                assert.ok(ignoredPaths);
+            }, "Package.json eslintIgnore property requires an array of paths");
+        });
+    });
+
+    describe("caching file reads", () => {
+
+        let readFileSyncCount;
+
+        before(() => {
+            readFileSyncCount = sinon.spy(fs, "readFileSync");
+        });
+
+        after(() => {
+            readFileSyncCount.restore();
+        });
+
+        it("should cache readFileSync on same file paths", () => {
+            const ignoreFilePath = getFixturePath(".eslintignore");
+            const ignoredPaths = new IgnoredPaths({ ignore: true, cwd: getFixturePath() });
+
+            ignoredPaths.readIgnoreFile(ignoreFilePath);
+            assert.isTrue(ignoredPaths.contains(ignoreFilePath));
+            sinon.assert.calledOnce(readFileSyncCount);
+        });
     });
 
     describe("initialization with ignorePattern", () => {
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index ed5fb2238..9c47fafe5 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -70,4 +70,18 @@ describe("Linter", () => {
             });
         });
     });
+
+    describe("verifyAndFix", () => {
+        it("Fixes the code", () => {
+            const linter = new Linter();
+            const messages = linter.verifyAndFix("var a", {
+                rules: {
+                    semi: 2
+                }
+            }, { filename: "test.js" });
+
+            assert.equal(messages.output, "var a;", "Fixes were applied correctly");
+            assert.isTrue(messages.fixed);
+        });
+    });
 });
diff --git a/tests/lib/rules/arrow-parens.js b/tests/lib/rules/arrow-parens.js
index 2bd370f35..a209d08c3 100644
--- a/tests/lib/rules/arrow-parens.js
+++ b/tests/lib/rules/arrow-parens.js
@@ -176,6 +176,18 @@ const invalid = [
             type
         }]
     },
+    {
+        code: "async(a) => a",
+        output: "async a => a",
+        options: ["as-needed"],
+        parserOptions: { ecmaVersion: 8 },
+        errors: [{
+            line: 1,
+            column: 1,
+            message: asNeededMessage,
+            type
+        }]
+    },
 
     // "as-needed", { "requireForBlockBody": true }
     {
@@ -223,6 +235,18 @@ const invalid = [
             message: requireForBlockBodyMessage,
             type
         }]
+    },
+    {
+        code: "async(a) => a",
+        output: "async a => a",
+        options: ["as-needed", { requireForBlockBody: true }],
+        parserOptions: { ecmaVersion: 8 },
+        errors: [{
+            line: 1,
+            column: 1,
+            message: requireForBlockBodyMessage,
+            type
+        }]
     }
 ];
 
diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js
index 335e8882f..fd2619ef9 100644
--- a/tests/lib/rules/indent.js
+++ b/tests/lib/rules/indent.js
@@ -2563,6 +2563,40 @@ ruleTester.run("indent", rule, {
             `,
             options: [4]
         },
+        {
+            code: unIndent`
+                [
+                ] || [
+                ]
+            `
+        },
+        {
+            code: unIndent`
+                (
+                    [
+                    ] || [
+                    ]
+                )
+            `
+        },
+        {
+            code: unIndent`
+                1
+                + (
+                    1
+                )
+            `
+        },
+        {
+            code: unIndent`
+                (
+                    foo && (
+                        bar ||
+                        baz
+                    )
+                )
+            `
+        },
         {
             code: unIndent`
                 var foo =
@@ -2983,6 +3017,41 @@ ruleTester.run("indent", rule, {
             `,
             options: [4, { flatTernaryExpressions: true }]
         },
+        {
+            code: unIndent`
+                function wrap() {
+                    return (
+                        foo ? bar :
+                        baz ? qux :
+                        foobar ? boop :
+                        /*else*/ beep
+                    )
+                }
+            `,
+            options: [4, { flatTernaryExpressions: true }]
+        },
+        {
+            code: unIndent`
+                function wrap() {
+                    return foo
+                        ? bar
+                        : baz
+                }
+            `,
+            options: [4, { flatTernaryExpressions: true }]
+        },
+        {
+            code: unIndent`
+                function wrap() {
+                    return (
+                        foo
+                            ? bar
+                            : baz
+                    )
+                }
+            `,
+            options: [4, { flatTernaryExpressions: true }]
+        },
         {
             code: unIndent`
                 foo(
@@ -3376,6 +3445,23 @@ ruleTester.run("indent", rule, {
             `,
             options: [4, { MemberExpression: "off" }]
         },
+        {
+            code: unIndent`
+                  foo = bar(
+                  ).baz(
+                  )
+            `,
+            options: [4, { MemberExpression: "off" }]
+        },
+        {
+            code: unIndent`
+                foo[
+                    bar ? baz :
+                    qux
+                ]
+            `,
+            options: [4, { flatTernaryExpressions: true }]
+        },
         {
             code: unIndent`
                   foo
@@ -7036,6 +7122,34 @@ ruleTester.run("indent", rule, {
             options: [4],
             errors: expectedErrors([2, 4, 8, "Identifier"])
         },
+        {
+            code: unIndent`
+                [
+                ] || [
+                    ]
+            `,
+            output: unIndent`
+                [
+                ] || [
+                ]
+            `,
+            errors: expectedErrors([3, 0, 4, "Punctuator"])
+        },
+        {
+            code: unIndent`
+                1
+                + (
+                        1
+                    )
+            `,
+            output: unIndent`
+                1
+                + (
+                    1
+                )
+            `,
+            errors: expectedErrors([[3, 4, 8, "Numeric"], [4, 0, 4, "Punctuator"]])
+        },
 
         // Template curlies
         {
diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js
index b30c42d86..fb69eb713 100644
--- a/tests/lib/rules/no-extra-parens.js
+++ b/tests/lib/rules/no-extra-parens.js
@@ -41,7 +41,6 @@ function invalid(code, output, type, line, config) {
     if (line) {
         result.errors[0].line = line;
     }
-
     return result;
 }
 
@@ -996,6 +995,27 @@ ruleTester.run("no-extra-parens", rule, {
             1,
             { parserOptions: { ecmaVersion: 2015 } }
         ),
+        invalid(
+            "for ((foo) of bar);",
+            "for (foo of bar);",
+            "Identifier",
+            1,
+            { parserOptions: { ecmaVersion: 2015 } }
+        ),
+        invalid(
+            "for ((foo)in bar);",
+            "for (foo in bar);",
+            "Identifier",
+            1,
+            { parserOptions: { ecmaVersion: 2015 } }
+        ),
+        invalid(
+            "for ((foo['bar'])of baz);",
+            "for (foo['bar']of baz);",
+            "MemberExpression",
+            1,
+            { parserOptions: { ecmaVersion: 2015 } }
+        ),
         invalid(
             "() => (({ foo: 1 }).foo)",
             "() => ({ foo: 1 }).foo",
diff --git a/tests/lib/rules/no-restricted-globals.js b/tests/lib/rules/no-restricted-globals.js
index 4041ebec0..df9d6e4ff 100644
--- a/tests/lib/rules/no-restricted-globals.js
+++ b/tests/lib/rules/no-restricted-globals.js
@@ -63,4 +63,3 @@ ruleTester.run("no-restricted-globals", rule, {
         }
     ]
 });
-
diff --git a/tests/lib/rules/semi-style.js b/tests/lib/rules/semi-style.js
index a0281bff7..43968facf 100644
--- a/tests/lib/rules/semi-style.js
+++ b/tests/lib/rules/semi-style.js
@@ -113,6 +113,12 @@ ruleTester.run("semi-style", rule, {
             options: ["last"],
             errors: ["Expected this semicolon to be at the end of the previous line."]
         },
+        {
+            code: "foo()\n;",
+            output: "foo();\n",
+            options: ["last"],
+            errors: ["Expected this semicolon to be at the end of the previous line."]
+        },
 
         {
             code: "foo;\nbar",
diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js
index 532a1b739..9afa4881c 100644
--- a/tests/lib/rules/space-infix-ops.js
+++ b/tests/lib/rules/space-infix-ops.js
@@ -9,9 +9,9 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const path = require("path"),
-    rule = require("../../../lib/rules/space-infix-ops"),
-    RuleTester = require("../../../lib/testers/rule-tester");
+const rule = require("../../../lib/rules/space-infix-ops"),
+    RuleTester = require("../../../lib/testers/rule-tester"),
+    parser = require("../../fixtures/fixture-parser");
 
 const ruleTester = new RuleTester();
 
@@ -30,10 +30,15 @@ ruleTester.run("space-infix-ops", rule, {
         { code: "const my_object = {key: 'value'};", parserOptions: { ecmaVersion: 6 } },
         { code: "var {a = 0} = bar;", parserOptions: { ecmaVersion: 6 } },
         { code: "function foo(a = 0) { }", parserOptions: { ecmaVersion: 6 } },
-        { code: "function foo(a: number = 0) { }", parser: path.resolve(__dirname, "../../fixtures/parsers/flow-stub-parser.js"), parserOptions: { ecmaVersion: 6 } },
         { code: "a ** b", parserOptions: { ecmaVersion: 7 } },
         { code: "a|0", options: [{ int32Hint: true }] },
-        { code: "a |0", options: [{ int32Hint: true }] }
+        { code: "a |0", options: [{ int32Hint: true }] },
+
+        // Type Annotations
+        { code: "function foo(a: number = 0) { }", parser: parser("type-annotations/function-parameter-type-annotation"), parserOptions: { ecmaVersion: 6 } },
+        { code: "function foo(): Bar { }", parser: parser("type-annotations/function-return-type-annotation"), parserOptions: { ecmaVersion: 6 } },
+        { code: "var foo: Bar = '';", parser: parser("type-annotations/variable-declaration-init-type-annotation"), parserOptions: { ecmaVersion: 6 } },
+        { code: "const foo = function(a: number = 0): Bar { };", parser: parser("type-annotations/function-expression-type-annotation"), parserOptions: { ecmaVersion: 6 } }
     ],
     invalid: [
         {
@@ -347,6 +352,32 @@ ruleTester.run("space-infix-ops", rule, {
                 column: 6,
                 nodeType: "BinaryExpression"
             }]
+        },
+
+        // Type Annotations
+
+        {
+            code: "var a: Foo= b;",
+            output: "var a: Foo = b;",
+            parser: parser("type-annotations/variable-declaration-init-type-annotation-no-space"),
+            errors: [{
+                message: "Infix operators must be spaced.",
+                type: "VariableDeclarator",
+                line: 1,
+                column: 11
+            }]
+        },
+        {
+            code: "function foo(a: number=0): Foo { }",
+            output: "function foo(a: number = 0): Foo { }",
+            parser: parser("type-annotations/function-declaration-type-annotation-no-space"),
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                message: "Infix operators must be spaced.",
+                line: 1,
+                column: 23,
+                nodeType: "AssignmentPattern"
+            }]
         }
     ]
 });
diff --git a/tests/lib/util/npm-util.js b/tests/lib/util/npm-util.js
index 48a41aa50..c8c7d8f2d 100644
--- a/tests/lib/util/npm-util.js
+++ b/tests/lib/util/npm-util.js
@@ -187,4 +187,15 @@ describe("npmUtil", () => {
             stub.restore();
         });
     });
+
+    describe("fetchPeerDependencies()", () => {
+        it("should execute 'npm show --json <packageName> peerDependencies' command", () => {
+            const stub = sandbox.stub(childProcess, "execSync").returns("");
+
+            npmUtil.fetchPeerDependencies("desired-package");
+            assert(stub.calledOnce);
+            assert.equal(stub.firstCall.args[0], "npm show --json desired-package peerDependencies");
+            stub.restore();
+        });
+    });
 });