Repository: eslint/eslint
Pull request #9629 (2017-11-15 23:16:56)

New: Adds implicit-arrow-linebreak rule (refs #9510)
**What is the purpose of this pull request? (put an "X" next to item)**
- [X] adds a new rule 

**What changes did you make? (Give an overview)**
Introduces a new rule enforcing the location of arrow function bodies with implicit returns. Also adds tests and docs.
Refs: #9510 & #6067 

**Is there anything you'd like reviewers to focus on?**
I think this rule gets a little less intuitive when it comes to function bodies surrounded by parentheses. 

I would like to make sure that this rule never warns on a case where parentheses are used to surround a multiline body, like this: 
```js
(foo) => (
  bar
);
```
However, currently, it does warn on cases like: 
```js
// incorrect code for "beside" option
(foo) => 
  (bar);

// incorrect code for "below" option
(foo) => (bar)
```
I'm not sure if that's the best way to handle this 🤔

cc. @ljharb, @not-an-aardvark  
more discussion: https://github.com/eslint/eslint/pull/9623.

kaicataldo: This needs a champion as well as support from one more team member.

Something to note is that this rule is incompatible with [`arrow-spacing`](https://eslint.org/docs/rules/arrow-spacing) when this rule is configured with `"below"` and `arrow-spacing` is configured with `{ after: false }`. Not an issue since there aren't any cases where they don't overlap.
sharmilajesupaul: @kaicataldo how do I find someone to champion this rule? Should I make an issue with the rule proposal?
kaicataldo: @sharmilajesupaul No need to do anything! Thanks for a great PR.

@eslint/eslint-team Looks like we have support from three team members and just need someone to step up to champion.
platinumazure: I'll champion this. Marking as accepted.
ljharb: "concise" refers to concise object methods; i'd prefer "implicit".
platinumazure: I've heard it both ways (and I use "shorthand" for those object methods). I'm not going to insist strongly on a name change, but I do think it would help.
not-an-aardvark: `brace-style` already covers arrow functions with block statements, so I don't think `arrow-linebreak` should cover them too.
platinumazure: > `brace-style` already covers arrow functions with block statements, so I don't think `arrow-linebreak` should cover them too.

Agreed full stop. However, the rule name and documentation could confuse a new user into thinking that the rule should cover that scenario (until you read some of the examples, anyway). So it makes sense for a See Also section to reference `brace-style` for sure. I also think it wouldn't hurt to change the name of the rule to be more precise about exactly what it covers.
sharmilajesupaul: Made some improvements:
- changes rule name from `arrow-linebreak` -> `implicit-arrow-linebreak`
- adds doc section for [`brace-style`](https://eslint.org/docs/rules/brace-style) rule ([here](https://github.com/eslint/eslint/pull/9629/files#diff-c0e856a4dcbd2877a24b5619228900adR9))
- warns on multiline expressions wrapped in parens (see: https://github.com/eslint/eslint/pull/9629#discussion_r151844896)
- fixes the autofix for expressions wrapped in multiple sets of parentheses i.e. `() => ((foo));` ([here](https://github.com/eslint/eslint/pull/9629/files#diff-6c1dbab61fffc096eef30d3fdaf8219cR60))
- improves variable names, adds new tests, and general clean up

ptal  @not-an-aardvark, @platinumazure, & @ljharb, thanks!

Patch:
diff --git a/README.md b/README.md
index 3b7d6aca4..5a23d6295 100644
--- a/README.md
+++ b/README.md
@@ -225,7 +225,7 @@ In all cases, make sure your plugins' peerDependencies have been installed as we
 
 ### Does ESLint support JSX?
 
-Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring).). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics.
+Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring)). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics.
 
 ### What about ECMAScript 6 support?
 
diff --git a/conf/environments.js b/conf/environments.js
index a11f2963d..44f2e0dee 100644
--- a/conf/environments.js
+++ b/conf/environments.js
@@ -17,10 +17,126 @@ const globals = require("globals");
 module.exports = {
     builtin: globals.es5,
     browser: {
-        globals: globals.browser
+
+        /*
+         * For backward compatibility.
+         * Remove those on the next major release.
+         */
+        globals: Object.assign(
+            {
+                AutocompleteErrorEvent: false,
+                CDATASection: false,
+                ClientRect: false,
+                ClientRectList: false,
+                CSSAnimation: false,
+                CSSTransition: false,
+                CSSUnknownRule: false,
+                CSSViewportRule: false,
+                Debug: false,
+                DocumentTimeline: false,
+                DOMSettableTokenList: false,
+                ElementTimeControl: false,
+                FederatedCredential: false,
+                FileError: false,
+                HTMLAppletElement: false,
+                HTMLBlockquoteElement: false,
+                HTMLIsIndexElement: false,
+                HTMLKeygenElement: false,
+                HTMLLayerElement: false,
+                IDBEnvironment: false,
+                InputMethodContext: false,
+                MediaKeyError: false,
+                MediaKeyEvent: false,
+                MediaKeys: false,
+                opera: false,
+                PasswordCredential: false,
+                ReadableByteStream: false,
+                SharedKeyframeList: false,
+                showModalDialog: false,
+                SiteBoundCredential: false,
+                SVGAltGlyphDefElement: false,
+                SVGAltGlyphElement: false,
+                SVGAltGlyphItemElement: false,
+                SVGAnimateColorElement: false,
+                SVGAnimatedPathData: false,
+                SVGAnimatedPoints: false,
+                SVGColor: false,
+                SVGColorProfileElement: false,
+                SVGColorProfileRule: false,
+                SVGCSSRule: false,
+                SVGCursorElement: false,
+                SVGDocument: false,
+                SVGElementInstance: false,
+                SVGElementInstanceList: false,
+                SVGEvent: false,
+                SVGExternalResourcesRequired: false,
+                SVGFilterPrimitiveStandardAttributes: false,
+                SVGFitToViewBox: false,
+                SVGFontElement: false,
+                SVGFontFaceElement: false,
+                SVGFontFaceFormatElement: false,
+                SVGFontFaceNameElement: false,
+                SVGFontFaceSrcElement: false,
+                SVGFontFaceUriElement: false,
+                SVGGlyphElement: false,
+                SVGGlyphRefElement: false,
+                SVGHKernElement: false,
+                SVGICCColor: false,
+                SVGLangSpace: false,
+                SVGLocatable: false,
+                SVGMissingGlyphElement: false,
+                SVGPaint: false,
+                SVGPathSeg: false,
+                SVGPathSegArcAbs: false,
+                SVGPathSegArcRel: false,
+                SVGPathSegClosePath: false,
+                SVGPathSegCurvetoCubicAbs: false,
+                SVGPathSegCurvetoCubicRel: false,
+                SVGPathSegCurvetoCubicSmoothAbs: false,
+                SVGPathSegCurvetoCubicSmoothRel: false,
+                SVGPathSegCurvetoQuadraticAbs: false,
+                SVGPathSegCurvetoQuadraticRel: false,
+                SVGPathSegCurvetoQuadraticSmoothAbs: false,
+                SVGPathSegCurvetoQuadraticSmoothRel: false,
+                SVGPathSegLinetoAbs: false,
+                SVGPathSegLinetoHorizontalAbs: false,
+                SVGPathSegLinetoHorizontalRel: false,
+                SVGPathSegLinetoRel: false,
+                SVGPathSegLinetoVerticalAbs: false,
+                SVGPathSegLinetoVerticalRel: false,
+                SVGPathSegList: false,
+                SVGPathSegMovetoAbs: false,
+                SVGPathSegMovetoRel: false,
+                SVGRenderingIntent: false,
+                SVGStylable: false,
+                SVGTests: false,
+                SVGTransformable: false,
+                SVGTRefElement: false,
+                SVGURIReference: false,
+                SVGViewSpec: false,
+                SVGVKernElement: false,
+                SVGZoomAndPan: false,
+                SVGZoomEvent: false,
+                TimeEvent: false,
+                XDomainRequest: false,
+                XMLHttpRequestProgressEvent: false,
+                XPathException: false,
+                XPathNamespace: false,
+                XPathNSResolver: false
+            },
+            globals.browser
+        )
     },
     node: {
-        globals: globals.node,
+
+        /*
+         * For backward compatibility.
+         * Remove those on the next major release.
+         */
+        globals: Object.assign(
+            { arguments: false, GLOBAL: false, root: false },
+            globals.node
+        ),
         parserOptions: {
             ecmaFeatures: {
                 globalReturn: true
@@ -51,7 +167,15 @@ module.exports = {
         globals: globals.jasmine
     },
     jest: {
-        globals: globals.jest
+
+        /*
+         * For backward compatibility.
+         * Remove those on the next major release.
+         */
+        globals: Object.assign(
+            { check: false, gen: false },
+            globals.jest
+        )
     },
     phantomjs: {
         globals: globals.phantomjs
@@ -96,7 +220,7 @@ module.exports = {
         globals: globals.webextensions
     },
     es6: {
-        globals: globals.es6,
+        globals: globals.es2015,
         parserOptions: {
             ecmaVersion: 6
         }
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 8421b9d38..0acee234a 100755
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -53,6 +53,7 @@ module.exports = {
         "id-blacklist": "off",
         "id-length": "off",
         "id-match": "off",
+        "implicit-arrow-linebreak": "off",
         indent: "off",
         "indent-legacy": "off",
         "init-declarations": "off",
diff --git a/docs/rules/implicit-arrow-linebreak.md b/docs/rules/implicit-arrow-linebreak.md
new file mode 100644
index 000000000..a1a235535
--- /dev/null
+++ b/docs/rules/implicit-arrow-linebreak.md
@@ -0,0 +1,101 @@
+# Enforce the location of arrow function bodies with implicit returns (implicit-arrow-linebreak)
+
+An arrow function body can contain an implicit return as an expression instead of a block body. It can be useful to enforce a consistent location for the implicitly returned expression.
+
+## Rule Details
+
+This rule aims to enforce a consistent location for an arrow function containing an implicit return.
+
+See Also:
+
+- [`brace-style`](https://eslint.org/docs/rules/brace-style) which enforces this behavior for arrow functions with block bodies.
+
+### Options
+
+This rule accepts a string option:
+
+- `"beside"` (default) disallows a newline before an arrow function body.
+- `"below"` requires a newline before an arrow function body.
+
+Examples of **incorrect** code for this rule with the default `"beside"` option:
+
+```js
+/* eslint implicit-arrow-linebreak: ["error", "beside"] */
+
+(foo) =>
+  bar;
+
+(foo) =>
+  (bar);
+
+(foo) =>
+  bar =>
+    baz;
+
+(foo) =>
+(
+  bar()
+);
+```
+
+Examples of **correct** code for this rule with the default `"beside"` option:
+
+```js
+/* eslint implicit-arrow-linebreak: ["error", "beside"] */
+
+(foo) => bar;
+
+(foo) => (bar);
+
+(foo) => bar => baz;
+
+(foo) => (
+  bar()
+);
+
+// functions with block bodies allowed with this rule using any style
+// to enforce a consistent location for this case, see the rule: `brace-style`
+(foo) => {
+  return bar();
+}
+
+(foo) =>
+{
+  return bar();
+}
+```
+
+Examples of **incorrect** code for this rule with the `"below"` option:
+
+```js
+/* eslint implicit-arrow-linebreak: ["error", "below"] */
+
+(foo) => bar;
+
+(foo) => (bar);
+
+(foo) => bar => baz;
+```
+
+Examples of **correct** code for this rule with the `"below"` option:
+
+```js
+/* eslint implicit-arrow-linebreak: ["error", "below"] */
+
+
+(foo) =>
+  bar;
+
+(foo) =>
+  (bar);
+
+(foo) =>
+  bar =>
+    baz;
+```
+
+## When Not To Use It
+
+If you're not concerned about consistent locations of implicitly returned arrow function expressions, you should not turn on this rule.
+
+You can also disable this rule if you are using the `"always"` option for the [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style), since this will disable the use of implicit returns in arrow functions.
diff --git a/docs/user-guide/migrating-from-jscs.md b/docs/user-guide/migrating-from-jscs.md
index 41d55aec0..c5ac5f235 100644
--- a/docs/user-guide/migrating-from-jscs.md
+++ b/docs/user-guide/migrating-from-jscs.md
@@ -100,7 +100,7 @@ Both JSCS and ESLint use comments inside of files to disable rules around certai
 | Enable one rule | `// jscs:enable ruleName` or `/* jscs:enable ruleName */` | `/* eslint-enable rule-name */` |
 | Disable multiple rules | `// jscs:disable ruleName1, ruleName2` or `/* jscs:disable ruleName1, ruleName2 */` | `/* eslint-disable rule-name1, rule-name2 */` |
 | Enable multiple rules | `// jscs:enable ruleName1, ruleName2` or `/* jscs:enable ruleName1, ruleName2 */` | `/* eslint-enable rule-name1, rule-name2 */` |
-| Disable one rule on single line | `// jscs:ignore ruleName` | `/* eslint-disable-line rule-name */` |
+| Disable one rule on single line | `// jscs:ignore ruleName` | `// eslint-disable-line rule-name` |
 
 ## Command Line Options
 
diff --git a/lib/formatters/checkstyle.js b/lib/formatters/checkstyle.js
index c80787193..720e831a3 100644
--- a/lib/formatters/checkstyle.js
+++ b/lib/formatters/checkstyle.js
@@ -32,7 +32,7 @@ module.exports = function(results) {
 
     let output = "";
 
-    output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
+    output += "<?xml version=\"1.1\" encoding=\"utf-8\"?>";
     output += "<checkstyle version=\"4.3\">";
 
     results.forEach(result => {
diff --git a/lib/formatters/jslint-xml.js b/lib/formatters/jslint-xml.js
index 14743430d..e152d8bdd 100644
--- a/lib/formatters/jslint-xml.js
+++ b/lib/formatters/jslint-xml.js
@@ -14,7 +14,7 @@ module.exports = function(results) {
 
     let output = "";
 
-    output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
+    output += "<?xml version=\"1.1\" encoding=\"utf-8\"?>";
     output += "<jslint>";
 
     results.forEach(result => {
diff --git a/lib/formatters/junit.js b/lib/formatters/junit.js
index 77d548f38..ca666bb14 100644
--- a/lib/formatters/junit.js
+++ b/lib/formatters/junit.js
@@ -32,7 +32,7 @@ module.exports = function(results) {
 
     let output = "";
 
-    output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+    output += "<?xml version=\"1.1\" encoding=\"utf-8\"?>\n";
     output += "<testsuites>\n";
 
     results.forEach(result => {
diff --git a/lib/rules/implicit-arrow-linebreak.js b/lib/rules/implicit-arrow-linebreak.js
new file mode 100644
index 000000000..b8802f4de
--- /dev/null
+++ b/lib/rules/implicit-arrow-linebreak.js
@@ -0,0 +1,86 @@
+/**
+ * @fileoverview enforce the location of arrow function bodies
+ * @author Sharmila Jesupaul
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+module.exports = {
+    meta: {
+        docs: {
+            description: "enforce the location of arrow function bodies",
+            category: "Stylistic Issues",
+            recommended: false
+        },
+        fixable: "whitespace",
+        schema: [
+            {
+                enum: ["beside", "below"]
+            }
+        ]
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+
+        //----------------------------------------------------------------------
+        // Helpers
+        //----------------------------------------------------------------------
+        /**
+         * Gets the applicable preference for a particular keyword
+         * @returns {string} The applicable option for the keyword, e.g. 'beside'
+         */
+        function getOption() {
+            return context.options[0] || "beside";
+        }
+
+        /**
+         * Validates the location of an arrow function body
+         * @param {ASTNode} node The arrow function body
+         * @param {string} keywordName The applicable keyword name for the arrow function body
+         * @returns {void}
+         */
+        function validateExpression(node) {
+            const option = getOption();
+
+            let tokenBefore = sourceCode.getTokenBefore(node.body);
+            const hasParens = tokenBefore.value === "(";
+
+            if (node.type === "BlockStatement") {
+                return;
+            }
+
+            let fixerTarget = node.body;
+
+            if (hasParens) {
+
+                // Gets the first token before the function body that is not an open paren
+                tokenBefore = sourceCode.getTokenBefore(node.body, token => token.value !== "(");
+                fixerTarget = sourceCode.getTokenAfter(tokenBefore);
+            }
+
+            if (tokenBefore.loc.end.line === fixerTarget.loc.start.line && option === "below") {
+                context.report({
+                    node: fixerTarget,
+                    message: "Expected a linebreak before this expression.",
+                    fix: fixer => fixer.insertTextBefore(fixerTarget, "\n")
+                });
+            } else if (tokenBefore.loc.end.line !== fixerTarget.loc.start.line && option === "beside") {
+                context.report({
+                    node: fixerTarget,
+                    message: "Expected no linebreak before this expression.",
+                    fix: fixer => fixer.replaceTextRange([tokenBefore.range[1], fixerTarget.range[0]], " ")
+                });
+            }
+        }
+
+        //----------------------------------------------------------------------
+        // Public
+        //----------------------------------------------------------------------
+        return {
+            ArrowFunctionExpression: node => validateExpression(node)
+        };
+    }
+};
diff --git a/lib/rules/space-in-parens.js b/lib/rules/space-in-parens.js
index 95b03c3db..67ec5847c 100644
--- a/lib/rules/space-in-parens.js
+++ b/lib/rules/space-in-parens.js
@@ -45,8 +45,7 @@ module.exports = {
         const MISSING_SPACE_MESSAGE = "There must be a space inside this paren.",
             REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.",
             ALWAYS = context.options[0] === "always",
-
-            exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [],
+            exceptionsArrayOptions = (context.options[1] && context.options[1].exceptions) || [],
             options = {};
         let exceptions;
 
diff --git a/package.json b/package.json
index 69f896149..363b80772 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
     "file-entry-cache": "^2.0.0",
     "functional-red-black-tree": "^1.0.1",
     "glob": "^7.1.2",
-    "globals": "^9.17.0",
+    "globals": "^11.0.1",
     "ignore": "^3.3.3",
     "imurmurhash": "^0.1.4",
     "inquirer": "^3.0.6",


Test patch:
diff --git a/tests/lib/formatters/checkstyle.js b/tests/lib/formatters/checkstyle.js
index 0bcece239..d650bec38 100644
--- a/tests/lib/formatters/checkstyle.js
+++ b/tests/lib/formatters/checkstyle.js
@@ -32,14 +32,14 @@ describe("formatter:checkstyle", () => {
         it("should return a string in the format filename: line x, col y, Error - z for errors", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
         });
 
         it("should return a string in the format filename: line x, col y, Warning - z for warnings", () => {
             code[0].messages[0].severity = 1;
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"warning\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"warning\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
         });
     });
 
@@ -58,7 +58,7 @@ describe("formatter:checkstyle", () => {
         it("should return a string in the format filename: line x, col y, Error - z", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"&lt;&gt;&amp;&quot;&apos;.js\"><error line=\"&lt;\" column=\"&gt;\" severity=\"error\" message=\"Unexpected &lt;&gt;&amp;&quot;&apos;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"&lt;&gt;&amp;&quot;&apos;.js\"><error line=\"&lt;\" column=\"&gt;\" severity=\"error\" message=\"Unexpected &lt;&gt;&amp;&quot;&apos;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
         });
     });
 
@@ -77,7 +77,7 @@ describe("formatter:checkstyle", () => {
         it("should return a string in the format filename: line x, col y, Error - z", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file></checkstyle>");
         });
     });
 
@@ -102,7 +102,7 @@ describe("formatter:checkstyle", () => {
         it("should return a string with multiple entries", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /><error line=\"6\" column=\"11\" severity=\"warning\" message=\"Unexpected bar. (bar)\" source=\"eslint.rules.bar\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /><error line=\"6\" column=\"11\" severity=\"warning\" message=\"Unexpected bar. (bar)\" source=\"eslint.rules.bar\" /></file></checkstyle>");
         });
     });
 
@@ -130,7 +130,7 @@ describe("formatter:checkstyle", () => {
         it("should return a string with multiple entries", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file><file name=\"bar.js\"><error line=\"6\" column=\"11\" severity=\"warning\" message=\"Unexpected bar. (bar)\" source=\"eslint.rules.bar\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo. (foo)\" source=\"eslint.rules.foo\" /></file><file name=\"bar.js\"><error line=\"6\" column=\"11\" severity=\"warning\" message=\"Unexpected bar. (bar)\" source=\"eslint.rules.bar\" /></file></checkstyle>");
         });
     });
 
@@ -148,7 +148,7 @@ describe("formatter:checkstyle", () => {
         it("should return a string in the format filename: line x, col y, Error - z for errors", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo.\" source=\"\" /></file></checkstyle>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><checkstyle version=\"4.3\"><file name=\"foo.js\"><error line=\"5\" column=\"10\" severity=\"error\" message=\"Unexpected foo.\" source=\"\" /></file></checkstyle>");
         });
     });
 });
diff --git a/tests/lib/formatters/jslint-xml.js b/tests/lib/formatters/jslint-xml.js
index 52ea4a75b..d860b0406 100644
--- a/tests/lib/formatters/jslint-xml.js
+++ b/tests/lib/formatters/jslint-xml.js
@@ -34,7 +34,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 1 issue in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
         });
     });
 
@@ -55,7 +55,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 1 issue in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
         });
     });
 
