mirror of
https://github.com/dlang-community/dfmt.git
synced 2025-04-25 21:00:03 +03:00
Implement #97
This commit is contained in:
parent
95308b9fc5
commit
959405eda5
6 changed files with 218 additions and 47 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
42
tests/allman/issue0097.d.ref
Normal file
42
tests/allman/issue0097.d.ref
Normal 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
1
tests/issue0097.args
Normal file
|
@ -0,0 +1 @@
|
|||
--align_switch_statements=false
|
42
tests/issue0097.d
Normal file
42
tests/issue0097.d
Normal 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;
|
||||
}
|
||||
}
|
33
tests/otbs/issue0097.d.ref
Normal file
33
tests/otbs/issue0097.d.ref
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue