Repository: eslint/eslint
Pull request #8477 (2017-04-18 22:18:14)

Fix: indent crash on arrow functions without parens at start of line
**What is the purpose of this pull request? (put an "X" next to item)**

[x] Bug fix

**Tell us about your environment**

* **ESLint Version:**
* **Node Version:**
* **npm Version:**

**What parser (default, Babel-ESLint, etc.) are you using?**

**Please show your full configuration:**

```yml
rules:
  indent: error
parserOptions:
  ecmaVersion: 6
```

**What did you do? Please include the actual source code causing the issue.**

```js
x => {}
```

**What did you expect to happen?**

I expected ESLint to not crash.

**What actually happened? Please include the actual, raw output from ESLint.**

ESLint crashed.

```
TypeError: Cannot read property 'range' of null
    at lodash.sortedIndexBy.token (path/to/lib/rules/indent.js:703:100)
    at baseSortedIndexBy (path/to/node_modules/lodash/lodash.js:4143:15)
    at Function.sortedIndexBy (path/to/node_modules/lodash/lodash.js:7991:14)
    at addFunctionParamsIndent (path/to/lib/rules/indent.js:703:46)
    at EventEmitter.ArrowFunctionExpression (path/to/lib/rules/indent.js:808:17)
    at emitOne (events.js:96:13)
    at EventEmitter.emit (events.js:191:7)
    at NodeEventGenerator.applySelector (path/to/lib/util/node-event-generator.js:265:26)
    at NodeEventGenerator.applySelectors (path/to/lib/util/node-event-generator.js:294:22)
    at NodeEventGenerator.enterNode (path/to/lib/util/node-event-generator.js:308:14)
```

**What changes did you make? (Give an overview)**

Previously, an arrow function without parentheses around the parameters at the start of a line would cause the `indent` rule to crash. This commit fixes the crash.

**Is there anything you'd like reviewers to focus on?**

Nothing in particular