@@ -82,7 +82,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 2 issues in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /><issue line=\"6\" char=\"11\" evidence=\"bar\" reason=\"Unexpected bar. (bar)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /><issue line=\"6\" char=\"11\" evidence=\"bar\" reason=\"Unexpected bar. (bar)\" /></file></jslint>");
         });
     });
 
@@ -112,7 +112,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 2 issues in 2 files", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file><file name=\"bar.js\"><issue line=\"6\" char=\"11\" evidence=\"bar\" reason=\"Unexpected bar. (bar)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected foo. (foo)\" /></file><file name=\"bar.js\"><issue line=\"6\" char=\"11\" evidence=\"bar\" reason=\"Unexpected bar. (bar)\" /></file></jslint>");
         });
     });
 
@@ -133,7 +133,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 1 issue in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected &lt;&amp;&quot;&apos;&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924; foo. (foo)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"foo\" reason=\"Unexpected &lt;&amp;&quot;&apos;&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924; foo. (foo)\" /></file></jslint>");
         });
     });
 
@@ -153,7 +153,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 1 issue in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"\" reason=\"Unexpected foo. (foo)\" /></file></jslint>");
         });
     });
 
@@ -170,7 +170,7 @@ describe("formatter:jslint-xml", () => {
         it("should return a string in JSLint XML format with 1 issue in 1 file", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result, "<?xml version=\"1.0\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"\" reason=\"\" /></file></jslint>");
+            assert.strictEqual(result, "<?xml version=\"1.1\" encoding=\"utf-8\"?><jslint><file name=\"foo.js\"><issue line=\"5\" char=\"10\" evidence=\"\" reason=\"\" /></file></jslint>");
         });
     });
 });
