From 053b775cd1a80531b1476b2e15d5f5cd293aca8e Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Fri, 11 Jan 2019 00:47:50 +0100 Subject: [PATCH] Add details to indentation stack This makes more advanced state handling easily possible. Also moved isWrapIndent/isTempIndent into this, which allows for exceptions for certain tokens and more control. --- src/dfmt/formatter.d | 25 ++++++++++++---- src/dfmt/indentation.d | 68 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/dfmt/formatter.d b/src/dfmt/formatter.d index bd47b93..b2716c7 100644 --- a/src/dfmt/formatter.d +++ b/src/dfmt/formatter.d @@ -1240,8 +1240,13 @@ private: break; case tok!"]": indents.popWrapIndents(); - if (indents.topIs(tok!"]")) - newline(); + if (indents.topIsTemp(tok!"]")) + { + if (!indents.topDetails.mini) + newline(); + else + indents.pop(); + } writeToken(); if (currentIs(tok!"identifier")) write(" "); @@ -1402,7 +1407,7 @@ private: : tokens[i .. $].countUntil!(t => t.index == r.front) + i; immutable size_t j = min(expressionEndIndex(i), ufcsBreakLocation); // Use magical negative value for array literals and wrap indents - immutable inLvl = (indents.topIsWrap() || indents.topIs(tok!"]")) ? -indentLevel + immutable inLvl = (indents.topIsWrap() || indents.topIsTemp(tok!"]")) ? -indentLevel : indentLevel; linebreakHints = chooseLineBreakTokens(i, tokens[i .. j], depths[i .. j], config, currentLineLength, inLvl); @@ -1528,7 +1533,7 @@ private: else if (currentIs(tok!"]")) { indents.popWrapIndents(); - if (indents.topIs(tok!"]")) + if (indents.topIsTemp(tok!"]")) { indents.pop(); indentLevel = indents.indentLevel; @@ -1671,13 +1676,21 @@ private: void pushWrapIndent(IdType type = tok!"") { immutable t = type == tok!"" ? tokens[index].type : type; + IndentStack.Details detail; + detail.wrap = isWrapIndent(t); + detail.temp = isTempIndent(t); + pushWrapIndent(t, detail); + } + + void pushWrapIndent(IdType type, IndentStack.Details detail) + { if (parenDepth == 0) { if (indents.wrapIndents == 0) - indents.push(t); + indents.push(type, detail); } else if (indents.wrapIndents < 1) - indents.push(t); + indents.push(type, detail); } const pure @safe @nogc: diff --git a/src/dfmt/indentation.d b/src/dfmt/indentation.d index 8eeacea..d2be341 100644 --- a/src/dfmt/indentation.d +++ b/src/dfmt/indentation.d @@ -7,6 +7,8 @@ module dfmt.indentation; import dparse.lexer; +import std.bitmanip : bitfields; + /** * Returns: true if the given token type is a wrap indent type */ @@ -29,6 +31,20 @@ bool isTempIndent(IdType type) pure nothrow @nogc @safe */ struct IndentStack { + static struct Details + { + mixin(bitfields!( + // generally true for all operators except {, case, @, ], (, ) + bool, "wrap", 1, + // temporary indentation which get's reverted when a block starts + // generally true for all tokens except ), {, case, @ + bool, "temp", 1, + // emit minimal newlines + bool, "mini", 1, + bool, "isAA", 1, + uint, "", 28)); + } + /** * Get the indent size at the most recent occurrence of the given indent type */ @@ -55,7 +71,7 @@ struct IndentStack int tempIndentCount = 0; for (size_t i = index; i > 0; i--) { - if (!isWrapIndent(arr[i - 1]) && arr[i - 1] != tok!"]") + if (!details[i - 1].wrap && arr[i - 1] != tok!"]") break; tempIndentCount++; } @@ -66,8 +82,20 @@ struct IndentStack * Pushes the given indent type on to the stack. */ void push(IdType item) pure nothrow + { + Details detail; + detail.wrap = isWrapIndent(item); + detail.temp = isTempIndent(item); + push(item, detail); + } + + /** + * Pushes the given indent type on to the stack. + */ + void push(IdType item, Details detail) pure nothrow { arr[index] = item; + details[index] = detail; //FIXME this is actually a bad thing to do, //we should not just override when the stack is //at it's limit @@ -91,7 +119,7 @@ struct IndentStack */ void popWrapIndents() pure nothrow @safe @nogc { - while (index > 0 && isWrapIndent(arr[index - 1])) + while (index > 0 && details[index - 1].wrap) index--; } @@ -100,7 +128,7 @@ struct IndentStack */ void popTempIndents() pure nothrow @safe @nogc { - while (index > 0 && isTempIndent(arr[index - 1])) + while (index > 0 && details[index - 1].temp) index--; } @@ -125,7 +153,15 @@ struct IndentStack */ bool topIsTemp() { - return index > 0 && index <= arr.length && isTempIndent(arr[index - 1]); + return index > 0 && index <= arr.length && details[index - 1].temp; + } + + /** + * Returns: `true` if the top of the indent stack is a temporary indent with the specified token + */ + bool topIsTemp(IdType item) + { + return index > 0 && index <= arr.length && arr[index - 1] == item && details[index - 1].temp; } /** @@ -133,7 +169,15 @@ struct IndentStack */ bool topIsWrap() { - return index > 0 && index <= arr.length && isWrapIndent(arr[index - 1]); + return index > 0 && index <= arr.length && details[index - 1].wrap; + } + + /** + * Returns: `true` if the top of the indent stack is a temporary indent with the specified token + */ + bool topIsWrap(IdType item) + { + return index > 0 && index <= arr.length && arr[index - 1] == item && details[index - 1].wrap; } /** @@ -156,6 +200,11 @@ struct IndentStack return arr[index - 1]; } + Details topDetails() const pure nothrow @property @safe @nogc + { + return details[index - 1]; + } + int indentLevel() const pure nothrow @property @safe @nogc { return indentSize(); @@ -183,6 +232,7 @@ private: size_t index; IdType[256] arr; + Details[arr.length] details; int indentSize(const size_t k = size_t.max) const pure nothrow @safe @nogc { @@ -196,17 +246,17 @@ private: { immutable int pc = (arr[i] == tok!"!" || arr[i] == tok!"(" || arr[i] == tok!")") ? parenCount + 1 : parenCount; - if ((isWrapIndent(arr[i]) || arr[i] == tok!"(") && parenCount > 1) + if ((details[i].wrap || arr[i] == tok!"(") && parenCount > 1) { parenCount = pc; continue; } if (i + 1 < index) { - if (arr[i] == tok!"]") + if (arr[i] == tok!"]" && details[i].temp) continue; - immutable currentIsNonWrapTemp = !isWrapIndent(arr[i]) - && isTempIndent(arr[i]) && arr[i] != tok!")" && arr[i] != tok!"!"; + immutable currentIsNonWrapTemp = !details[i].wrap + && details[i].temp && arr[i] != tok!")" && arr[i] != tok!"!"; if (arr[i] == tok!"static" && arr[i + 1].among!(tok!"if", tok!"else", tok!"foreach", tok!"foreach_reverse") && (i + 2 >= index || arr[i + 2] != tok!"{"))