Repository: eslint/eslint
Pull request #9585 (2017-11-05 22:37:07)

Docs: disallow use of the comma operator using no-restricted-syntax

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Documentation update

refs: https://github.com/eslint/eslint/pull/9465#issuecomment-338511025

**Is there anything you'd like reviewers to focus on?**
no.



Patch:
diff --git a/Makefile.js b/Makefile.js
index 544ee8fc6..02363aa66 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -20,7 +20,6 @@ const lodash = require("lodash"),
     fs = require("fs"),
     glob = require("glob"),
     markdownlint = require("markdownlint"),
-    nodeCLI = require("shelljs-nodecli"),
     os = require("os"),
     path = require("path"),
     semver = require("semver"),
@@ -103,7 +102,7 @@ function getTestFilePatterns() {
             initialValue.push(`"tests/lib/${currentValues}/**/*.js"`);
         }
         return initialValue;
-    }, ["tests/lib/rules/**/*.js", "tests/lib/*.js", "tests/bin/**/*.js", "tests/tools/**/*.js"]).join(" ");
+    }, ["\"tests/lib/rules/**/*.js\"", "\"tests/lib/*.js\"", "\"tests/bin/**/*.js\"", "\"tests/tools/**/*.js\""]).join(" ");
 }
 
 /**
@@ -468,6 +467,15 @@ function getFormatterResults() {
     }, { formatterResults: {} });
 }
 
+/**
+ * Gets a path to an executable in node_modules/.bin
+ * @param {string} command The executable name
+ * @returns {string} The executable path
+ */
+function getBinFile(command) {
+    return path.join("node_modules", ".bin", command);
+}
+
 //------------------------------------------------------------------------------
 // Tasks
 //------------------------------------------------------------------------------