diff --git a/tests/lib/formatters/junit.js b/tests/lib/formatters/junit.js
index c6995755d..6d7fa37dc 100644
--- a/tests/lib/formatters/junit.js
+++ b/tests/lib/formatters/junit.js
@@ -25,7 +25,7 @@ describe("formatter:junit", () => {
         it("should not complain about anything", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites></testsuites>");
         });
     });
 
@@ -44,14 +44,14 @@ describe("formatter:junit", () => {
         it("should return a single <testcase> with a message and the line and col number in the body (error)", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></failure></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></failure></testcase></testsuite></testsuites>");
         });
 
         it("should return a single <testcase> with a message and the line and col number in the body (warning)", () => {
             code[0].messages[0].severity = 1;
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite></testsuites>");
         });
     });
 
@@ -70,7 +70,7 @@ describe("formatter:junit", () => {
         it("should return a single <testcase> and an <error>", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><error message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></error></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><error message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></error></testcase></testsuite></testsuites>");
         });
     });
 
@@ -86,7 +86,7 @@ describe("formatter:junit", () => {
         it("should return a single <testcase> and an <error>", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.unknown\"><error message=\"Unexpected foo.\"><![CDATA[line 0, col 0, Error - Unexpected foo.]]></error></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.unknown\"><error message=\"Unexpected foo.\"><![CDATA[line 0, col 0, Error - Unexpected foo.]]></error></testcase></testsuite></testsuites>");
         });
     });
 
