This commit is contained in:
Hackerpilot 2015-06-08 02:25:49 -07:00
parent 95308b9fc5
commit 959405eda5
6 changed files with 218 additions and 47 deletions

View file

@ -318,7 +318,7 @@ private:
void formatModuleOrImport()
{
auto t = current.type;
immutable t = current.type;
writeToken();
if (currentIs(tok!"("))
{
@ -464,12 +464,20 @@ private:
void formatColon()
{
if (astInformation.caseEndLocations.canFindIndex(current.index)
|| astInformation.attributeDeclarationLines.canFindIndex(current.line))
import dfmt.editorconfig : OptionalBoolean;
immutable bool isCase = astInformation.caseEndLocations.canFindIndex(current.index);
immutable bool isAttribute = astInformation.attributeDeclarationLines.canFindIndex(current.line);
if (isCase || isAttribute)
{
writeToken();
if (!currentIs(tok!"{"))
{
if (isCase && !indents.topIs(tok!"case") && config.dfmt_align_switch_statements == OptionalBoolean.f)
indents.push(tok!"case");
newline();
}
}
else if (peekBackIs(tok!"identifier") && (peekBack2Is(tok!"{", true)
|| peekBack2Is(tok!"}", true) || peekBack2Is(tok!";", true)
@ -541,7 +549,7 @@ private:
{
if (currentIs(tok!"{"))
indents.popTempIndents();
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
newline();
}
}
@ -588,9 +596,9 @@ private:
{
indents.popWrapIndents();
if (indents.length && isTempIndent(indents.top))
indentLevel = indents.indentSize - 1;
indentLevel = indents.indentLevel - 1;
else
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
if (!peekBackIsSlashSlash())
{
@ -604,7 +612,7 @@ private:
{
writeToken();
indents.popTempIndents();
indentLevel = indents.indentSize - 1;
indentLevel = indents.indentLevel - 1;
}
indents.push(tok!"{");
if (!currentIs(tok!"{"))
@ -1064,7 +1072,6 @@ private:
if (hasCurrent)
{
bool switchLabel = false;
if (currentIs(tok!"else"))
{
auto i = indents.indentToMostRecent(tok!"if");
@ -1075,36 +1082,31 @@ private:
}
else if (currentIs(tok!"identifier") && peekIs(tok!":"))
{
while ((peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
&& indents.length && isTempIndent(indents.top()))
{
indents.pop();
}
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
indents.popTempIndents();
immutable l = indents.indentToMostRecent(tok!"switch");
if (l != -1)
{
if (l != -1 && config.dfmt_align_switch_statements == OptionalBoolean.t)
indentLevel = l;
switchLabel = true;
}
else if (config.dfmt_compact_labeled_statements == OptionalBoolean.f
|| !isBlockHeader(2) || peek2Is(tok!"if"))
|| !isBlockHeader(2) || peek2Is(tok!"if"))
{
immutable l2 = indents.indentToMostRecent(tok!"{");
indentLevel = l2 == -1 ? indentLevel : l2;
indentLevel = l2 != -1 ? l2 : indents.indentLevel - 1;
}
else
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
}
else if (currentIs(tok!"case") || currentIs(tok!"default"))
{
while (indents.length && (peekBackIs(tok!"}", true)
|| peekBackIs(tok!";", true)) && isTempIndent(indents.top()))
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
{
indents.pop();
indents.popTempIndents();
if (indents.topIs(tok!"case"))
indents.pop();
}
immutable l = indents.indentToMostRecent(tok!"switch");
if (l != -1)
indentLevel = l;
indentLevel = config.dfmt_align_switch_statements == OptionalBoolean.t ? l : indents.indentLevel;
}
else if (currentIs(tok!"{"))
{
@ -1112,13 +1114,15 @@ private:
if (peekBackIsSlashSlash())
{
indents.popTempIndents();
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
}
}
else if (currentIs(tok!"}"))
{
indents.popTempIndents();
if (indents.top == tok!"{")
if (indents.topIs(tok!"case"))
indents.pop();
if (indents.topIs(tok!"{"))
{
indentLevel = indents.indentToMostRecent(tok!"{");
indents.pop();
@ -1135,7 +1139,7 @@ private:
if (indents.topIs(tok!"]"))
{
indents.pop();
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
}
}
else if (astInformation.attributeDeclarationLines.canFindIndex(current.line))
@ -1150,7 +1154,7 @@ private:
{
indents.pop();
}
indentLevel = indents.indentSize;
indentLevel = indents.indentLevel;
}
indent();
}

View file

@ -7,19 +7,32 @@ module dfmt.indentation;
import std.d.lexer;
/**
* Returns: true if the given token type is a wrap indent type
*/
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
{
return type != tok!"{" && type != tok!":" && type != tok!"]" && isOperator(type);
return type != tok!"{" && type != tok!"case" && type != tok!"]" && isOperator(type);
}
/**
* Returns: true if the given token type is a wrap indent type
*/
bool isTempIndent(IdType type) pure nothrow @nogc @safe
{
return type != tok!"{";
return type != tok!"{" && type != tok!"case";
}
/**
* Stack for managing indent levels.
*/
struct IndentStack
{
int indentToMostRecent(IdType item)
/**
* Modifies the indent stack to match the state that it had at the most
* recent appearance of the given token type.
*/
int indentToMostRecent(IdType item) const
{
size_t i = index;
while (true)
@ -47,44 +60,69 @@ struct IndentStack
return tempIndentCount;
}
/**
* Pushes the given indent type on to the stack.
*/
void push(IdType item) pure nothrow
{
index = index == 255 ? index : index + 1;
arr[index] = item;
}
/**
* Pops the top indent from the stack.
*/
void pop() pure nothrow
{
index = index == 0 ? index : index - 1;
}
/**
* Pops all wrapping indents from the top of the stack.
*/
void popWrapIndents() pure nothrow @safe @nogc
{
while (index > 0 && isWrapIndent(arr[index]))
index--;
}
/**
* Pops all temporary indents from the top of the stack.
*/
void popTempIndents() pure nothrow @safe @nogc
{
while (index > 0 && isTempIndent(arr[index]))
index--;
}
/**
* Returns: `true` if the top of the indent stack is the given indent type.
*/
bool topIs(IdType type) const pure nothrow @safe @nogc
{
return index > 0 && arr[index] == type;
}
/**
* Returns: `true` if the top of the indent stack is a temporary indent
*/
bool topIsTemp()
{
return index > 0 && index < arr.length && isTempIndent(arr[index]);
}
/**
* Returns: `true` if the top of the indent stack is a wrapping indent
*/
bool topIsWrap()
{
return index > 0 && index < arr.length && isWrapIndent(arr[index]);
}
/**
* Returns: `true` if the top of the indent stack is one of the given token
* types.
*/
bool topIsOneOf(IdType[] types...) const pure nothrow @safe @nogc
{
if (index <= 0)
@ -101,23 +139,9 @@ struct IndentStack
return arr[index];
}
int indentSize(size_t k = size_t.max) const pure nothrow @safe @nogc
int indentLevel() const pure nothrow @safe @nogc @property
{
if (index == 0)
return 0;
immutable size_t j = k == size_t.max ? index : k - 1;
int size = 0;
foreach (i; 1 .. j + 1)
{
if ((i + 1 <= index && arr[i] != tok!"]" && !isWrapIndent(arr[i])
&& isTempIndent(arr[i]) && (!isTempIndent(arr[i + 1])
|| arr[i + 1] == tok!"switch")))
{
continue;
}
size++;
}
return size;
return indentSize();
}
int length() const pure nothrow @property
@ -126,6 +150,31 @@ struct IndentStack
}
private:
size_t index;
IdType[256] arr;
int indentSize(size_t k = size_t.max) const pure nothrow @safe @nogc
{
if (index == 0)
return 0;
immutable size_t j = k == size_t.max ? index : k - 1;
int size = 0;
foreach (i; 1 .. j + 1)
{
if (i + 1 <= index)
{
if (arr[i] == tok!"]")
continue;
immutable bool currentIsTemp = isTempIndent(arr[i]);
immutable bool nextIsTemp = isTempIndent(arr[i + 1]);
immutable bool nextIsSwitch = arr[i + 1] == tok!"switch";
if (currentIsTemp && (!nextIsTemp || nextIsSwitch))
continue;
}
size++;
}
return size;
}
}

View file

@ -0,0 +1,42 @@
unittest
{
switch (x)
{
case 0:
version (none)
{
// Comment
case '\n':
break;
}
}
}
unittest
{
switch (x)
{
case 0:
{
Label: while (1)
{
}
break;
}
Label2:
doStuff();
}
}
unittest
{
switch (a)
{
case a:
doStuff();
doOtherStuff();
break;
default:
break;
}
}

1
tests/issue0097.args Normal file
View file

@ -0,0 +1 @@
--align_switch_statements=false

42
tests/issue0097.d Normal file
View file

@ -0,0 +1,42 @@
unittest
{
switch (x)
{
case 0:
version (none)
{
// Comment
case '\n':
break;
}
}
}
unittest
{
switch (x)
{
case 0:
{
Label: while (1)
{
}
break;
}
Label2:
doStuff();
}
}
unittest
{
switch (a)
{
case a:
doStuff();
doOtherStuff();
break;
default:
break;
}
}

View file

@ -0,0 +1,33 @@
unittest {
switch (x) {
case 0:
version (none) {
// Comment
case '\n':
break;
}
}
}
unittest {
switch (x) {
case 0: {
Label: while (1) {
}
break;
}
Label2:
doStuff();
}
}
unittest {
switch (a) {
case a:
doStuff();
doOtherStuff();
break;
default:
break;
}
}