@@ -560,21 +568,20 @@ target.test = function() {
     let errors = 0,
         lastReturn;
 
-    // exec(ISTANBUL + " cover " + MOCHA + "-- -c " + TEST_FILES);
-    lastReturn = nodeCLI.exec("istanbul", "cover", MOCHA, `-- -R progress -t ${MOCHA_TIMEOUT}`, "-c", TEST_FILES);
+    lastReturn = exec(`${getBinFile("istanbul")} cover ${MOCHA} -- -R progress -t ${MOCHA_TIMEOUT} -c ${TEST_FILES}`);
     if (lastReturn.code !== 0) {
         errors++;
     }
 
-    // exec(ISTANBUL + "check-coverage --statement 99 --branch 98 --function 99 --lines 99");
-    lastReturn = nodeCLI.exec("istanbul", "check-coverage", "--statement 99 --branch 98 --function 99 --lines 99");
+    lastReturn = exec(`${getBinFile("istanbul")} check-coverage --statement 99 --branch 98 --function 99 --lines 99`);
+
     if (lastReturn.code !== 0) {
         errors++;
     }
 
     target.browserify();
 
-    lastReturn = nodeCLI.exec("karma", "start karma.conf.js");
+    lastReturn = exec(`${getBinFile("karma")} start karma.conf.js`);
     if (lastReturn.code !== 0) {
         errors++;
     }
@@ -588,7 +595,7 @@ target.test = function() {
 
 target.docs = function() {
     echo("Generating documentation");
-    nodeCLI.exec("jsdoc", "-d jsdoc lib");
+    exec(`${getBinFile("jsdoc")} -d jsdoc lib`);
     echo("Documentation has been output to /jsdoc");
 };
 
@@ -799,10 +806,10 @@ target.browserify = function() {
     generateRulesIndex(TEMP_DIR);
 
     // 5. browserify the temp directory
-    nodeCLI.exec("browserify", "-x espree", `${TEMP_DIR}linter.js`, "-o", `${BUILD_DIR}eslint.js`, "-s eslint", "--global-transform [ babelify --presets [ es2015 ] ]");
+    exec(`${getBinFile("browserify")} -x espree ${TEMP_DIR}linter.js -o ${BUILD_DIR}eslint.js -s eslint --global-transform [ babelify --presets [ es2015 ] ]`);
 
     // 6. Browserify espree
-    nodeCLI.exec("browserify", "-r espree", "-o", `${TEMP_DIR}espree.js`);
+    exec(`${getBinFile("browserify")} -r espree -o ${TEMP_DIR}espree.js`);
 
     // 7. Concatenate Babel polyfill, Espree, and ESLint files together
     cat("./node_modules/babel-polyfill/dist/polyfill.js", `${TEMP_DIR}espree.js`, `${BUILD_DIR}eslint.js`).to(`${BUILD_DIR}eslint.js`);
diff --git a/appveyor.yml b/appveyor.yml
index e424a345b..966263e29 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -7,7 +7,7 @@ version: "{build}"
 # What combinations to test
 environment:
   matrix:
-    - nodejs_version: 4
+    - nodejs_version: 8
 
 branches:
   only:
diff --git a/docs/rules/lines-around-comment.md b/docs/rules/lines-around-comment.md
index ae8ef4de7..61af59698 100644
--- a/docs/rules/lines-around-comment.md
+++ b/docs/rules/lines-around-comment.md
@@ -21,6 +21,8 @@ This rule has an object option:
 * `"allowObjectEnd": true` allows comments to appear at the end of object literals
 * `"allowArrayStart": true` allows comments to appear at the start of array literals
 * `"allowArrayEnd": true` allows comments to appear at the end of array literals
+* `"allowClassStart": true` allows comments to appear at the start of classes
+* `"allowClassEnd": true` allows comments to appear at the end of classes
 * `"applyDefaultIgnorePatterns"` enables or disables the default comment patterns to be ignored by the rule
 * `"ignorePattern"` custom patterns to be ignored by the rule
 
diff --git a/docs/rules/lines-between-class-members.md b/docs/rules/lines-between-class-members.md
index c17b7a1aa..5196b6ad5 100644
--- a/docs/rules/lines-between-class-members.md
+++ b/docs/rules/lines-between-class-members.md
@@ -102,6 +102,6 @@ If you don't want to enforce empty lines between class members, you can disable
 ## Related Rules
 
 * [padded-blocks](padded-blocks.md)
-* [padding-line-between-statement](padding-line-between-statement.md)
+* [padding-line-between-statements](padding-line-between-statements.md)
 * [requirePaddingNewLinesAfterBlocks](http://jscs.info/rule/requirePaddingNewLinesAfterBlocks)
 * [disallowPaddingNewLinesAfterBlocks](http://jscs.info/rule/disallowPaddingNewLinesAfterBlocks)
diff --git a/docs/rules/no-sequences.md b/docs/rules/no-sequences.md
index 1d05e8255..f1f4afea0 100644
--- a/docs/rules/no-sequences.md
+++ b/docs/rules/no-sequences.md
@@ -66,3 +66,12 @@ while ((val = foo(), val < 42));
 ## When Not To Use It
 
 Disable this rule if sequence expressions with the comma operator are acceptable.
+Another case is where you might want to report all usages of the comma operator, even if they are wrapped in parentheses or in a for loop. You can achieve this using rule `no-restricted-syntax`:
+
+```js
+{
+    "rules": {
+        "no-restricted-syntax": ["error", "SequenceExpression"]
+    }
+}
+```
diff --git a/lib/ast-utils.js b/lib/ast-utils.js
index 23d2a7dcb..a186bdee5 100644
--- a/lib/ast-utils.js
+++ b/lib/ast-utils.js
@@ -406,6 +406,31 @@ function createGlobalLinebreakMatcher() {
     return new RegExp(LINEBREAK_MATCHER.source, "g");
 }
 
+/**
+ * Checks whether or not the tokens of two given nodes are same.
+ * @param {ASTNode} left - A node 1 to compare.
+ * @param {ASTNode} right - A node 2 to compare.
+ * @param {SourceCode} sourceCode - The ESLint source code object.
+ * @returns {boolean} the source code for the given node.
+ */
+function equalTokens(left, right, sourceCode) {
+    const tokensL = sourceCode.getTokens(left);
+    const tokensR = sourceCode.getTokens(right);
+
+    if (tokensL.length !== tokensR.length) {
+        return false;
+    }
+    for (let i = 0; i < tokensL.length; ++i) {
+        if (tokensL[i].type !== tokensR[i].type ||
+            tokensL[i].value !== tokensR[i].value
+        ) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
 //------------------------------------------------------------------------------
@@ -438,6 +463,7 @@ module.exports = {
     isArrayFromMethod,
     isParenthesised,
     createGlobalLinebreakMatcher,
+    equalTokens,
 
     isArrowToken,
     isClosingBraceToken,
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 39169dc42..55450fd63 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -409,9 +409,13 @@ class CLIEngine {
             });
         }
 
-        Object.keys(this.options.rules || {}).forEach(name => {
-            validator.validateRuleOptions(name, this.options.rules[name], "CLI", this.linter.rules);
-        });
+        if (this.options.rules && Object.keys(this.options.rules).length) {
+            const loadedRules = this.linter.getRules();
+
+            Object.keys(this.options.rules).forEach(name => {
+                validator.validateRuleOptions(loadedRules.get(name), name, this.options.rules[name], "CLI");
+            });
+        }
 
         this.config = new Config(this.options, this.linter);
     }
diff --git a/lib/config/config-file.js b/lib/config/config-file.js
index 8cefd437d..c5ff073cf 100644
--- a/lib/config/config-file.js
+++ b/lib/config/config-file.js
@@ -501,8 +501,10 @@ function loadFromDisk(resolvedPath, configContext) {
             }
         }
 
+        const ruleMap = configContext.linterContext.getRules();
+
         // validate the configuration before continuing
-        validator.validate(config, resolvedPath.configFullName, configContext.linterContext.rules, configContext.linterContext.environments);
+        validator.validate(config, resolvedPath.configFullName, ruleMap.get.bind(ruleMap), configContext.linterContext.environments);
 
         /*
          * If an `extends` property is defined, it represents a configuration file to use as
diff --git a/lib/config/config-validator.js b/lib/config/config-validator.js
index f2307dc63..3d98b5104 100644
--- a/lib/config/config-validator.js
+++ b/lib/config/config-validator.js
@@ -14,9 +14,7 @@ const ajv = require("../util/ajv"),
     configSchema = require("../../conf/config-schema.js"),
     util = require("util");
 
-const validators = {
-    rules: Object.create(null)
-};
+const ruleValidators = new WeakMap();
 
 //------------------------------------------------------------------------------
 // Private
@@ -25,13 +23,11 @@ let validateSchema;
 
 /**
  * Gets a complete options schema for a rule.
- * @param {string} id The rule's unique name.
- * @param {Rules} rulesContext Rule context
+ * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
  * @returns {Object} JSON Schema for the rule's options.
  */
-function getRuleOptionsSchema(id, rulesContext) {
-    const rule = rulesContext.get(id),
-        schema = rule && rule.schema || rule && rule.meta && rule.meta.schema;
+function getRuleOptionsSchema(rule) {
+    const schema = rule.schema || rule.meta && rule.meta.schema;
 
     // Given a tuple of schemas, insert warning level at the beginning
     if (Array.isArray(schema)) {
@@ -72,19 +68,20 @@ function validateRuleSeverity(options) {
 
 /**
  * Validates the non-severity options passed to a rule, based on its schema.
- * @param {string} id The rule's unique name
+ * @param {{create: Function}} rule The rule to validate
  * @param {array} localOptions The options for the rule, excluding severity
- * @param {Rules} rulesContext Rule context
  * @returns {void}
  */
-function validateRuleSchema(id, localOptions, rulesContext) {
-    const schema = getRuleOptionsSchema(id, rulesContext);
+function validateRuleSchema(rule, localOptions) {
+    if (!ruleValidators.has(rule)) {
+        const schema = getRuleOptionsSchema(rule);
 
-    if (!validators.rules[id] && schema) {
-        validators.rules[id] = ajv.compile(schema);
+        if (schema) {
+            ruleValidators.set(rule, ajv.compile(schema));
+        }
     }
 
-    const validateRule = validators.rules[id];
+    const validateRule = ruleValidators.get(rule);
 
     if (validateRule) {
         validateRule(localOptions);
@@ -98,21 +95,24 @@ function validateRuleSchema(id, localOptions, rulesContext) {
 
 /**
  * Validates a rule's options against its schema.
- * @param {string} id The rule's unique name.
+ * @param {{create: Function}|null} rule The rule that the config is being validated for
+ * @param {string} ruleId The rule's unique name.
  * @param {array|number} options The given options for the rule.
  * @param {string} source The name of the configuration source to report in any errors.
- * @param {Rules} rulesContext Rule context
  * @returns {void}
  */
-function validateRuleOptions(id, options, source, rulesContext) {
+function validateRuleOptions(rule, ruleId, options, source) {
+    if (!rule) {
+        return;
+    }
     try {
         const severity = validateRuleSeverity(options);
 
         if (severity !== 0 && !(typeof severity === "string" && severity.toLowerCase() === "off")) {
-            validateRuleSchema(id, Array.isArray(options) ? options.slice(1) : [], rulesContext);
+            validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
         }
     } catch (err) {
-        throw new Error(`${source}:\n\tConfiguration for rule "${id}" is invalid:\n${err.message}`);
+        throw new Error(`${source}:\n\tConfiguration for rule "${ruleId}" is invalid:\n${err.message}`);
     }
 }
 
@@ -143,16 +143,16 @@ function validateEnvironment(environment, source, envContext) {
  * Validates a rules config object
  * @param {Object} rulesConfig The rules config object to validate.
  * @param {string} source The name of the configuration source to report in any errors.
- * @param {Rules} rulesContext Rule context
+ * @param {function(string): {create: Function}} ruleMapper A mapper function from strings to loaded rules
  * @returns {void}
  */
-function validateRules(rulesConfig, source, rulesContext) {
+function validateRules(rulesConfig, source, ruleMapper) {
     if (!rulesConfig) {
         return;
     }
 
     Object.keys(rulesConfig).forEach(id => {
-        validateRuleOptions(id, rulesConfig[id], source, rulesContext);
+        validateRuleOptions(ruleMapper(id), id, rulesConfig[id], source);
     });
 }
 
@@ -223,13 +223,13 @@ function validateConfigSchema(config, source) {
  * Validates an entire config object.
  * @param {Object} config The config object to validate.
  * @param {string} source The name of the configuration source to report in any errors.
- * @param {Rules} rulesContext The rules context
+ * @param {function(string): {create: Function}} ruleMapper A mapper function from rule IDs to defined rules
  * @param {Environments} envContext The env context
  * @returns {void}
  */
-function validate(config, source, rulesContext, envContext) {
+function validate(config, source, ruleMapper, envContext) {
     validateConfigSchema(config, source);
-    validateRules(config.rules, source, rulesContext);
+    validateRules(config.rules, source, ruleMapper);
     validateEnvironment(config.env, source, envContext);
 }
 
diff --git a/lib/linter.js b/lib/linter.js
index 128798424..35ecf7c75 100755
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -278,7 +278,7 @@ function createDisableDirectives(type, loc, value) {
  * @param {string} filename The file being checked.
  * @param {ASTNode} ast The top node of the AST.
  * @param {Object} config The existing configuration data.
- * @param {Linter} linterContext Linter context object
+ * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
  * @returns {{
  *      config: Object,
  *      problems: Problem[],
@@ -291,7 +291,7 @@ function createDisableDirectives(type, loc, value) {
  * }} Modified config object, along with any problems encountered
  * while parsing config comments
  */
-function modifyConfigsFromComments(filename, ast, config, linterContext) {
+function modifyConfigsFromComments(filename, ast, config, ruleMapper) {
 
     const commentConfig = {
         exported: {},
@@ -337,7 +337,7 @@ function modifyConfigsFromComments(filename, ast, config, linterContext) {
                             Object.keys(parseResult.config).forEach(name => {
                                 const ruleValue = parseResult.config[name];
 
-                                validator.validateRuleOptions(name, ruleValue, `${filename} line ${comment.loc.start.line}`, linterContext.rules);
+                                validator.validateRuleOptions(ruleMapper(name), name, ruleValue, `${filename} line ${comment.loc.start.line}`);
                                 commentRules[name] = ruleValue;
                             });
                         } else {
@@ -806,7 +806,7 @@ module.exports = class Linter {
 
         // parse global comments and modify config
         if (allowInlineConfig !== false) {
-            const modifyConfigResult = modifyConfigsFromComments(filename, sourceCode.ast, config, this);
+            const modifyConfigResult = modifyConfigsFromComments(filename, sourceCode.ast, config, ruleId => this.rules.get(ruleId));
 
             config = modifyConfigResult.config;
             modifyConfigResult.problems.forEach(problem => problems.push(problem));
diff --git a/lib/rules/no-useless-call.js b/lib/rules/no-useless-call.js
index eb67bcb3b..e4820ac24 100644
--- a/lib/rules/no-useless-call.js
+++ b/lib/rules/no-useless-call.js
@@ -28,30 +28,6 @@ function isCallOrNonVariadicApply(node) {
     );
 }
 
-/**
- * Checks whether or not the tokens of two given nodes are same.
- * @param {ASTNode} left - A node 1 to compare.
- * @param {ASTNode} right - A node 2 to compare.
- * @param {SourceCode} sourceCode - The ESLint source code object.
- * @returns {boolean} the source code for the given node.
- */
-function equalTokens(left, right, sourceCode) {
-    const tokensL = sourceCode.getTokens(left);
-    const tokensR = sourceCode.getTokens(right);
-
-    if (tokensL.length !== tokensR.length) {
-        return false;
-    }
-    for (let i = 0; i < tokensL.length; ++i) {
-        if (tokensL[i].type !== tokensR[i].type ||
-            tokensL[i].value !== tokensR[i].value
-        ) {
-            return false;
-        }
-    }
-
-    return true;
-}
 
 /**
  * Checks whether or not `thisArg` is not changed by `.call()`/`.apply()`.
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, sourceCode) {
     if (!expectedThis) {
         return astUtils.isNullOrUndefined(thisArg);
     }
-    return equalTokens(expectedThis, thisArg, sourceCode);
+    return astUtils.equalTokens(expectedThis, thisArg, sourceCode);
 }
 
 //------------------------------------------------------------------------------
diff --git a/lib/rules/object-curly-newline.js b/lib/rules/object-curly-newline.js
index 42f277873..ebad69de2 100644
--- a/lib/rules/object-curly-newline.js
+++ b/lib/rules/object-curly-newline.js
@@ -131,8 +131,15 @@ module.exports = {
          */
         function check(node) {
             const options = normalizedOptions[node.type];
-            const openBrace = sourceCode.getFirstToken(node);
-            const closeBrace = sourceCode.getLastToken(node);
+            const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
+            let closeBrace;
+
+            if (node.typeAnnotation) {
+                closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
+            } else {
+                closeBrace = sourceCode.getLastToken(node);
+            }
+
             let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
             let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
             const needsLinebreaks = (
diff --git a/lib/rules/prefer-spread.js b/lib/rules/prefer-spread.js
index 1f5785828..c111d5f98 100644
--- a/lib/rules/prefer-spread.js
+++ b/lib/rules/prefer-spread.js
@@ -28,30 +28,6 @@ function isVariadicApplyCalling(node) {
     );
 }
 
-/**
- * Checks whether or not the tokens of two given nodes are same.
- * @param {ASTNode} left - A node 1 to compare.
- * @param {ASTNode} right - A node 2 to compare.
- * @param {SourceCode} sourceCode - The ESLint source code object.
- * @returns {boolean} the source code for the given node.
- */
-function equalTokens(left, right, sourceCode) {
-    const tokensL = sourceCode.getTokens(left);
-    const tokensR = sourceCode.getTokens(right);
-
-    if (tokensL.length !== tokensR.length) {
-        return false;
-    }
-    for (let i = 0; i < tokensL.length; ++i) {
-        if (tokensL[i].type !== tokensR[i].type ||
-            tokensL[i].value !== tokensR[i].value
-        ) {
-            return false;
-        }
-    }
-
-    return true;
-}
 
 /**
  * Checks whether or not `thisArg` is not changed by `.apply()`.
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, context) {
     if (!expectedThis) {
         return astUtils.isNullOrUndefined(thisArg);
     }
-    return equalTokens(expectedThis, thisArg, context);
+    return astUtils.equalTokens(expectedThis, thisArg, context);
 }
 
 //------------------------------------------------------------------------------
diff --git a/lib/rules/semi-style.js b/lib/rules/semi-style.js
index 97fcc3ac8..41fb39246 100644
--- a/lib/rules/semi-style.js
+++ b/lib/rules/semi-style.js
@@ -18,13 +18,51 @@ const astUtils = require("../ast-utils");
 const SELECTOR = `:matches(${
     [
         "BreakStatement", "ContinueStatement", "DebuggerStatement",
-        "DoWhileStatement", "EmptyStatement", "ExportAllDeclaration",
+        "DoWhileStatement", "ExportAllDeclaration",
         "ExportDefaultDeclaration", "ExportNamedDeclaration",
         "ExpressionStatement", "ImportDeclaration", "ReturnStatement",
         "ThrowStatement", "VariableDeclaration"
     ].join(",")
 })`;
 
+/**
+ * Get the child node list of a given node.
+ * This returns `Program#body`, `BlockStatement#body`, or `SwitchCase#consequent`.
+ * This is used to check whether a node is the first/last child.
+ * @param {Node} node A node to get child node list.
+ * @returns {Node[]|null} The child node list.
+ */
+function getChildren(node) {
+    const t = node.type;
+
+    if (t === "BlockStatement" || t === "Program") {
+        return node.body;
+    }
+    if (t === "SwitchCase") {
+        return node.consequent;
+    }
+    return null;
+}
+
+/**
+ * Check whether a given node is the last statement in the parent block.
+ * @param {Node} node A node to check.
+ * @returns {boolean} `true` if the node is the last statement in the parent block.
+ */
+function isLastChild(node) {
+    const t = node.parent.type;
+
+    if (t === "IfStatement" && node.parent.consequent === node && node.parent.alternate) { // before `else` keyword.
+        return true;
+    }
+    if (t === "DoWhileStatement") { // before `while` keyword.
+        return true;
+    }
+    const nodeList = getChildren(node.parent);
+
+    return nodeList !== null && nodeList[nodeList.length - 1] === node; // before `}` or etc.
+}
+
 module.exports = {
     meta: {
         docs: {
@@ -40,23 +78,6 @@ module.exports = {
         const sourceCode = context.getSourceCode();
         const option = context.options[0] || "last";
 
-        /**
-         * Check whether comments exist between the given 2 tokens.
-         * @param {Token} left The left token to check.
-         * @param {Token} right The right token to check.
-         * @returns {boolean} `true` if comments exist between the given 2 tokens.
-         */
-        function commentsExistBetween(left, right) {
-            return sourceCode.getFirstTokenBetween(
-                left,
-                right,
-                {
-                    includeComments: true,
-                    filter: astUtils.isCommentToken
-                }
-            ) !== null;
-        }
-
         /**
          * Check the given semicolon token.
          * @param {Token} semiToken The semicolon token to check.
@@ -79,7 +100,7 @@ module.exports = {
                             : "the beginning of the next line"
                     },
                     fix(fixer) {
-                        if (prevToken && nextToken && commentsExistBetween(prevToken, nextToken)) {
+                        if (prevToken && nextToken && sourceCode.commentsExistBetween(prevToken, nextToken)) {
                             return null;
                         }
 
@@ -95,6 +116,10 @@ module.exports = {
 
         return {
             [SELECTOR](node) {
+                if (option === "first" && isLastChild(node)) {
+                    return;
+                }
+
                 const lastToken = sourceCode.getLastToken(node);
 
                 if (astUtils.isSemicolonToken(lastToken)) {
diff --git a/lib/util/safe-emitter.js b/lib/util/safe-emitter.js
index 242cbe429..2fa373cb9 100644
--- a/lib/util/safe-emitter.js
+++ b/lib/util/safe-emitter.js
@@ -10,7 +10,7 @@
 //------------------------------------------------------------------------------
 
 /**
- * An object describing an AST selector
+ * An event emitter
  * @typedef {Object} SafeEmitter
  * @property {function(eventName: string, listenerFunc: Function): void} on Adds a listener for a given event name
  * @property {function(eventName: string, arg1?: any, arg2?: any, arg3?: any)} emit Emits an event with a given name.
diff --git a/package.json b/package.json
index da71cf6d0..35add7049 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
     "debug": "^3.0.1",
     "doctrine": "^2.0.0",
     "eslint-scope": "^3.7.1",
-    "espree": "^3.5.1",
+    "espree": "^3.5.2",
     "esquery": "^1.0.0",
     "estraverse": "^4.2.0",
     "esutils": "^2.0.2",
@@ -84,11 +84,11 @@
     "coveralls": "^2.13.1",
     "dateformat": "^2.0.0",
     "ejs": "^2.5.6",
-    "eslint-rule-composer": "^0.1.0",
     "eslint-plugin-eslint-plugin": "^1.2.0",
     "eslint-plugin-node": "^5.1.0",
     "eslint-plugin-rulesdir": "^0.1.0",
     "eslint-release": "^0.10.1",
+    "eslint-rule-composer": "^0.1.0",
     "eslump": "1.6.0",
     "esprima": "^4.0.0",
     "esprima-fb": "^15001.1001.0-dev-harmony-fb",
@@ -108,7 +108,6 @@
     "phantomjs-prebuilt": "^2.1.14",
     "proxyquire": "^1.8.0",
     "shelljs": "^0.7.7",
-    "shelljs-nodecli": "~0.1.1",
     "sinon": "^3.2.1",
     "temp": "^0.8.3",
     "through": "^2.3.8"
diff --git a/packages/eslint-config-eslint/LICENSE b/packages/eslint-config-eslint/LICENSE
index d41bdf795..777939e8f 100644
--- a/packages/eslint-config-eslint/LICENSE
+++ b/packages/eslint-config-eslint/LICENSE
@@ -1,5 +1,5 @@
 ESLint
-Copyright jQuery Foundation and other contributors, https://jquery.org/
+Copyright JS Foundation and other contributors, https://js.foundation
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal


Test patch:
diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js
index 9861998ff..aae66301d 100644
--- a/lib/testers/rule-tester.js
+++ b/lib/testers/rule-tester.js
@@ -271,6 +271,23 @@ class RuleTester {
             ].concat(scenarioErrors).join("\n"));
         }
 
+
+        linter.defineRule(ruleName, Object.assign({}, rule, {
+
+            // Create a wrapper rule that freezes the `context` properties.
+            create(context) {
+                freezeDeeply(context.options);
+                freezeDeeply(context.settings);
+                freezeDeeply(context.parserOptions);
+
+                return (typeof rule === "function" ? rule : rule.create)(context);
+            }
+        }));
+
+        linter.defineRules(this.rules);
+
+        const ruleMap = linter.getRules();
+
         /**
          * Run the rule for the given item
          * @param {string|Object} item Item to run the rule against
@@ -313,20 +330,22 @@ class RuleTester {
                 config.rules[ruleName] = 1;
             }
 
-            linter.defineRule(ruleName, Object.assign({}, rule, {
+            const schema = validator.getRuleOptionsSchema(rule);
 
-                // Create a wrapper rule that freezes the `context` properties.
-                create(context) {
-                    freezeDeeply(context.options);
-                    freezeDeeply(context.settings);
-                    freezeDeeply(context.parserOptions);
-
-                    return (typeof rule === "function" ? rule : rule.create)(context);
+            /*
+             * Setup AST getters.
+             * The goal is to check whether or not AST was modified when
+             * running the rule under test.
+             */
+            linter.defineRule("rule-tester/validate-ast", () => ({
+                Program(node) {
+                    beforeAST = cloneDeeplyExcludesParent(node);
+                },
+                "Program:exit"(node) {
+                    afterAST = node;
                 }
             }));
 
-            const schema = validator.getRuleOptionsSchema(ruleName, linter.rules);
-
             if (schema) {
                 ajv.validateSchema(schema);
 
@@ -341,21 +360,7 @@ class RuleTester {
                 }
             }
 
-            validator.validate(config, "rule-tester", linter.rules, new Environments());
-
-            /*
-             * Setup AST getters.
-             * The goal is to check whether or not AST was modified when
-             * running the rule under test.
-             */
-            linter.defineRule("rule-tester/validate-ast", () => ({
-                Program(node) {
-                    beforeAST = cloneDeeplyExcludesParent(node);
-                },
-                "Program:exit"(node) {
-                    afterAST = node;
-                }
-            }));
+            validator.validate(config, "rule-tester", ruleMap.get.bind(ruleMap), new Environments());
 
             return {
                 messages: linter.verify(code, config, filename, true),
@@ -532,7 +537,6 @@ class RuleTester {
             RuleTester.describe("valid", () => {
                 test.valid.forEach(valid => {
                     RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
-                        linter.defineRules(this.rules);
                         testValidTemplate(valid);
                     });
                 });
@@ -541,7 +545,6 @@ class RuleTester {
             RuleTester.describe("invalid", () => {
                 test.invalid.forEach(invalid => {
                     RuleTester.it(invalid.code, () => {
-                        linter.defineRules(this.rules);
                         testInvalidTemplate(invalid);
                     });
                 });
diff --git a/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline-type-literal.js b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline-type-literal.js
new file mode 100644
index 000000000..ae4bb5a3f
--- /dev/null
+++ b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline-type-literal.js
@@ -0,0 +1,821 @@
+
+/*
+  AST for:
+
+ function foo({
+ a,
+ b
+} : { a : string, b : string }) {}
+
+*/
+exports.parse = () => ({
+    "type": "Program",
+    "start": 0,
+    "end": 57,
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 5,
+            "column": 0
+        }
+    },
+    "range": [
+        0,
+        57
+    ],
+    "comments": [],
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            },
+            "range": [
+                0,
+                8
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            },
+            "range": [
+                9,
+                12
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            },
+            "range": [
+                12,
+                13
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 13,
+            "end": 14,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            },
+            "range": [
+                13,
+                14
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 16,
+            "end": 17,
+            "loc": {
+                "start": {
+                    "line": 2,
+                    "column": 1
+                },
+                "end": {
+                    "line": 2,
+                    "column": 2
+                }
+            },
+            "range": [
+                16,
+                17
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 17,
+            "end": 18,
+            "loc": {
+                "start": {
+                    "line": 2,
+                    "column": 2
+                },
+                "end": {
+                    "line": 2,
+                    "column": 3
+                }
+            },
+            "range": [
+                17,
+                18
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 20,
+            "end": 21,
+            "loc": {
+                "start": {
+                    "line": 3,
+                    "column": 1
+                },
+                "end": {
+                    "line": 3,
+                    "column": 2
+                }
+            },
+            "range": [
+                20,
+                21
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 22,
+            "end": 23,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 0
+                },
+                "end": {
+                    "line": 4,
+                    "column": 1
+                }
+            },
+            "range": [
+                22,
+                23
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 24,
+            "end": 25,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 2
+                },
+                "end": {
+                    "line": 4,
+                    "column": 3
+                }
+            },
+            "range": [
+                24,
+                25
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 26,
+            "end": 27,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 4
+                },
+                "end": {
+                    "line": 4,
+                    "column": 5
+                }
+            },
+            "range": [
+                26,
+                27
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 28,
+            "end": 29,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 6
+                },
+                "end": {
+                    "line": 4,
+                    "column": 7
+                }
+            },
+            "range": [
+                28,
+                29
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 30,
+            "end": 31,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 8
+                },
+                "end": {
+                    "line": 4,
+                    "column": 9
+                }
+            },
+            "range": [
+                30,
+                31
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "string",
+            "start": 32,
+            "end": 38,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 10
+                },
+                "end": {
+                    "line": 4,
+                    "column": 16
+                }
+            },
+            "range": [
+                32,
+                38
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 38,
+            "end": 39,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 16
+                },
+                "end": {
+                    "line": 4,
+                    "column": 17
+                }
+            },
+            "range": [
+                38,
+                39
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 40,
+            "end": 41,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 18
+                },
+                "end": {
+                    "line": 4,
+                    "column": 19
+                }
+            },
+            "range": [
+                40,
+                41
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 42,
+            "end": 43,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 20
+                },
+                "end": {
+                    "line": 4,
+                    "column": 21
+                }
+            },
+            "range": [
+                42,
+                43
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "string",
+            "start": 44,
+            "end": 50,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 22
+                },
+                "end": {
+                    "line": 4,
+                    "column": 28
+                }
+            },
+            "range": [
+                44,
+                50
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 51,
+            "end": 52,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 29
+                },
+                "end": {
+                    "line": 4,
+                    "column": 30
+                }
+            },
+            "range": [
+                51,
+                52
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 52,
+            "end": 53,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 30
+                },
+                "end": {
+                    "line": 4,
+                    "column": 31
+                }
+            },
+            "range": [
+                52,
+                53
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 54,
+            "end": 55,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 32
+                },
+                "end": {
+                    "line": 4,
+                    "column": 33
+                }
+            },
+            "range": [
+                54,
+                55
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 55,
+            "end": 56,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 33
+                },
+                "end": {
+                    "line": 4,
+                    "column": 34
+                }
+            },
+            "range": [
+                55,
+                56
+            ]
+        }
+    ],
+    "sourceType": "module",
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "start": 0,
+            "end": 56,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 4,
+                    "column": 34
+                }
+            },
+            "range": [
+                0,
+                56
+            ],
+            "id": {
+                "type": "Identifier",
+                "start": 9,
+                "end": 12,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    },
+                    "identifierName": "foo"
+                },
+                "range": [
+                    9,
+                    12
+                ],
+                "name": "foo",
+                "_babelType": "Identifier"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [
+                {
+                    "type": "ObjectPattern",
+                    "start": 13,
+                    "end": 52,
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 13
+                        },
+                        "end": {
+                            "line": 4,
+                            "column": 30
+                        }
+                    },
+                    "range": [
+                        13,
+                        52
+                    ],
+                    "properties": [
+                        {
+                            "type": "Property",
+                            "start": 16,
+                            "end": 17,
+                            "loc": {
+                                "start": {
+                                    "line": 2,
+                                    "column": 1
+                                },
+                                "end": {
+                                    "line": 2,
+                                    "column": 2
+                                }
+                            },
+                            "range": [
+                                16,
+                                17
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 16,
+                                "end": 17,
+                                "loc": {
+                                    "start": {
+                                        "line": 2,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 2,
+                                        "column": 2
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    16,
+                                    17
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 16,
+                                "end": 17,
+                                "loc": {
+                                    "start": {
+                                        "line": 2,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 2,
+                                        "column": 2
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    16,
+                                    17
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        },
+                        {
+                            "type": "Property",
+                            "start": 20,
+                            "end": 21,
+                            "loc": {
+                                "start": {
+                                    "line": 3,
+                                    "column": 1
+                                },
+                                "end": {
+                                    "line": 3,
+                                    "column": 2
+                                }
+                            },
+                            "range": [
+                                20,
+                                21
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 20,
+                                "end": 21,
+                                "loc": {
+                                    "start": {
+                                        "line": 3,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 3,
+                                        "column": 2
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    20,
+                                    21
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 20,
+                                "end": 21,
+                                "loc": {
+                                    "start": {
+                                        "line": 3,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 3,
+                                        "column": 2
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    20,
+                                    21
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        }
+                    ],
+                    "typeAnnotation": {
+                        "type": "TypeAnnotation",
+                        "start": 24,
+                        "end": 52,
+                        "loc": {
+                            "start": {
+                                "line": 4,
+                                "column": 2
+                            },
+                            "end": {
+                                "line": 4,
+                                "column": 30
+                            }
+                        },
+                        "range": [
+                            24,
+                            52
+                        ],
+                        "typeAnnotation": {
+                            "type": "ObjectTypeAnnotation",
+                            "start": 26,
+                            "end": 52,
+                            "loc": {
+                                "start": {
+                                    "line": 4,
+                                    "column": 4
+                                },
+                                "end": {
+                                    "line": 4,
+                                    "column": 30
+                                }
+                            },
+                            "range": [
+                                26,
+                                52
+                            ],
+                            "callProperties": [],
+                            "properties": [
+                                {
+                                    "type": "ObjectTypeProperty",
+                                    "start": 28,
+                                    "end": 38,
+                                    "loc": {
+                                        "start": {
+                                            "line": 4,
+                                            "column": 6
+                                        },
+                                        "end": {
+                                            "line": 4,
+                                            "column": 16
+                                        }
+                                    },
+                                    "range": [
+                                        28,
+                                        38
+                                    ],
+                                    "static": false,
+                                    "kind": "init",
+                                    "value": {
+                                        "type": "StringTypeAnnotation",
+                                        "start": 32,
+                                        "end": 38,
+                                        "loc": {
+                                            "start": {
+                                                "line": 4,
+                                                "column": 10
+                                            },
+                                            "end": {
+                                                "line": 4,
+                                                "column": 16
+                                            }
+                                        },
+                                        "range": [
+                                            32,
+                                            38
+                                        ],
+                                        "_babelType": "StringTypeAnnotation"
+                                    },
+                                    "variance": null,
+                                    "optional": false,
+                                    "_babelType": "ObjectTypeProperty"
+                                },
+                                {
+                                    "type": "ObjectTypeProperty",
+                                    "start": 40,
+                                    "end": 50,
+                                    "loc": {
+                                        "start": {
+                                            "line": 4,
+                                            "column": 18
+                                        },
+                                        "end": {
+                                            "line": 4,
+                                            "column": 28
+                                        }
+                                    },
+                                    "range": [
+                                        40,
+                                        50
+                                    ],
+                                    "static": false,
+                                    "kind": "init",
+                                    "value": {
+                                        "type": "StringTypeAnnotation",
+                                        "start": 44,
+                                        "end": 50,
+                                        "loc": {
+                                            "start": {
+                                                "line": 4,
+                                                "column": 22
+                                            },
+                                            "end": {
+                                                "line": 4,
+                                                "column": 28
+                                            }
+                                        },
+                                        "range": [
+                                            44,
+                                            50
+                                        ],
+                                        "_babelType": "StringTypeAnnotation"
+                                    },
+                                    "variance": null,
+                                    "optional": false,
+                                    "_babelType": "ObjectTypeProperty"
+                                }
+                            ],
+                            "indexers": [],
+                            "exact": false,
+                            "_babelType": "ObjectTypeAnnotation"
+                        },
+                        "_babelType": "TypeAnnotation"
+                    },
+                    "_babelType": "ObjectPattern"
+                }
+            ],
+            "body": {
+                "type": "BlockStatement",
+                "start": 54,
+                "end": 56,
+                "loc": {
+                    "start": {
+                        "line": 4,
+                        "column": 32
+                    },
+                    "end": {
+                        "line": 4,
+                        "column": 34
+                    }
+                },
+                "range": [
+                    54,
+                    56
+                ],
+                "body": [],
+                "_babelType": "BlockStatement"
+            },
+            "_babelType": "FunctionDeclaration"
+        }
+    ]
+});
+
diff --git a/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline.js b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline.js
new file mode 100644
index 000000000..8e2f53b07
--- /dev/null
+++ b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-multiline.js
@@ -0,0 +1,591 @@
+
+/*
+  AST for:
+
+function foo({
+ a,
+ b
+} : MyType) {}
+
+*/
+exports.parse = () => ({
+    "type": "Program",
+    "start": 0,
+    "end": 37,
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 5,
+            "column": 0
+        }
+    },
+    "range": [
+        0,
+        37
+    ],
+    "comments": [],
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            },
+            "range": [
+                0,
+                8
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            },
+            "range": [
+                9,
+                12
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            },
+            "range": [
+                12,
+                13
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 13,
+            "end": 14,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            },
+            "range": [
+                13,
+                14
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 16,
+            "end": 17,
+            "loc": {
+                "start": {
+                    "line": 2,
+                    "column": 1
+                },
+                "end": {
+                    "line": 2,
+                    "column": 2
+                }
+            },
+            "range": [
+                16,
+                17
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 17,
+            "end": 18,
+            "loc": {
+                "start": {
+                    "line": 2,
+                    "column": 2
+                },
+                "end": {
+                    "line": 2,
+                    "column": 3
+                }
+            },
+            "range": [
+                17,
+                18
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 20,
+            "end": 21,
+            "loc": {
+                "start": {
+                    "line": 3,
+                    "column": 1
+                },
+                "end": {
+                    "line": 3,
+                    "column": 2
+                }
+            },
+            "range": [
+                20,
+                21
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 22,
+            "end": 23,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 0
+                },
+                "end": {
+                    "line": 4,
+                    "column": 1
+                }
+            },
+            "range": [
+                22,
+                23
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 24,
+            "end": 25,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 2
+                },
+                "end": {
+                    "line": 4,
+                    "column": 3
+                }
+            },
+            "range": [
+                24,
+                25
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "MyType",
+            "start": 26,
+            "end": 32,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 4
+                },
+                "end": {
+                    "line": 4,
+                    "column": 10
+                }
+            },
+            "range": [
+                26,
+                32
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 32,
+            "end": 33,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 10
+                },
+                "end": {
+                    "line": 4,
+                    "column": 11
+                }
+            },
+            "range": [
+                32,
+                33
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 34,
+            "end": 35,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 12
+                },
+                "end": {
+                    "line": 4,
+                    "column": 13
+                }
+            },
+            "range": [
+                34,
+                35
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 35,
+            "end": 36,
+            "loc": {
+                "start": {
+                    "line": 4,
+                    "column": 13
+                },
+                "end": {
+                    "line": 4,
+                    "column": 14
+                }
+            },
+            "range": [
+                35,
+                36
+            ]
+        }
+    ],
+    "sourceType": "module",
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "start": 0,
+            "end": 36,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 4,
+                    "column": 14
+                }
+            },
+            "range": [
+                0,
+                36
+            ],
+            "id": {
+                "type": "Identifier",
+                "start": 9,
+                "end": 12,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    },
+                    "identifierName": "foo"
+                },
+                "range": [
+                    9,
+                    12
+                ],
+                "name": "foo",
+                "_babelType": "Identifier"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [
+                {
+                    "type": "ObjectPattern",
+                    "start": 13,
+                    "end": 32,
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 13
+                        },
+                        "end": {
+                            "line": 4,
+                            "column": 10
+                        }
+                    },
+                    "range": [
+                        13,
+                        32
+                    ],
+                    "properties": [
+                        {
+                            "type": "Property",
+                            "start": 16,
+                            "end": 17,
+                            "loc": {
+                                "start": {
+                                    "line": 2,
+                                    "column": 1
+                                },
+                                "end": {
+                                    "line": 2,
+                                    "column": 2
+                                }
+                            },
+                            "range": [
+                                16,
+                                17
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 16,
+                                "end": 17,
+                                "loc": {
+                                    "start": {
+                                        "line": 2,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 2,
+                                        "column": 2
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    16,
+                                    17
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 16,
+                                "end": 17,
+                                "loc": {
+                                    "start": {
+                                        "line": 2,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 2,
+                                        "column": 2
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    16,
+                                    17
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        },
+                        {
+                            "type": "Property",
+                            "start": 20,
+                            "end": 21,
+                            "loc": {
+                                "start": {
+                                    "line": 3,
+                                    "column": 1
+                                },
+                                "end": {
+                                    "line": 3,
+                                    "column": 2
+                                }
+                            },
+                            "range": [
+                                20,
+                                21
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 20,
+                                "end": 21,
+                                "loc": {
+                                    "start": {
+                                        "line": 3,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 3,
+                                        "column": 2
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    20,
+                                    21
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 20,
+                                "end": 21,
+                                "loc": {
+                                    "start": {
+                                        "line": 3,
+                                        "column": 1
+                                    },
+                                    "end": {
+                                        "line": 3,
+                                        "column": 2
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    20,
+                                    21
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        }
+                    ],
+                    "typeAnnotation": {
+                        "type": "TypeAnnotation",
+                        "start": 24,
+                        "end": 32,
+                        "loc": {
+                            "start": {
+                                "line": 4,
+                                "column": 2
+                            },
+                            "end": {
+                                "line": 4,
+                                "column": 10
+                            }
+                        },
+                        "range": [
+                            24,
+                            32
+                        ],
+                        "typeAnnotation": {
+                            "type": "GenericTypeAnnotation",
+                            "start": 26,
+                            "end": 32,
+                            "loc": {
+                                "start": {
+                                    "line": 4,
+                                    "column": 4
+                                },
+                                "end": {
+                                    "line": 4,
+                                    "column": 10
+                                }
+                            },
+                            "range": [
+                                26,
+                                32
+                            ],
+                            "typeParameters": null,
+                            "id": {
+                                "type": "Identifier",
+                                "start": 26,
+                                "end": 32,
+                                "loc": {
+                                    "start": {
+                                        "line": 4,
+                                        "column": 4
+                                    },
+                                    "end": {
+                                        "line": 4,
+                                        "column": 10
+                                    },
+                                    "identifierName": "MyType"
+                                },
+                                "range": [
+                                    26,
+                                    32
+                                ],
+                                "name": "MyType",
+                                "_babelType": "Identifier"
+                            },
+                            "_babelType": "GenericTypeAnnotation"
+                        },
+                        "_babelType": "TypeAnnotation"
+                    },
+                    "_babelType": "ObjectPattern"
+                }
+            ],
+            "body": {
+                "type": "BlockStatement",
+                "start": 34,
+                "end": 36,
+                "loc": {
+                    "start": {
+                        "line": 4,
+                        "column": 12
+                    },
+                    "end": {
+                        "line": 4,
+                        "column": 14
+                    }
+                },
+                "range": [
+                    34,
+                    36
+                ],
+                "body": [],
+                "_babelType": "BlockStatement"
+            },
+            "_babelType": "FunctionDeclaration"
+        }
+    ]
+});
+
diff --git a/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline-type-literal.js b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline-type-literal.js
new file mode 100644
index 000000000..96abb1f14
--- /dev/null
+++ b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline-type-literal.js
@@ -0,0 +1,818 @@
+
+/*
+  AST for:
+
+function foo({ a, b } : { a : string, b : string }) {}
+
+*/
+exports.parse = () => ({
+    "type": "Program",
+    "start": 0,
+    "end": 55,
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 2,
+            "column": 0
+        }
+    },
+    "range": [
+        0,
+        55
+    ],
+    "comments": [],
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            },
+            "range": [
+                0,
+                8
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            },
+            "range": [
+                9,
+                12
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            },
+            "range": [
+                12,
+                13
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 13,
+            "end": 14,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            },
+            "range": [
+                13,
+                14
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 15,
+            "end": 16,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 15
+                },
+                "end": {
+                    "line": 1,
+                    "column": 16
+                }
+            },
+            "range": [
+                15,
+                16
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 16,
+            "end": 17,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 16
+                },
+                "end": {
+                    "line": 1,
+                    "column": 17
+                }
+            },
+            "range": [
+                16,
+                17
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 18,
+            "end": 19,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 18
+                },
+                "end": {
+                    "line": 1,
+                    "column": 19
+                }
+            },
+            "range": [
+                18,
+                19
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 20,
+            "end": 21,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 20
+                },
+                "end": {
+                    "line": 1,
+                    "column": 21
+                }
+            },
+            "range": [
+                20,
+                21
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 22,
+            "end": 23,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 22
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            },
+            "range": [
+                22,
+                23
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 24,
+            "end": 25,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 24
+                },
+                "end": {
+                    "line": 1,
+                    "column": 25
+                }
+            },
+            "range": [
+                24,
+                25
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 26,
+            "end": 27,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 26
+                },
+                "end": {
+                    "line": 1,
+                    "column": 27
+                }
+            },
+            "range": [
+                26,
+                27
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 28,
+            "end": 29,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 28
+                },
+                "end": {
+                    "line": 1,
+                    "column": 29
+                }
+            },
+            "range": [
+                28,
+                29
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "string",
+            "start": 30,
+            "end": 36,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 30
+                },
+                "end": {
+                    "line": 1,
+                    "column": 36
+                }
+            },
+            "range": [
+                30,
+                36
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 36,
+            "end": 37,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 36
+                },
+                "end": {
+                    "line": 1,
+                    "column": 37
+                }
+            },
+            "range": [
+                36,
+                37
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 38,
+            "end": 39,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 38
+                },
+                "end": {
+                    "line": 1,
+                    "column": 39
+                }
+            },
+            "range": [
+                38,
+                39
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 40,
+            "end": 41,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 40
+                },
+                "end": {
+                    "line": 1,
+                    "column": 41
+                }
+            },
+            "range": [
+                40,
+                41
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "string",
+            "start": 42,
+            "end": 48,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 42
+                },
+                "end": {
+                    "line": 1,
+                    "column": 48
+                }
+            },
+            "range": [
+                42,
+                48
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 49,
+            "end": 50,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 49
+                },
+                "end": {
+                    "line": 1,
+                    "column": 50
+                }
+            },
+            "range": [
+                49,
+                50
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 50,
+            "end": 51,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 50
+                },
+                "end": {
+                    "line": 1,
+                    "column": 51
+                }
+            },
+            "range": [
+                50,
+                51
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 52,
+            "end": 53,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 52
+                },
+                "end": {
+                    "line": 1,
+                    "column": 53
+                }
+            },
+            "range": [
+                52,
+                53
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 53,
+            "end": 54,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 53
+                },
+                "end": {
+                    "line": 1,
+                    "column": 54
+                }
+            },
+            "range": [
+                53,
+                54
+            ]
+        }
+    ],
+    "sourceType": "module",
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "start": 0,
+            "end": 54,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 54
+                }
+            },
+            "range": [
+                0,
+                54
+            ],
+            "id": {
+                "type": "Identifier",
+                "start": 9,
+                "end": 12,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    },
+                    "identifierName": "foo"
+                },
+                "range": [
+                    9,
+                    12
+                ],
+                "name": "foo",
+                "_babelType": "Identifier"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [
+                {
+                    "type": "ObjectPattern",
+                    "start": 13,
+                    "end": 50,
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 13
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 50
+                        }
+                    },
+                    "range": [
+                        13,
+                        50
+                    ],
+                    "properties": [
+                        {
+                            "type": "Property",
+                            "start": 15,
+                            "end": 16,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 15
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 16
+                                }
+                            },
+                            "range": [
+                                15,
+                                16
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 15,
+                                "end": 16,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 15
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 16
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    15,
+                                    16
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 15,
+                                "end": 16,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 15
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 16
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    15,
+                                    16
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        },
+                        {
+                            "type": "Property",
+                            "start": 18,
+                            "end": 19,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 18
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 19
+                                }
+                            },
+                            "range": [
+                                18,
+                                19
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 18,
+                                "end": 19,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 18
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 19
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    18,
+                                    19
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 18,
+                                "end": 19,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 18
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 19
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    18,
+                                    19
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        }
+                    ],
+                    "typeAnnotation": {
+                        "type": "TypeAnnotation",
+                        "start": 22,
+                        "end": 50,
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 22
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 50
+                            }
+                        },
+                        "range": [
+                            22,
+                            50
+                        ],
+                        "typeAnnotation": {
+                            "type": "ObjectTypeAnnotation",
+                            "start": 24,
+                            "end": 50,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 24
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 50
+                                }
+                            },
+                            "range": [
+                                24,
+                                50
+                            ],
+                            "callProperties": [],
+                            "properties": [
+                                {
+                                    "type": "ObjectTypeProperty",
+                                    "start": 26,
+                                    "end": 36,
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 26
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 36
+                                        }
+                                    },
+                                    "range": [
+                                        26,
+                                        36
+                                    ],
+                                    "static": false,
+                                    "kind": "init",
+                                    "value": {
+                                        "type": "StringTypeAnnotation",
+                                        "start": 30,
+                                        "end": 36,
+                                        "loc": {
+                                            "start": {
+                                                "line": 1,
+                                                "column": 30
+                                            },
+                                            "end": {
+                                                "line": 1,
+                                                "column": 36
+                                            }
+                                        },
+                                        "range": [
+                                            30,
+                                            36
+                                        ],
+                                        "_babelType": "StringTypeAnnotation"
+                                    },
+                                    "variance": null,
+                                    "optional": false,
+                                    "_babelType": "ObjectTypeProperty"
+                                },
+                                {
+                                    "type": "ObjectTypeProperty",
+                                    "start": 38,
+                                    "end": 48,
+                                    "loc": {
+                                        "start": {
+                                            "line": 1,
+                                            "column": 38
+                                        },
+                                        "end": {
+                                            "line": 1,
+                                            "column": 48
+                                        }
+                                    },
+                                    "range": [
+                                        38,
+                                        48
+                                    ],
+                                    "static": false,
+                                    "kind": "init",
+                                    "value": {
+                                        "type": "StringTypeAnnotation",
+                                        "start": 42,
+                                        "end": 48,
+                                        "loc": {
+                                            "start": {
+                                                "line": 1,
+                                                "column": 42
+                                            },
+                                            "end": {
+                                                "line": 1,
+                                                "column": 48
+                                            }
+                                        },
+                                        "range": [
+                                            42,
+                                            48
+                                        ],
+                                        "_babelType": "StringTypeAnnotation"
+                                    },
+                                    "variance": null,
+                                    "optional": false,
+                                    "_babelType": "ObjectTypeProperty"
+                                }
+                            ],
+                            "indexers": [],
+                            "exact": false,
+                            "_babelType": "ObjectTypeAnnotation"
+                        },
+                        "_babelType": "TypeAnnotation"
+                    },
+                    "_babelType": "ObjectPattern"
+                }
+            ],
+            "body": {
+                "type": "BlockStatement",
+                "start": 52,
+                "end": 54,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 52
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 54
+                    }
+                },
+                "range": [
+                    52,
+                    54
+                ],
+                "body": [],
+                "_babelType": "BlockStatement"
+            },
+            "_babelType": "FunctionDeclaration"
+        }
+    ]
+});
+
diff --git a/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline.js b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline.js
new file mode 100644
index 000000000..a9df13092
--- /dev/null
+++ b/tests/fixtures/parsers/object-curly-newline/flow-stub-parser-singleline.js
@@ -0,0 +1,588 @@
+
+/*
+  AST for:
+
+function foo({ a, b } : MyType) {}
+
+*/
+exports.parse = () => ({
+    "type": "Program",
+    "start": 0,
+    "end": 35,
+    "loc": {
+        "start": {
+            "line": 1,
+            "column": 0
+        },
+        "end": {
+            "line": 2,
+            "column": 0
+        }
+    },
+    "range": [
+        0,
+        35
+    ],
+    "comments": [],
+    "tokens": [
+        {
+            "type": "Keyword",
+            "value": "function",
+            "start": 0,
+            "end": 8,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 8
+                }
+            },
+            "range": [
+                0,
+                8
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "foo",
+            "start": 9,
+            "end": 12,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 9
+                },
+                "end": {
+                    "line": 1,
+                    "column": 12
+                }
+            },
+            "range": [
+                9,
+                12
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "(",
+            "start": 12,
+            "end": 13,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 12
+                },
+                "end": {
+                    "line": 1,
+                    "column": 13
+                }
+            },
+            "range": [
+                12,
+                13
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 13,
+            "end": 14,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 13
+                },
+                "end": {
+                    "line": 1,
+                    "column": 14
+                }
+            },
+            "range": [
+                13,
+                14
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "a",
+            "start": 15,
+            "end": 16,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 15
+                },
+                "end": {
+                    "line": 1,
+                    "column": 16
+                }
+            },
+            "range": [
+                15,
+                16
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ",",
+            "start": 16,
+            "end": 17,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 16
+                },
+                "end": {
+                    "line": 1,
+                    "column": 17
+                }
+            },
+            "range": [
+                16,
+                17
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "b",
+            "start": 18,
+            "end": 19,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 18
+                },
+                "end": {
+                    "line": 1,
+                    "column": 19
+                }
+            },
+            "range": [
+                18,
+                19
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 20,
+            "end": 21,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 20
+                },
+                "end": {
+                    "line": 1,
+                    "column": 21
+                }
+            },
+            "range": [
+                20,
+                21
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ":",
+            "start": 22,
+            "end": 23,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 22
+                },
+                "end": {
+                    "line": 1,
+                    "column": 23
+                }
+            },
+            "range": [
+                22,
+                23
+            ]
+        },
+        {
+            "type": "Identifier",
+            "value": "MyType",
+            "start": 24,
+            "end": 30,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 24
+                },
+                "end": {
+                    "line": 1,
+                    "column": 30
+                }
+            },
+            "range": [
+                24,
+                30
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": ")",
+            "start": 30,
+            "end": 31,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 30
+                },
+                "end": {
+                    "line": 1,
+                    "column": 31
+                }
+            },
+            "range": [
+                30,
+                31
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "{",
+            "start": 32,
+            "end": 33,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 32
+                },
+                "end": {
+                    "line": 1,
+                    "column": 33
+                }
+            },
+            "range": [
+                32,
+                33
+            ]
+        },
+        {
+            "type": "Punctuator",
+            "value": "}",
+            "start": 33,
+            "end": 34,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 33
+                },
+                "end": {
+                    "line": 1,
+                    "column": 34
+                }
+            },
+            "range": [
+                33,
+                34
+            ]
+        }
+    ],
+    "sourceType": "module",
+    "body": [
+        {
+            "type": "FunctionDeclaration",
+            "start": 0,
+            "end": 34,
+            "loc": {
+                "start": {
+                    "line": 1,
+                    "column": 0
+                },
+                "end": {
+                    "line": 1,
+                    "column": 34
+                }
+            },
+            "range": [
+                0,
+                34
+            ],
+            "id": {
+                "type": "Identifier",
+                "start": 9,
+                "end": 12,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 9
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 12
+                    },
+                    "identifierName": "foo"
+                },
+                "range": [
+                    9,
+                    12
+                ],
+                "name": "foo",
+                "_babelType": "Identifier"
+            },
+            "generator": false,
+            "expression": false,
+            "async": false,
+            "params": [
+                {
+                    "type": "ObjectPattern",
+                    "start": 13,
+                    "end": 30,
+                    "loc": {
+                        "start": {
+                            "line": 1,
+                            "column": 13
+                        },
+                        "end": {
+                            "line": 1,
+                            "column": 30
+                        }
+                    },
+                    "range": [
+                        13,
+                        30
+                    ],
+                    "properties": [
+                        {
+                            "type": "Property",
+                            "start": 15,
+                            "end": 16,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 15
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 16
+                                }
+                            },
+                            "range": [
+                                15,
+                                16
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 15,
+                                "end": 16,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 15
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 16
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    15,
+                                    16
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 15,
+                                "end": 16,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 15
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 16
+                                    },
+                                    "identifierName": "a"
+                                },
+                                "range": [
+                                    15,
+                                    16
+                                ],
+                                "name": "a",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        },
+                        {
+                            "type": "Property",
+                            "start": 18,
+                            "end": 19,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 18
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 19
+                                }
+                            },
+                            "range": [
+                                18,
+                                19
+                            ],
+                            "method": false,
+                            "computed": false,
+                            "key": {
+                                "type": "Identifier",
+                                "start": 18,
+                                "end": 19,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 18
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 19
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    18,
+                                    19
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "shorthand": true,
+                            "value": {
+                                "type": "Identifier",
+                                "start": 18,
+                                "end": 19,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 18
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 19
+                                    },
+                                    "identifierName": "b"
+                                },
+                                "range": [
+                                    18,
+                                    19
+                                ],
+                                "name": "b",
+                                "_babelType": "Identifier"
+                            },
+                            "kind": "init",
+                            "extra": {
+                                "shorthand": true
+                            },
+                            "_babelType": "Property"
+                        }
+                    ],
+                    "typeAnnotation": {
+                        "type": "TypeAnnotation",
+                        "start": 22,
+                        "end": 30,
+                        "loc": {
+                            "start": {
+                                "line": 1,
+                                "column": 22
+                            },
+                            "end": {
+                                "line": 1,
+                                "column": 30
+                            }
+                        },
+                        "range": [
+                            22,
+                            30
+                        ],
+                        "typeAnnotation": {
+                            "type": "GenericTypeAnnotation",
+                            "start": 24,
+                            "end": 30,
+                            "loc": {
+                                "start": {
+                                    "line": 1,
+                                    "column": 24
+                                },
+                                "end": {
+                                    "line": 1,
+                                    "column": 30
+                                }
+                            },
+                            "range": [
+                                24,
+                                30
+                            ],
+                            "typeParameters": null,
+                            "id": {
+                                "type": "Identifier",
+                                "start": 24,
+                                "end": 30,
+                                "loc": {
+                                    "start": {
+                                        "line": 1,
+                                        "column": 24
+                                    },
+                                    "end": {
+                                        "line": 1,
+                                        "column": 30
+                                    },
+                                    "identifierName": "MyType"
+                                },
+                                "range": [
+                                    24,
+                                    30
+                                ],
+                                "name": "MyType",
+                                "_babelType": "Identifier"
+                            },
+                            "_babelType": "GenericTypeAnnotation"
+                        },
+                        "_babelType": "TypeAnnotation"
+                    },
+                    "_babelType": "ObjectPattern"
+                }
+            ],
+            "body": {
+                "type": "BlockStatement",
+                "start": 32,
+                "end": 34,
+                "loc": {
+                    "start": {
+                        "line": 1,
+                        "column": 32
+                    },
+                    "end": {
+                        "line": 1,
+                        "column": 34
+                    }
+                },
+                "range": [
+                    32,
+                    34
+                ],
+                "body": [],
+                "_babelType": "BlockStatement"
+            },
+            "_babelType": "FunctionDeclaration"
+        }
+    ]
+});
+
diff --git a/tests/lib/ast-utils.js b/tests/lib/ast-utils.js
index 65600f353..538b941cd 100644
--- a/tests/lib/ast-utils.js
+++ b/tests/lib/ast-utils.js
@@ -1198,4 +1198,22 @@ describe("ast-utils", () => {
             });
         });
     });