@@ -101,7 +101,7 @@ describe("formatter:junit", () => {
         it("should return a single <testcase> and an <error>", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.unknown\"><error message=\"\"><![CDATA[line 0, col 0, Error - ]]></error></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.unknown\"><error message=\"\"><![CDATA[line 0, col 0, Error - ]]></error></testcase></testsuite></testsuites>");
         });
     });
 
@@ -126,7 +126,7 @@ describe("formatter:junit", () => {
         it("should return a multiple <testcase>'s", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"2\" errors=\"2\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></failure></testcase><testcase time=\"0\" name=\"org.eslint.bar\"><failure message=\"Unexpected bar.\"><![CDATA[line 6, col 11, Warning - Unexpected bar. (bar)]]></failure></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"2\" errors=\"2\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Error - Unexpected foo. (foo)]]></failure></testcase><testcase time=\"0\" name=\"org.eslint.bar\"><failure message=\"Unexpected bar.\"><![CDATA[line 6, col 11, Warning - Unexpected bar. (bar)]]></failure></testcase></testsuite></testsuites>");
         });
     });
 
@@ -145,7 +145,7 @@ describe("formatter:junit", () => {
         it("should make them go away", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected &lt;foo&gt;&lt;/foo&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;.\"><![CDATA[line 5, col 10, Warning - Unexpected &lt;foo&gt;&lt;/foo&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;. (foo)]]></failure></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected &lt;foo&gt;&lt;/foo&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;.\"><![CDATA[line 5, col 10, Warning - Unexpected &lt;foo&gt;&lt;/foo&gt;&#8;&#9;&#10;&#12;&#13;&#29275;&#36924;. (foo)]]></failure></testcase></testsuite></testsuites>");
         });
     });
 
