diff --git a/src/dfmt/formatter.d b/src/dfmt/formatter.d
index c64ee9b..d302f4a 100644
--- a/src/dfmt/formatter.d
+++ b/src/dfmt/formatter.d
@@ -15,7 +15,7 @@ import dfmt.indentation;
 import dfmt.tokens;
 import dfmt.wrapping;
 import std.array;
-import std.algorithm.comparison : among;
+import std.algorithm.comparison : among, max;
 
 /**
  * Formats the code contained in `buffer` into `output`.
@@ -213,6 +213,11 @@ private:
     /// True if the next "else" should be formatted as a single line
     bool inlineElse;
 
+    /// Tracks paren depth on a single line. This information can be used to
+    /// indent array literals inside parens, since arrays are indented only once
+    /// and paren indentation is ignored.line breaks and "[" reset the counter.
+    int parenDepthOnLine;
+
     void formatStep()
     {
         import std.range : assumeSorted;
@@ -614,6 +619,7 @@ private:
         writeToken();
         if (p == tok!"(")
         {
+            ++parenDepthOnLine;
             // If the file starts with an open paren, just give up. This isn't
             // valid D code.
             if (index < 2)
@@ -633,9 +639,7 @@ private:
 
         if (arrayInitializerStart && isMultilineAt(index - 1))
         {
-            if (peekBack2Is(tok!"(")) {
-                indents.pop();
-            }
+            revertParenIndentation();
 
             // Use the close bracket as the indent token to distinguish
             // the array initialiazer from an array index in the newline
@@ -659,9 +663,7 @@ private:
         }
         else if (p == tok!"[" && config.dfmt_keep_line_breaks == OptionalBoolean.t)
         {
-            if (peekBack2Is(tok!"(")) {
-                indents.pop();
-            }
+            revertParenIndentation();
             IndentStack.Details detail;
 
             detail.wrap = false;
@@ -714,6 +716,19 @@ private:
         }
     }
 
+    void revertParenIndentation()
+    {
+        if (parenDepthOnLine)
+        {
+            foreach (i; 0 .. parenDepthOnLine)
+            {
+                indents.pop();
+            }
+            indents.popTempIndents();
+        }
+        parenDepthOnLine = 0;
+    }
+
     void formatRightParen()
     in
     {
@@ -721,6 +736,7 @@ private:
     }
     do
     {
+        parenDepthOnLine = max(parenDepthOnLine - 1, 0);
         parenDepth--;
         indents.popWrapIndents();
         while (indents.topIsOneOf(tok!"!", tok!")"))
@@ -1682,6 +1698,8 @@ private:
         import std.algorithm : max, canFind;
         import dfmt.editorconfig : OptionalBoolean;
 
+        parenDepthOnLine = 0;
+
         if (currentIs(tok!"comment") && index > 0 && current.line == tokenEndLine(tokens[index - 1]))
             return;
 
diff --git a/tests/allman/foreach_array.d.ref b/tests/allman/foreach_array.d.ref
new file mode 100644
index 0000000..e714129
--- /dev/null
+++ b/tests/allman/foreach_array.d.ref
@@ -0,0 +1,54 @@
+static foreach (x; [
+    1,
+    2,
+    3,
+])
+{
+}
+
+static foreach_reverse (x; [
+    1,
+    2,
+    3,
+])
+{
+}
+
+void f()
+{
+    foreach (x; [
+        1,
+        2,
+        3,
+    ])
+    {
+    }
+    foreach_reverse (x; [
+        1,
+        2,
+        3,
+    ])
+    {
+    }
+
+    if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri))
+    {
+        send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
+        ]));
+    }
+
+    foreach (x; map([
+        1,
+        2,
+        3,
+    ]))
+    {
+    }
+    foreach (x; foo!(map!([
+        1,
+        2,
+        3,
+    ])))
+    {
+    }
+}
diff --git a/tests/foreach_array.args b/tests/foreach_array.args
new file mode 100644
index 0000000..3e94d38
--- /dev/null
+++ b/tests/foreach_array.args
@@ -0,0 +1 @@
+--keep_line_breaks true
diff --git a/tests/foreach_array.d b/tests/foreach_array.d
new file mode 100644
index 0000000..8e8ea0f
--- /dev/null
+++ b/tests/foreach_array.d
@@ -0,0 +1,53 @@
+static foreach (x; [
+    1,
+    2,
+    3,
+])
+{
+}
+
+static foreach_reverse (x; [
+    1,
+    2,
+    3,
+])
+{
+}
+
+void f()
+{
+    foreach (x; [
+        1,
+        2,
+        3,
+    ])
+    {
+    }
+    foreach_reverse (x; [
+        1,
+        2,
+        3,
+    ])
+    {
+    }
+
+    if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri))
+    {
+        send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, []));
+    }
+
+    foreach (x; map([
+            1,
+            2,
+            3,
+        ]))
+    {
+    }
+    foreach (x; foo!(map!([
+            1,
+            2,
+            3,
+        ])))
+    {
+    }
+}
diff --git a/tests/knr/foreach_array.d.ref b/tests/knr/foreach_array.d.ref
new file mode 100644
index 0000000..f0d447e
--- /dev/null
+++ b/tests/knr/foreach_array.d.ref
@@ -0,0 +1,47 @@
+static foreach (x; [
+    1,
+    2,
+    3,
+]) {
+}
+
+static foreach_reverse (x; [
+    1,
+    2,
+    3,
+]) {
+}
+
+void f()
+{
+    foreach (x; [
+        1,
+        2,
+        3,
+    ]) {
+    }
+    foreach_reverse (x; [
+        1,
+        2,
+        3,
+    ]) {
+    }
+
+    if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri)) {
+        send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
+        ]));
+    }
+
+    foreach (x; map([
+        1,
+        2,
+        3,
+    ])) {
+    }
+    foreach (x; foo!(map!([
+        1,
+        2,
+        3,
+    ]))) {
+    }
+}
diff --git a/tests/otbs/foreach_array.d.ref b/tests/otbs/foreach_array.d.ref
new file mode 100644
index 0000000..b505616
--- /dev/null
+++ b/tests/otbs/foreach_array.d.ref
@@ -0,0 +1,46 @@
+static foreach (x; [
+    1,
+    2,
+    3,
+]) {
+}
+
+static foreach_reverse (x; [
+    1,
+    2,
+    3,
+]) {
+}
+
+void f() {
+    foreach (x; [
+        1,
+        2,
+        3,
+    ]) {
+    }
+    foreach_reverse (x; [
+        1,
+        2,
+        3,
+    ]) {
+    }
+
+    if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri)) {
+        send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
+        ]));
+    }
+
+    foreach (x; map([
+        1,
+        2,
+        3,
+    ])) {
+    }
+    foreach (x; foo!(map!([
+        1,
+        2,
+        3,
+    ]))) {
+    }
+}
diff --git a/tests/test.sh b/tests/test.sh
index 88df227..7b81277 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -5,6 +5,8 @@ for braceStyle in allman otbs knr
 do
 	for source in *.d
 	do
+		test "$(basename $source '.d')" = 'test' && continue
+
 		echo "${source}.ref" "${braceStyle}/${source}.out"
 		argsFile=$(basename "${source}" .d).args
 		if [ -e "${argsFile}" ]; then