+
+    describe("equalTokens", () => {
+        it("should return true if tokens are equal", () => {
+            const code = "a=0;a=0;";
+            const ast = espree.parse(code, ESPREE_CONFIG);
+            const sourceCode = new SourceCode(code, ast);
+
+            assert.strictEqual(astUtils.equalTokens(ast.body[0], ast.body[1], sourceCode), true);
+        });
+
+        it("should return false if tokens are not equal", () => {
+            const code = "a=0;a=1;";
+            const ast = espree.parse(code, ESPREE_CONFIG);
+            const sourceCode = new SourceCode(code, ast);
+
+            assert.strictEqual(astUtils.equalTokens(ast.body[0], ast.body[1], sourceCode), false);
+        });
+    });
 });
diff --git a/tests/lib/config/config-validator.js b/tests/lib/config/config-validator.js
index 5f3d65278..5d6cf8cc0 100644
--- a/tests/lib/config/config-validator.js
+++ b/tests/lib/config/config-validator.js
@@ -90,6 +90,15 @@ const mockRequiredOptionsRule = {
 
 describe("Validator", () => {
 
+    /**
+     * Gets a loaded rule given a rule ID
+     * @param {string} ruleId The ID of the rule
+     * @returns {{create: Function}} The loaded rule
+     */
+    function ruleMapper(ruleId) {
+        return linter.getRules().get(ruleId);
+    }
+
     beforeEach(() => {
         linter.defineRule("mock-rule", mockRule);
         linter.defineRule("mock-required-options-rule", mockRequiredOptionsRule);
@@ -98,7 +107,7 @@ describe("Validator", () => {
     describe("validate", () => {
 
         it("should do nothing with an empty config", () => {
-            const fn = validator.validate.bind(null, {}, "tests", linter.rules, linter.environments);
+            const fn = validator.validate.bind(null, {}, "tests", ruleMapper, linter.environments);
 
             assert.doesNotThrow(fn);
         });
@@ -118,7 +127,7 @@ describe("Validator", () => {
                     rules: {}
                 },
                 "tests",
-                linter.rules,
+                ruleMapper,
                 linter.environments
             );
 
@@ -132,7 +141,7 @@ describe("Validator", () => {
                     foo: true
                 },
                 "tests",
-                linter.rules,
+                ruleMapper,
                 linter.environments
             );
 
@@ -141,13 +150,13 @@ describe("Validator", () => {
 
         describe("root", () => {
             it("should throw with a string value", () => {
-                const fn = validator.validate.bind(null, { root: "true" }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { root: "true" }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"root\" is the wrong type (expected boolean but got `\"true\"`).");
             });
 
             it("should throw with a numeric value", () => {
-                const fn = validator.validate.bind(null, { root: 0 }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { root: 0 }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"root\" is the wrong type (expected boolean but got `0`).");
             });
@@ -155,13 +164,13 @@ describe("Validator", () => {
 
         describe("globals", () => {
             it("should throw with a string value", () => {
-                const fn = validator.validate.bind(null, { globals: "jQuery" }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { globals: "jQuery" }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"globals\" is the wrong type (expected object but got `\"jQuery\"`).");
             });
 
             it("should throw with an array value", () => {
-                const fn = validator.validate.bind(null, { globals: ["jQuery"] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { globals: ["jQuery"] }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"globals\" is the wrong type (expected object but got `[\"jQuery\"]`).");
             });
@@ -169,7 +178,7 @@ describe("Validator", () => {
 
         describe("parser", () => {
             it("should not throw with a null value", () => {
-                const fn = validator.validate.bind(null, { parser: null }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { parser: null }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
@@ -178,31 +187,31 @@ describe("Validator", () => {
         describe("env", () => {
 
             it("should throw with an array environment", () => {
-                const fn = validator.validate.bind(null, { env: [] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { env: [] }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"env\" is the wrong type (expected object but got `[]`).");
             });
 
             it("should throw with a primitive environment", () => {
-                const fn = validator.validate.bind(null, { env: 1 }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { env: 1 }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"env\" is the wrong type (expected object but got `1`).");
             });
 
             it("should catch invalid environments", () => {
-                const fn = validator.validate.bind(null, { env: { browser: true, invalid: true } }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { env: { browser: true, invalid: true } }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Environment key \"invalid\" is unknown\n");
             });
 
             it("should catch disabled invalid environments", () => {
-                const fn = validator.validate.bind(null, { env: { browser: true, invalid: false } }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { env: { browser: true, invalid: false } }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Environment key \"invalid\" is unknown\n");
             });
 
             it("should do nothing with an undefined environment", () => {
-                const fn = validator.validate.bind(null, {}, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, {}, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
@@ -211,13 +220,13 @@ describe("Validator", () => {
 
         describe("plugins", () => {
             it("should not throw with an empty array", () => {
-                const fn = validator.validate.bind(null, { plugins: [] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { plugins: [] }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should throw with a string", () => {
-                const fn = validator.validate.bind(null, { plugins: "react" }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { plugins: "react" }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"plugins\" is the wrong type (expected array but got `\"react\"`).");
             });
@@ -225,13 +234,13 @@ describe("Validator", () => {
 
         describe("settings", () => {
             it("should not throw with an empty object", () => {
-                const fn = validator.validate.bind(null, { settings: {} }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { settings: {} }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should throw with an array", () => {
-                const fn = validator.validate.bind(null, { settings: ["foo"] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { settings: ["foo"] }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"settings\" is the wrong type (expected object but got `[\"foo\"]`).");
             });
@@ -239,19 +248,19 @@ describe("Validator", () => {
 
         describe("extends", () => {
             it("should not throw with an empty array", () => {
-                const fn = validator.validate.bind(null, { extends: [] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { extends: [] }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should not throw with a string", () => {
-                const fn = validator.validate.bind(null, { extends: "react" }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { extends: "react" }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should throw with an object", () => {
-                const fn = validator.validate.bind(null, { extends: {} }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { extends: {} }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"extends\" is the wrong type (expected string/array but got `{}`).");
             });
@@ -259,13 +268,13 @@ describe("Validator", () => {
 
         describe("parserOptions", () => {
             it("should not throw with an empty object", () => {
-                const fn = validator.validate.bind(null, { parserOptions: {} }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { parserOptions: {} }, null, ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should throw with an array", () => {
-                const fn = validator.validate.bind(null, { parserOptions: ["foo"] }, null, linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { parserOptions: ["foo"] }, null, ruleMapper, linter.environments);
 
                 assert.throws(fn, "Property \"parserOptions\" is the wrong type (expected object but got `[\"foo\"]`).");
             });
@@ -274,67 +283,67 @@ describe("Validator", () => {
         describe("rules", () => {
 
             it("should do nothing with an empty rules object", () => {
-                const fn = validator.validate.bind(null, { rules: {} }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: {} }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config with rules", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": [2, "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": [2, "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is off", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["off", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["off", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with an invalid config when severity is off", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-required-options-rule": "off" } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-required-options-rule": "off" } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with an invalid config when severity is an array with 'off'", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-required-options-rule": ["off"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-required-options-rule": ["off"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is warn", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["warn", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["warn", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is error", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["error", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["error", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is Off", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Off", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Off", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is Warn", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Warn", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Warn", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should do nothing with a valid config when severity is Error", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Error", "second"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": ["Error", "second"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should catch invalid rule options", () => {
-                const fn = validator.validate.bind(null, { rules: { "mock-rule": [3, "third"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-rule": [3, "third"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n");
             });
@@ -342,7 +351,7 @@ describe("Validator", () => {
             it("should allow for rules with no options", () => {
                 linter.defineRule("mock-no-options-rule", mockNoOptionsRule);
 
-                const fn = validator.validate.bind(null, { rules: { "mock-no-options-rule": 2 } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-no-options-rule": 2 } }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
@@ -350,7 +359,7 @@ describe("Validator", () => {
             it("should not allow options for rules with no options", () => {
                 linter.defineRule("mock-no-options-rule", mockNoOptionsRule);
 
-                const fn = validator.validate.bind(null, { rules: { "mock-no-options-rule": [2, "extra"] } }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { rules: { "mock-no-options-rule": [2, "extra"] } }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-no-options-rule\" is invalid:\n\tValue [\"extra\"] should NOT have more than 0 items.\n");
             });
@@ -358,43 +367,43 @@ describe("Validator", () => {
 
         describe("overrides", () => {
             it("should not throw with an empty overrides array", () => {
-                const fn = validator.validate.bind(null, { overrides: [] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [] }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should not throw with a valid overrides array", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ files: "*", rules: {} }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ files: "*", rules: {} }] }, "tests", ruleMapper, linter.environments);
 
                 assert.doesNotThrow(fn);
             });
 
             it("should throw if override does not specify files", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ rules: {} }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ rules: {} }] }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "ESLint configuration in tests is invalid:\n\t- \"overrides[0]\" should have required property 'files'. Value: {\"rules\":{}}.\n");
             });
 
             it("should throw if override has an empty files array", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ files: [] }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ files: [] }] }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "ESLint configuration in tests is invalid:\n\t- Property \"overrides[0].files\" is the wrong type (expected string but got `[]`).\n\t- \"overrides[0].files\" should NOT have less than 1 items. Value: [].\n\t- \"overrides[0].files\" should match exactly one schema in oneOf. Value: [].\n");
             });
 
             it("should throw if override has nested overrides", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ files: "*", overrides: [{ files: "*", rules: {} }] }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ files: "*", overrides: [{ files: "*", rules: {} }] }] }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "ESLint configuration in tests is invalid:\n\t- Unexpected top-level property \"overrides[0].overrides\".\n");
             });
 
             it("should throw if override extends", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ files: "*", extends: "eslint-recommended" }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ files: "*", extends: "eslint-recommended" }] }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "ESLint configuration in tests is invalid:\n\t- Unexpected top-level property \"overrides[0].extends\".\n");
             });
 
             it("should throw if override tries to set root", () => {
-                const fn = validator.validate.bind(null, { overrides: [{ files: "*", root: "true" }] }, "tests", linter.rules, linter.environments);
+                const fn = validator.validate.bind(null, { overrides: [{ files: "*", root: "true" }] }, "tests", ruleMapper, linter.environments);
 
                 assert.throws(fn, "ESLint configuration in tests is invalid:\n\t- Unexpected top-level property \"overrides[0].root\".\n");
             });
@@ -405,12 +414,12 @@ describe("Validator", () => {
     describe("getRuleOptionsSchema", () => {
 
         it("should return null for a missing rule", () => {
-            assert.strictEqual(validator.getRuleOptionsSchema("non-existent-rule", linter.rules), null);
+            assert.strictEqual(validator.getRuleOptionsSchema(linter.rules.get("non-existent-rule")), null);
         });
 
         it("should not modify object schema", () => {
             linter.defineRule("mock-object-rule", mockObjectRule);
-            assert.deepStrictEqual(validator.getRuleOptionsSchema("mock-object-rule", linter.rules), {
+            assert.deepStrictEqual(validator.getRuleOptionsSchema(linter.rules.get("mock-object-rule")), {
                 enum: ["first", "second"]
             });
         });
@@ -420,43 +429,43 @@ describe("Validator", () => {
     describe("validateRuleOptions", () => {
 
         it("should throw for incorrect warning level number", () => {
-            const fn = validator.validateRuleOptions.bind(null, "mock-rule", 3, "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("mock-rule"), "mock-rule", 3, "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n");
         });
 
         it("should throw for incorrect warning level string", () => {
-            const fn = validator.validateRuleOptions.bind(null, "mock-rule", "booya", "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("mock-rule"), "mock-rule", "booya", "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '\"booya\"').\n");
         });
 
         it("should throw for invalid-type warning level", () => {
-            const fn = validator.validateRuleOptions.bind(null, "mock-rule", [["error"]], "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("mock-rule"), "mock-rule", [["error"]], "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '[ \"error\" ]').\n");
         });
 
         it("should only check warning level for nonexistent rules", () => {
-            const fn = validator.validateRuleOptions.bind(null, "non-existent-rule", [3, "foobar"], "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("non-existent-rule"), "non-existent-rule", [3, "foobar"], "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"non-existent-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n");
         });
 
         it("should only check warning level for plugin rules", () => {
-            const fn = validator.validateRuleOptions.bind(null, "plugin/rule", 3, "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("plugin/rule"), "plugin/rule", 3, "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"plugin/rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n");
         });
 
         it("should throw for incorrect configuration values", () => {
-            const fn = validator.validateRuleOptions.bind(null, "mock-rule", [2, "frist"], "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("mock-rule"), "mock-rule", [2, "frist"], "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue \"frist\" should be equal to one of the allowed values.\n");
         });
 
         it("should throw for too many configuration values", () => {
-            const fn = validator.validateRuleOptions.bind(null, "mock-rule", [2, "first", "second"], "tests", linter.rules);
+            const fn = validator.validateRuleOptions.bind(null, linter.rules.get("mock-rule"), "mock-rule", [2, "first", "second"], "tests");
 
             assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue [\"first\",\"second\"] should NOT have more than 1 items.\n");
         });
diff --git a/tests/lib/rules/object-curly-newline.js b/tests/lib/rules/object-curly-newline.js
index ce8f87165..cdbf75750 100644
--- a/tests/lib/rules/object-curly-newline.js
+++ b/tests/lib/rules/object-curly-newline.js
@@ -9,7 +9,8 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const rule = require("../../../lib/rules/object-curly-newline"),
+const resolvePath = require("path").resolve,
+    rule = require("../../../lib/rules/object-curly-newline"),
     RuleTester = require("../../../lib/testers/rule-tester");
 
 //------------------------------------------------------------------------------
@@ -64,6 +65,26 @@ ruleTester.run("object-curly-newline", rule, {
             ].join("\n"),
             options: ["always"]
         },
+        {
+            code: [
+                "function foo({",
+                " a,",
+                " b",
+                "} : MyType) {}"
+            ].join("\n"),
+            options: ["always"],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-multiline")
+        },
+        {
+            code: [
+                "function foo({",
+                " a,",
+                " b",
+                "} : { a : string, b : string }) {}"
+            ].join("\n"),
+            options: ["always"],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-multiline-type-literal")
+        },
 
         // "never" -------------------------------------------------------------
         {
@@ -99,6 +120,16 @@ ruleTester.run("object-curly-newline", rule, {
             ].join("\n"),
             options: ["never"]
         },
+        {
+            code: "function foo({ a, b } : MyType) {}",
+            options: ["never"],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-singleline")
+        },
+        {
+            code: "function foo({ a, b } : { a : string, b : string }) {}",
+            options: ["never"],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-singleline-type-literal")
+        },
 
         // "multiline" ---------------------------------------------------------
         {
@@ -486,6 +517,34 @@ ruleTester.run("object-curly-newline", rule, {
                 { line: 3, column: 2, message: "Expected a line break before this closing brace." }
             ]
         },
+        {
+            code: "function foo({ a, b } : MyType) {}",
+            output: [
+                "function foo({",
+                " a, b ",
+                "} : MyType) {}"
+            ].join("\n"),
+            options: ["always"],
+            errors: [
+                { line: 1, column: 14, message: "Expected a line break after this opening brace." },
+                { line: 1, column: 21, message: "Expected a line break before this closing brace." }
+            ],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-singleline")
+        },
+        {
+            code: "function foo({ a, b } : { a : string, b : string }) {}",
+            output: [
+                "function foo({",
+                " a, b ",
+                "} : { a : string, b : string }) {}"
+            ].join("\n"),
+            options: ["always"],
+            errors: [
+                { line: 1, column: 14, message: "Expected a line break after this opening brace." },
+                { line: 1, column: 21, message: "Expected a line break before this closing brace." }
+            ],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-singleline-type-literal")
+        },
 
         // "never" ------------------------------------------------------------
         {
@@ -568,6 +627,42 @@ ruleTester.run("object-curly-newline", rule, {
                 { line: 5, column: 1, message: "Unexpected line break before this closing brace." }
             ]
         },
+        {
+            code: [
+                "function foo({",
+                " a,",
+                " b",
+                "} : MyType) {}"
+            ].join("\n"),
+            output: [
+                "function foo({a,",
+                " b} : MyType) {}"
+            ].join("\n"),
+            options: ["never"],
+            errors: [
+                { line: 1, column: 14, message: "Unexpected line break after this opening brace." },
+                { line: 4, column: 1, message: "Unexpected line break before this closing brace." }
+            ],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-multiline")
+        },
+        {
+            code: [
+                "function foo({",
+                " a,",
+                " b",
+                "} : { a : string, b : string }) {}"
+            ].join("\n"),
+            output: [
+                "function foo({a,",
+                " b} : { a : string, b : string }) {}"
+            ].join("\n"),
+            options: ["never"],
+            errors: [
+                { line: 1, column: 14, message: "Unexpected line break after this opening brace." },
+                { line: 4, column: 1, message: "Unexpected line break before this closing brace." }
+            ],
+            parser: resolvePath(__dirname, "../../fixtures/parsers/object-curly-newline/flow-stub-parser-multiline-type-literal")
+        },
 
         // "multiline" ---------------------------------------------------------
         {
diff --git a/tests/lib/rules/semi-style.js b/tests/lib/rules/semi-style.js
index 43968facf..8b0834af3 100644
--- a/tests/lib/rules/semi-style.js
+++ b/tests/lib/rules/semi-style.js
@@ -27,18 +27,103 @@ ruleTester.run("semi-style", rule, {
         "for(a;\nb;\nc);",
         "for((a\n);\n(b\n);\n(c));",
         "if(a)foo;\nbar",
+        { code: ";", options: ["last"] },
         { code: ";foo;bar;baz;", options: ["last"] },
         { code: "foo;\nbar;", options: ["last"] },
         { code: "for(a;b;c);", options: ["last"] },
         { code: "for(a;\nb;\nc);", options: ["last"] },
         { code: "for((a\n);\n(b\n);\n(c));", options: ["last"] },
         { code: "if(a)foo;\nbar", options: ["last"] },
+        { code: ";", options: ["first"] },
         { code: ";foo;bar;baz;", options: ["first"] },
         { code: "foo\n;bar;", options: ["first"] },
         { code: "for(a;b;c);", options: ["first"] },
         { code: "for(a;\nb;\nc);", options: ["first"] },
         { code: "for((a\n);\n(b\n);\n(c));", options: ["first"] },
-        { code: "if(a)foo\n;bar", options: ["first"] }
+
+        // edge cases
+        {
+            code: `
+                {
+                    ;
+                }
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                while (a)
+                    ;
+                foo
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                do
+                    ;
+                while (a)
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                do
+                    foo;
+                while (a)
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                if (a)
+                    foo;
+                else
+                    bar
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                if (a)
+                    foo
+                ;bar
+            `,
+            options: ["first"]
+        },
+        {
+            code: `
+                {
+                    ;
+                }
+            `,
+            options: ["last"]
+        },
+        {
+            code: `
+                switch (a) {
+                    case 1:
+                        ;foo
+                }
+            `,
+            options: ["last"]
+        },
+        {
+            code: `
+                while (a)
+                    ;
+                foo
+            `,
+            options: ["last"]
+        },
+        {
+            code: `
+                do
+                    ;
+                while (a)
+            `,
+            options: ["last"]
+        }
     ],
     invalid: [
         {