@@ -173,7 +173,7 @@ describe("formatter:junit", () => {
         it("should return 2 <testsuite>'s", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"bar.js\"><testcase time=\"0\" name=\"org.eslint.bar\"><failure message=\"Unexpected bar.\"><![CDATA[line 6, col 11, Error - Unexpected bar. (bar)]]></failure></testcase></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"bar.js\"><testcase time=\"0\" name=\"org.eslint.bar\"><failure message=\"Unexpected bar.\"><![CDATA[line 6, col 11, Error - Unexpected bar. (bar)]]></failure></testcase></testsuite></testsuites>");
         });
     });
 
@@ -195,7 +195,7 @@ describe("formatter:junit", () => {
         it("should return 2 <testsuite>", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"0\" name=\"bar.js\"><testcase time=\"0\" name=\"bar.js\" /></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"1\" name=\"foo.js\"><testcase time=\"0\" name=\"org.eslint.foo\"><failure message=\"Unexpected foo.\"><![CDATA[line 5, col 10, Warning - Unexpected foo. (foo)]]></failure></testcase></testsuite><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"0\" name=\"bar.js\"><testcase time=\"0\" name=\"bar.js\" /></testsuite></testsuites>");
         });
     });
 
@@ -208,7 +208,7 @@ describe("formatter:junit", () => {
         it("should print a passing <testcase>", () => {
             const result = formatter(code);
 
-            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"0\" name=\"foo.js\"><testcase time=\"0\" name=\"foo.js\" /></testsuite></testsuites>");
+            assert.strictEqual(result.replace(/\n/g, ""), "<?xml version=\"1.1\" encoding=\"utf-8\"?><testsuites><testsuite package=\"org.eslint\" time=\"0\" tests=\"1\" errors=\"0\" name=\"foo.js\"><testcase time=\"0\" name=\"foo.js\" /></testsuite></testsuites>");
         });
     });
 });
