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

View File

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