Patch:
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 17b0f448e..79340ce7d 100755
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -16,6 +16,7 @@ module.exports = {
 
         /* eslint-enable sort-keys */
         "accessor-pairs": "off",
+        "array-bracket-newline": "off",
         "array-bracket-spacing": "off",
         "array-callback-return": "off",
         "arrow-body-style": "off",
diff --git a/docs/rules/array-bracket-newline.md b/docs/rules/array-bracket-newline.md
new file mode 100644
index 000000000..b4fd7cb63
--- /dev/null
+++ b/docs/rules/array-bracket-newline.md
@@ -0,0 +1,237 @@
+# enforce line breaks after opening and before closing array brackets (array-bracket-newline)
+
+A number of style guides require or disallow line breaks inside of array brackets.
+
+## Rule Details
+
+This rule enforces line breaks after opening and before closing array brackets.
+
+## Options
+
+This rule has either a string option:
+
+* `"always"` requires line breaks inside braces
+* `"never"` disallows line breaks inside braces
+
+Or an object option (Requires line breaks if any of properties is satisfied. Otherwise, disallows line breaks):
+
+* `"multiline": true` (default) requires line breaks if there are line breaks inside elements or between elements. If this is false, this condition is disabled.
+* `"minItems": null` (default) requires line breaks if the number of elements is at least the given integer. If this is 0, this condition will act the same as the option `"always"`. If this is `null` (the default), this condition is disabled.
+
+### always
+
+Examples of **incorrect** code for this rule with the `"always"` option:
+
+```js
+/*eslint array-bracket-newline: ["error", "always"]*/
+
+var a = [];
+var b = [1];
+var c = [1, 2];
+var d = [1,
+    2];
+var e = [function foo() {
+    dosomething();
+}];
+```
+
+Examples of **correct** code for this rule with the `"always"` option:
+
+```js
+/*eslint array-bracket-newline: ["error", "always"]*/
+
+var a = [
+];
+var b = [
+    1
+];
+var c = [
+    1, 2
+];
+var d = [
+    1,
+    2
+];
+var e = [
+    function foo() {
+        dosomething();
+    }
+];
+```
+
+### never
+
+Examples of **incorrect** code for this rule with the `"never"` option:
+
+```js
+/*eslint array-bracket-newline: ["error", "never"]*/
+
+var a = [
+];
+var b = [
+    1
+];
+var c = [
+    1, 2
+];
+var d = [
+    1,
+    2
+];
+var e = [
+    function foo() {
+        dosomething();
+    }
+];
+```
+
+Examples of **correct** code for this rule with the `"never"` option:
+
+```js
+/*eslint array-bracket-newline: ["error", "never"]*/
+
+var a = [];
+var b = [1];
+var c = [1, 2];
+var d = [1,
+    2];
+var e = [function foo() {
+    dosomething();
+}];
+```
+
+### multiline
+
+Examples of **incorrect** code for this rule with the default `{ "multiline": true }` option:
+
+```js
+/*eslint array-bracket-newline: ["error", { "multiline": true }]*/
+
+var a = [
+];
+var b = [
+    1
+];
+var c = [
+    1, 2
+];
+var d = [1,
+    2];
+var e = [function foo() {
+    dosomething();
+}];
+```
+
+Examples of **correct** code for this rule with the default `{ "multiline": true }` option:
+
+```js
+/*eslint array-bracket-newline: ["error", { "multiline": true }]*/
+
+var a = [];
+var b = [1];
+var c = [1, 2];
+var d = [
+    1,
+    2
+];
+var e = [
+    function foo() {
+        dosomething();
+    }
+];
+```
+
+### minItems
+
+Examples of **incorrect** code for this rule with the `{ "minItems": 2 }` option:
+
+```js
+/*eslint array-bracket-newline: ["error", { "minItems": 2 }]*/
+
+var a = [
+];
+var b = [
+    1
+];
+var c = [1, 2];
+var d = [1,
+    2];
+var e = [
+  function foo() {
+    dosomething();
+  }
+];
+```
+
+Examples of **correct** code for this rule with the `{ "minItems": 2 }` option:
+
+```js
+/*eslint array-bracket-newline: ["error", { "minItems": 2 }]*/
+
+var a = [];
+var b = [1];
+var c = [
+    1, 2
+];
+var d = [
+    1,
+    2
+];
+var e = [function foo() {
+    dosomething();
+}];
+```
+
+### multiline and minItems
+
+Examples of **incorrect** code for this rule with the `{ "multiline": true, "minItems": 2 }` options:
+
+```js
+/*eslint array-bracket-newline: ["error", { "multiline": true, "minItems": 2 }]*/
+
+var a = [
+];
+var b = [
+    1
+];
+var c = [1, 2];
+var d = [1,
+    2];
+var e = [function foo() {
+    dosomething();
+}];
+```
+
+Examples of **correct** code for this rule with the `{ "multiline": true, "minItems": 2 }` options:
+
+```js
+/*eslint array-bracket-newline: ["error", { "multiline": true, "minItems": 2 }]*/
+
+var a = [];
+var b = [1];
+var c = [
+    1, 2
+];
+var d = [
+    1,
+    2
+];
+var e = [
+    function foo() {
+        dosomething();
+    }
+];
+```
+
+
+## When Not To Use It
+
+If you don't want to enforce line breaks after opening and before closing array brackets, don't enable this rule.
+
+## Compatibility
+
+* **JSCS:** [validateNewlineAfterArrayElements](http://jscs.info/rule/validateNewlineAfterArrayElements)
+
+## Related Rules
+
+* [array-bracket-spacing](array-bracket-spacing.md)
diff --git a/docs/rules/comma-dangle.md b/docs/rules/comma-dangle.md
index 1897f6661..9eb3dedd3 100644
--- a/docs/rules/comma-dangle.md
+++ b/docs/rules/comma-dangle.md
@@ -68,8 +68,9 @@ The default for each option is `"never"` unless otherwise specified.
 * `objects` is for object literals and object patterns of destructuring. (e.g. `let {a,} = {a: 1};`)
 * `imports` is for import declarations of ES Modules. (e.g. `import {a,} from "foo";`)
 * `exports` is for export declarations of ES Modules. (e.g. `export {a,};`)
-* `functions` is for function declarations and function calls. (e.g. `(function(a,){ })(b,);`)<br>
-  `functions` is set to `"ignore"` by default for consistency with the string option.
+* `functions` is for function declarations and function calls. (e.g. `(function(a,){ })(b,);`)
+    * `functions` is set to `"ignore"` by default for consistency with the string option.
+    * `functions` should only be enabled when linting ECMAScript 2017 or higher.
 
 ### never
 
diff --git a/lib/rules/array-bracket-newline.js b/lib/rules/array-bracket-newline.js
new file mode 100644
index 000000000..319ac60f2
--- /dev/null
+++ b/lib/rules/array-bracket-newline.js
@@ -0,0 +1,235 @@
+/**
+ * @fileoverview Rule to enforce linebreaks after open and before close array brackets
+ * @author Jan Peer Stöcklmair <https://github.com/JPeer264>
+ */
+
+"use strict";
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        docs: {
+            description: "enforce linebreaks after opening and before closing array brackets",
+            category: "Stylistic Issues",
+            recommended: false
+        },
+        fixable: "whitespace",
+        schema: [
+            {
+                oneOf: [
+                    {
+                        enum: ["always", "never"]
+                    },
+                    {
+                        type: "object",
+                        properties: {
+                            multiline: {
+                                type: "boolean"
+                            },
+                            minItems: {
+                                type: ["integer", "null"],
+                                minimum: 0
+                            }
+                        },
+                        additionalProperties: false
+                    }
+                ]
+            }
+        ]
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+
+
+        //----------------------------------------------------------------------
+        // Helpers
+        //----------------------------------------------------------------------
+
+        /**
+         * Normalizes a given option value.
+         *
+         * @param {string|Object|undefined} option - An option value to parse.
+         * @returns {{multiline: boolean, minItems: number}} Normalized option object.
+         */
+        function normalizeOptionValue(option) {
+            let multiline = false;
+            let minItems = 0;
+
+            if (option) {
+                if (option === "always" || option.minItems === 0) {
+                    minItems = 0;
+                } else if (option === "never") {
+                    minItems = Number.POSITIVE_INFINITY;
+                } else {
+                    multiline = Boolean(option.multiline);
+                    minItems = option.minItems || Number.POSITIVE_INFINITY;
+                }
+            } else {
+                multiline = true;
+                minItems = Number.POSITIVE_INFINITY;
+            }
+
+            return { multiline, minItems };
+        }
+
+        /**
+         * Normalizes a given option value.
+         *
+         * @param {string|Object|undefined} options - An option value to parse.
+         * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
+         */
+        function normalizeOptions(options) {
+            const value = normalizeOptionValue(options);
+
+            return { ArrayExpression: value, ArrayPattern: value };
+        }
+
+        /**
+        * Reports that there shouldn't be a linebreak after the first token
+        * @param {ASTNode} node - The node to report in the event of an error.
+        * @param {Token} token - The token to use for the report.
+        * @returns {void}
+        */
+        function reportNoBeginningLinebreak(node, token) {
+            context.report({
+                node,
+                loc: token.loc,
+                message: "There should be no linebreak after '['.",
+                fix(fixer) {
+                    const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
+
+                    if (astUtils.isCommentToken(nextToken)) {
+                        return null;
+                    }
+
+                    return fixer.removeRange([token.range[1], nextToken.range[0]]);
+                }
+            });
+        }
+
+        /**
+        * Reports that there shouldn't be a linebreak before the last token
+        * @param {ASTNode} node - The node to report in the event of an error.
+        * @param {Token} token - The token to use for the report.
+        * @returns {void}
+        */
+        function reportNoEndingLinebreak(node, token) {
+            context.report({
+                node,
+                loc: token.loc,
+                message: "There should be no linebreak before ']'.",
+                fix(fixer) {
+                    const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
+
+                    if (astUtils.isCommentToken(previousToken)) {
+                        return null;
+                    }
+
+                    return fixer.removeRange([previousToken.range[1], token.range[0]]);
+                }
+            });
+        }
+
+        /**
+        * Reports that there should be a linebreak after the first token
+        * @param {ASTNode} node - The node to report in the event of an error.
+        * @param {Token} token - The token to use for the report.
+        * @returns {void}
+        */
+        function reportRequiredBeginningLinebreak(node, token) {
+            context.report({
+                node,
+                loc: token.loc,
+                message: "A linebreak is required after '['.",
+                fix(fixer) {
+                    return fixer.insertTextAfter(token, "\n");
+                }
+            });
+        }
+
+        /**
+        * Reports that there should be a linebreak before the last token
+        * @param {ASTNode} node - The node to report in the event of an error.
+        * @param {Token} token - The token to use for the report.
+        * @returns {void}
+        */
+        function reportRequiredEndingLinebreak(node, token) {
+            context.report({
+                node,
+                loc: token.loc,
+                message: "A linebreak is required before ']'.",
+                fix(fixer) {
+                    return fixer.insertTextBefore(token, "\n");
+                }
+            });
+        }
+
+        /**
+         * Reports a given node if it violated this rule.
+         *
+         * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node.
+         * @param {{multiline: boolean, minItems: number}} options - An option object.
+         * @returns {void}
+         */
+        function check(node) {
+            const elements = node.elements;
+            const normalizedOptions = normalizeOptions(context.options[0]);
+            const options = normalizedOptions[node.type];
+            const openBracket = sourceCode.getFirstToken(node);
+            const closeBracket = sourceCode.getLastToken(node);
+            const firstIncComment = sourceCode.getTokenAfter(openBracket, { includeComments: true });
+            const lastIncComment = sourceCode.getTokenBefore(closeBracket, { includeComments: true });
+            const first = sourceCode.getTokenAfter(openBracket);
+            const last = sourceCode.getTokenBefore(closeBracket);
+
+            const needsLinebreaks = (
+                elements.length >= options.minItems ||
+                (
+                    options.multiline &&
+                    elements.length > 0 &&
+                    firstIncComment.loc.start.line !== lastIncComment.loc.end.line
+                )
+            );
+
+            /*
+             * Use tokens or comments to check multiline or not.
+             * But use only tokens to check whether linebreaks are needed.
+             * This allows:
+             *     var arr = [ // eslint-disable-line foo
+             *         'a'
+             *     ]
+             */
+
+            if (needsLinebreaks) {
+                if (astUtils.isTokenOnSameLine(openBracket, first)) {
+                    reportRequiredBeginningLinebreak(node, openBracket);
+                }
+                if (astUtils.isTokenOnSameLine(last, closeBracket)) {
+                    reportRequiredEndingLinebreak(node, closeBracket);
+                }
+            } else {
+                if (!astUtils.isTokenOnSameLine(openBracket, first)) {
+                    reportNoBeginningLinebreak(node, openBracket);
+                }
+                if (!astUtils.isTokenOnSameLine(last, closeBracket)) {
+                    reportNoEndingLinebreak(node, closeBracket);
+                }
+            }
+        }
+
+        //----------------------------------------------------------------------
+        // Public
+        //----------------------------------------------------------------------
+
+        return {
+            ArrayPattern: check,
+            ArrayExpression: check
+        };
+    }
+};
diff --git a/lib/rules/indent.js b/lib/rules/indent.js
index a4258a070..1dd41804a 100644
--- a/lib/rules/indent.js
+++ b/lib/rules/indent.js
@@ -698,6 +698,13 @@ module.exports = {
         */
         function addFunctionParamsIndent(node, paramsIndent) {
             const openingParen = node.params.length ? sourceCode.getTokenBefore(node.params[0]) : sourceCode.getTokenBefore(node.body, 1);
+
+            if (!openingParen) {
+
+                // If there is no opening paren (e.g. for an arrow function with a single parameter), don't indent anything.
+                return;
+            }
+
             const closingParen = sourceCode.getTokenBefore(node.body);
             const nodeTokens = getTokensAndComments(node);
             const openingParenIndex = lodash.sortedIndexBy(nodeTokens, openingParen, token => token.range[0]);


Test patch:
diff --git a/tests/lib/rules/array-bracket-newline.js b/tests/lib/rules/array-bracket-newline.js
new file mode 100644
index 000000000..fd4afcc46
--- /dev/null
+++ b/tests/lib/rules/array-bracket-newline.js
@@ -0,0 +1,1460 @@
+/**
+ * @fileoverview Tests for array-bracket-newline rule.
+ * @author Jan Peer Stöcklmair <https://github.com/JPeer264>
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/array-bracket-newline");
+const RuleTester = require("../../../lib/testers/rule-tester");
+
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+
+const ERR_NO_BREAK_AFTER = "There should be no linebreak after '['.";
+const ERR_BREAK_AFTER = "A linebreak is required after '['.";
+const ERR_NO_BREAK_BEFORE = "There should be no linebreak before ']'.";
+const ERR_BREAK_BEFORE = "A linebreak is required before ']'.";
+
+ruleTester.run("array-bracket-newline", rule, {
+
+    valid: [
+
+        // ArrayExpression
+        // "default" { multiline: true }
+        "var foo = [];",
+        "var foo = [1];",
+        "var foo = /* any comment */[1];",
+        "var foo = /* any comment */\n[1];",
+        "var foo = [1, 2];",
+        "var foo = [ // any comment\n1, 2\n];",
+        "var foo = [\n// any comment\n1, 2\n];",
+        "var foo = [\n1, 2\n// any comment\n];",
+        "var foo = [\n1,\n2\n];",
+        "var foo = [\nfunction foo() {\nreturn dosomething();\n}\n];",
+
+        // "always"
+        { code: "var foo = [\n];", options: ["always"] },
+        { code: "var foo = [\n1\n];", options: ["always"] },
+        { code: "var foo = [\n// any\n1\n];", options: ["always"] },
+        { code: "var foo = [\n/* any */\n1\n];", options: ["always"] },
+        { code: "var foo = [\n1, 2\n];", options: ["always"] },
+        { code: "var foo = [\n1, 2 // any comment\n];", options: ["always"] },
+        { code: "var foo = [\n1, 2 /* any comment */\n];", options: ["always"] },
+        { code: "var foo = [\n1,\n2\n];", options: ["always"] },
+        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: ["always"] },
+
+        // "never"
+        { code: "var foo = [];", options: ["never"] },
+        { code: "var foo = [1];", options: ["never"] },
+        { code: "var foo = [/* any comment */1];", options: ["never"] },
+        { code: "var foo = [1, 2];", options: ["never"] },
+        { code: "var foo = [1,\n2];", options: ["never"] },
+        { code: "var foo = [1,\n/* any comment */\n2];", options: ["never"] },
+        { code: "var foo = [function foo() {\ndosomething();\n}];", options: ["never"] },
+
+        // { multiline: true }
+        { code: "var foo = [];", options: [{ multiline: true }] },
+        { code: "var foo = [1];", options: [{ multiline: true }] },
+        { code: "var foo = /* any comment */[1];", options: [{ multiline: true }] },
+        { code: "var foo = /* any comment */\n[1];", options: [{ multiline: true }] },
+        { code: "var foo = [1, 2];", options: [{ multiline: true }] },
+        { code: "var foo = [ // any comment\n1, 2\n];", options: [{ multiline: true }] },
+        { code: "var foo = [\n// any comment\n1, 2\n];", options: [{ multiline: true }] },
+        { code: "var foo = [\n1, 2\n// any comment\n];", options: [{ multiline: true }] },
+        { code: "var foo = [\n1,\n2\n];", options: [{ multiline: true }] },
+        { code: "var foo = [\nfunction foo() {\nreturn dosomething();\n}\n];", options: [{ multiline: true }] },
+
+        // { multiline: false }
+        { code: "var foo = [];", options: [{ multiline: false }] },
+        { code: "var foo = [1];", options: [{ multiline: false }] },
+        { code: "var foo = [1]/* any comment*/;", options: [{ multiline: false }] },
+        { code: "var foo = [1]\n/* any comment*/\n;", options: [{ multiline: false }] },
+        { code: "var foo = [1, 2];", options: [{ multiline: false }] },
+        { code: "var foo = [1,\n2];", options: [{ multiline: false }] },
+        { code: "var foo = [function foo() {\nreturn dosomething();\n}];", options: [{ multiline: false }] },
+
+        // { minItems: 2 }
+        { code: "var foo = [];", options: [{ minItems: 2 }] },
+        { code: "var foo = [1];", options: [{ minItems: 2 }] },
+        { code: "var foo = [\n1, 2\n];", options: [{ minItems: 2 }] },
+        { code: "var foo = [\n1,\n2\n];", options: [{ minItems: 2 }] },
+        { code: "var foo = [function foo() {\ndosomething();\n}];", options: [{ minItems: 2 }] },
+
+        // { minItems: 0 }
+        { code: "var foo = [\n];", options: [{ minItems: 0 }] },
+        { code: "var foo = [\n1\n];", options: [{ minItems: 0 }] },
+        { code: "var foo = [\n1, 2\n];", options: [{ minItems: 0 }] },
+        { code: "var foo = [\n1,\n2\n];", options: [{ minItems: 0 }] },
+        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ minItems: 0 }] },
+
+        // { minItems: null }
+        { code: "var foo = [];", options: [{ minItems: null }] },
+        { code: "var foo = [1];", options: [{ minItems: null }] },
+        { code: "var foo = [1, 2];", options: [{ minItems: null }] },
+        { code: "var foo = [1,\n2];", options: [{ minItems: null }] },
+        { code: "var foo = [function foo() {\ndosomething();\n}];", options: [{ minItems: null }] },
+
+        // { multiline: true, minItems: null }
+        { code: "var foo = [];", options: [{ multiline: true, minItems: null }] },
+        { code: "var foo = [1];", options: [{ multiline: true, minItems: null }] },
+        { code: "var foo = [1, 2];", options: [{ multiline: true, minItems: null }] },
+        { code: "var foo = [\n1,\n2\n];", options: [{ multiline: true, minItems: null }] },
+        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ multiline: true, minItems: null }] },
+
+        // { multiline: true, minItems: 2 }
+        { code: "var a = [];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var b = [1];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var b = [ // any comment\n1\n];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var b = [ /* any comment */ 1];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var c = [\n1, 2\n];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var c = [\n/* any comment */1, 2\n];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var c = [\n1, /* any comment */ 2\n];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var d = [\n1,\n2\n];", options: [{ multiline: true, minItems: 2 }] },
+        { code: "var e = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ multiline: true, minItems: 2 }] },
+
+        // ArrayPattern
+        // default { multiline: true }
+        { code: "var [] = foo", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [a] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var /* any comment */[a] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var /* any comment */\n[a] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [a, b] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [ // any comment\na, b\n] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\n// any comment\na, b\n] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na, b\n// any comment\n] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na,\nb\n] = foo;", parserOptions: { ecmaVersion: 6 } },
+
+        // "always"
+        { code: "var [\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\n// any\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\n/* any */\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na, b\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na, b // any comment\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na, b /* any comment */\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na,\nb\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+
+        // { multiline: true }
+        { code: "var [] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var /* any comment */[a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var /* any comment */\n[a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [a, b] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [ // any comment\na, b\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\n// any comment\na, b\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na, b\n// any comment\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na,\nb\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } }
+
+    ],
+
+    invalid: [
+
+        // ArrayExpression
+        // "always"
+        {
+            code: "var foo = [];",
+            options: ["always"],
+            output: "var foo = [\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
+                }
+            ]
+        },
+        {
+            code: "var foo = [1];",
+            options: ["always"],
+            output: "var foo = [\n1\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "var foo = [ // any comment\n1];",
+            options: ["always"],
+            output: "var foo = [ // any comment\n1\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 3
+                }
+            ]
+        },
+        {
+            code: "var foo = [ /* any comment */\n1];",
+            options: ["always"],
+            output: "var foo = [ /* any comment */\n1\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2];",
+            options: ["always"],
+            output: "var foo = [\n1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 16,
+                    endLine: 1,
+                    endColumn: 17
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2 // any comment\n];",
+            options: ["always"],
+            output: "var foo = [\n1, 2 // any comment\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2 /* any comment */];",
+            options: ["always"],
+            output: "var foo = [\n1, 2 /* any comment */\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 34
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: ["always"],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: ["always"],
+            output: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 2
+                }
+            ]
+        },
+
+        // "never"
+        {
+            code: "var foo = [\n];",
+            options: ["never"],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: ["never"],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: ["never"],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [ /* any comment */\n1, 2\n];",
+            options: ["never"],
+            output: "var foo = [ /* any comment */\n1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1, 2\n/* any comment */];",
+            options: ["never"],
+            output: "var foo = [1, 2\n/* any comment */];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 18
+                }
+            ]
+        },
+        {
+            code: "var foo = [ // any comment\n1, 2\n];",
+            options: ["never"],
+            output: "var foo = [ // any comment\n1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1,\n2\n];",
+            output: "var foo = [1,\n2];",
+            options: ["never"],
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 4,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: ["never"],
+            output: "var foo = [function foo() {\ndosomething();\n}];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 5,
+                    column: 1
+                }
+            ]
+        },
+
+        // { multiline: true }
+        {
+            code: "var foo = [\n];",
+            options: [{ multiline: true }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n// any comment\n];",
+            options: [{ multiline: true }],
+            output: "var foo = [\n// any comment\n];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ multiline: true }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1, 2\n];",
+            options: [{ multiline: true }],
+            output: "var foo = [1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: [{ multiline: true }],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ multiline: true }],
+            output: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 2
+                }
+            ]
+        },
+
+        // { minItems: 2 }
+        {
+            code: "var foo = [\n];",
+            options: [{ minItems: 2 }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ minItems: 2 }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2];",
+            options: [{ minItems: 2 }],
+            output: "var foo = [\n1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 16
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: [{ minItems: 2 }],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ minItems: 2 }],
+            output: "var foo = [function foo() {\ndosomething();\n}];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 5,
+                    column: 1
+                }
+            ]
+        },
+
+        // { minItems: 0 }
+        {
+            code: "var foo = [];",
+            options: [{ minItems: 0 }],
+            output: "var foo = [\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12
+                }
+            ]
+        },
+        {
+            code: "var foo = [1];",
+            options: [{ minItems: 0 }],
+            output: "var foo = [\n1\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2];",
+            options: [{ minItems: 0 }],
+            output: "var foo = [\n1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 16
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: [{ minItems: 0 }],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+
+            ]
+        },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ minItems: 0 }],
+            output: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 2
+                }
+            ]
+        },
+
+        // { minItems: null }
+        {
+            code: "var foo = [\n];",
+            options: [{ minItems: null }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ minItems: null }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1, 2\n];",
+            options: [{ minItems: null }],
+            output: "var foo = [1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1,\n2\n];",
+            options: [{ minItems: null }],
+            output: "var foo = [1,\n2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 4,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ minItems: null }],
+            output: "var foo = [function foo() {\ndosomething();\n}];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 5,
+                    column: 1
+                }
+            ]
+        },
+
+        // { multiline: true, minItems: null }
+        {
+            code: "var foo = [\n];",
+            options: [{ multiline: true, minItems: null }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ multiline: true, minItems: null }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1, 2\n];",
+            options: [{ multiline: true, minItems: null }],
+            output: "var foo = [1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: [{ multiline: true, minItems: null }],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ multiline: true, minItems: null }],
+            output: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 2
+                }
+            ]
+        },
+
+        // { multiline: true, minItems: 2 }
+        {
+            code: "var foo = [\n];",
+            options: [{ multiline: true, minItems: 2 }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ multiline: true, minItems: 2 }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [1, 2];",
+            options: [{ multiline: true, minItems: 2 }],
+            output: "var foo = [\n1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 16
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2];",
+            options: [{ multiline: true, minItems: 2 }],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ multiline: true, minItems: 2 }],
+            output: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 2
+                }
+            ]
+        },
+
+        // extra test cases
+        // "always"
+        {
+            code: "var foo = [\n1, 2];",
+            options: ["always"],
+            output: "var foo = [\n1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 5
+                }
+            ]
+        },
+        {
+            code: "var foo = [\t1, 2];",
+            options: ["always"],
+            output: "var foo = [\n\t1, 2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 17
+                }
+            ]
+        },
+        {
+            code: "var foo = [1,\n2\n];",
+            options: ["always"],
+            output: "var foo = [\n1,\n2\n];",
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                }
+            ]
+        },
+
+        //  { multiline: false }
+        {
+            code: "var foo = [\n];",
+            options: [{ multiline: false }],
+            output: "var foo = [];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1\n];",
+            options: [{ multiline: false }],
+            output: "var foo = [1];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1, 2\n];",
+            options: [{ multiline: false }],
+            output: "var foo = [1, 2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\n1,\n2\n];",
+            options: [{ multiline: false }],
+            output: "var foo = [1,\n2];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 4,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ multiline: false }],
+            output: "var foo = [function foo() {\ndosomething();\n}];",
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayExpression",
+                    line: 5,
+                    column: 1
+                }
+            ]
+        },
+
+        // ArrayPattern
+        // "always"
+        {
+            code: "var [] = foo;",
+            options: ["always"],
+            output: "var [\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 6
+                }
+            ]
+        },
+        {
+            code: "var [a] = foo;",
+            options: ["always"],
+            output: "var [\na\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 7
+                }
+            ]
+        },
+        {
+            code: "var [ // any comment\na] = foo;",
+            options: ["always"],
+            output: "var [ // any comment\na\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var [ /* any comment */\na] = foo;",
+            options: ["always"],
+            output: "var [ /* any comment */\na\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+        {
+            code: "var [a, b] = foo;",
+            options: ["always"],
+            output: "var [\na, b\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 10
+                }
+            ]
+        },
+        {
+            code: "var [a, b // any comment\n] = foo;",
+            options: ["always"],
+            output: "var [\na, b // any comment\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                }
+            ]
+        },
+        {
+            code: "var [a, b /* any comment */] = foo;",
+            options: ["always"],
+            output: "var [\na, b /* any comment */\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 28
+                }
+            ]
+        },
+        {
+            code: "var [a,\nb] = foo;",
+            options: ["always"],
+            output: "var [\na,\nb\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        },
+
+        // { minItems: 2 }
+        {
+            code: "var [\n] = foo;",
+            options: [{ minItems: 2 }],
+            output: "var [] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var [\na\n] = foo;",
+            options: [{ minItems: 2 }],
+            output: "var [a] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_NO_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_NO_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 3,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "var [a, b] = foo;",
+            options: [{ minItems: 2 }],
+            output: "var [\na, b\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 10
+                }
+            ]
+        },
+        {
+            code: "var [a,\nb] = foo;",
+            options: [{ minItems: 2 }],
+            output: "var [\na,\nb\n] = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: ERR_BREAK_AFTER,
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 5
+                },
+                {
+                    message: ERR_BREAK_BEFORE,
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 2
+                }
+            ]
+        }
+
+    ]
+});
diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js
index 4a926f427..e965c8aad 100644
--- a/tests/lib/rules/indent.js
+++ b/tests/lib/rules/indent.js
@@ -3041,6 +3041,10 @@ ruleTester.run("indent", rule, {
 
                 ; [1, 2, 3].map(baz)
             `
+        },
+        {
+            code: "x => {}",
+            parserOptions: { ecmaVersion: 6 }
         }
     ],