diff --git a/tests/lib/rules/implicit-arrow-linebreak.js b/tests/lib/rules/implicit-arrow-linebreak.js
new file mode 100644
index 000000000..7212e083f
--- /dev/null
+++ b/tests/lib/rules/implicit-arrow-linebreak.js
@@ -0,0 +1,173 @@
+/**
+ * @fileoverview enforce the location of arrow function bodies
+ * @author Sharmila Jesupaul
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/implicit-arrow-linebreak");
+const RuleTester = require("../../../lib/testers/rule-tester");
+
+const EXPECTED_LINEBREAK = { message: "Expected a linebreak before this expression." };
+const UNEXPECTED_LINEBREAK = { message: "Expected no linebreak before this expression." };
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
+
+ruleTester.run("implicit-arrow-linebreak", rule, {
+
+    valid: [
+
+        // always valid
+        `(foo) => {
+            bar
+        }`,
+
+        // 'beside' option
+        "() => bar;",
+        "() => (bar);",
+        "() => bar => baz;",
+        "() => ((((bar))));",
+        `(foo) => (
+            bar
+        )`,
+        {
+            code: "(foo) => bar();",
+            options: ["beside"]
+        },
+
+        // 'below' option
+        {
+            code: `
+                (foo) =>
+                    (
+                        bar
+                    )
+            `,
+            options: ["below"]
+        }, {
+            code: `
+                () =>
+                    ((((bar))));
+            `,
+            options: ["below"]
+        }, {
+            code: `
+                () =>
+                    bar();
+            `,
+            options: ["below"]
+        }, {
+            code: `
+                () =>
+                    (bar);
+            `,
+            options: ["below"]
+        }, {
+            code: `
+                () =>
+                    bar =>
+                        baz;
+            `,
+            options: ["below"]
+        }
+    ],
+
+    invalid: [
+
+        // 'beside' option
+        {
+            code: `
+                (foo) =>
+                    bar();
+            `,
+            output: `
+                (foo) => bar();
+            `,
+            errors: [UNEXPECTED_LINEBREAK]
+        }, {
+            code: `
+                () =>
+                    (bar);
+            `,
+            output: `
+                () => (bar);
+            `,
+            errors: [UNEXPECTED_LINEBREAK]
+        }, {
+            code: `
+                () =>
+                    bar =>
+                        baz;
+            `,
+            output: `
+                () => bar => baz;
+            `,
+            errors: [UNEXPECTED_LINEBREAK, UNEXPECTED_LINEBREAK]
+        }, {
+            code: `
+                () =>
+                    ((((bar))));
+            `,
+            output: `
+                () => ((((bar))));
+            `,
+            errors: [UNEXPECTED_LINEBREAK]
+        }, {
+            code: `
+                (foo) =>
+                    (
+                        bar
+                    )
+            `,
+            output: `
+                (foo) => (
+                        bar
+                    )
+            `,
+            errors: [UNEXPECTED_LINEBREAK]
+        },
+
+        // 'below' option
+        {
+            code: "(foo) => bar();",
+            output: "(foo) => \nbar();",
+            options: ["below"],
+            errors: [EXPECTED_LINEBREAK]
+        }, {
+            code: "(foo) => bar => baz;",
+            output: "(foo) => \nbar => \nbaz;",
+            options: ["below"],
+            errors: [EXPECTED_LINEBREAK, EXPECTED_LINEBREAK]
+        }, {
+            code: "(foo) => (bar);",
+            output: "(foo) => \n(bar);",
+            options: ["below"],
+            errors: [EXPECTED_LINEBREAK]
+        }, {
+            code: "(foo) => (((bar)));",
+            output: "(foo) => \n(((bar)));",
+            options: ["below"],
+            errors: [EXPECTED_LINEBREAK]
+        }, {
+            code: `
+                (foo) => (
+                    bar
+                )
+            `,
+            output: `
+                (foo) => \n(
+                    bar
+                )
+            `,
+            options: ["below"],
+            errors: [EXPECTED_LINEBREAK]
+        }
+    ]
+});
diff --git a/tests/lib/rules/space-in-parens.js b/tests/lib/rules/space-in-parens.js
index c9249e730..6e66a8fbd 100644
--- a/tests/lib/rules/space-in-parens.js
+++ b/tests/lib/rules/space-in-parens.js
@@ -110,7 +110,8 @@ ruleTester.run("space-in-parens", rule, {
         { code: "foo( ); bar( {bar:'baz'} ); baz( [1,2] )", options: ["never", { exceptions: ["{}", "[]", "empty"] }] },
 
         // faulty exceptions option
-        { code: "foo( { bar: 'baz' } )", options: ["always", { exceptions: [] }] }
+        { code: "foo( { bar: 'baz' } )", options: ["always", { exceptions: [] }] },
+        { code: "foo( { bar: 'baz' } )", options: ["always", {}] }
     ],
 
     invalid: [