Skip to content

Commit e5fc320

Browse files
authored
Merge pull request swiftlang#5548 from dduan/indent_switch_case_block
[swift-format] add option to indent switch block
2 parents baa9e03 + d0de084 commit e5fc320

File tree

10 files changed

+138
-25
lines changed

10 files changed

+138
-25
lines changed

include/swift/IDE/Formatting.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ namespace swift {
1717
namespace ide {
1818

1919
struct CodeFormatOptions {
20+
public:
2021
bool UseTabs = false;
22+
bool IndentSwitchCase = false;
2123
unsigned IndentWidth = 4;
2224
unsigned TabWidth = 4;
2325
};

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ def use_tabs : Flag<["-"], "use-tabs">, Group<code_formatting_Group>,
336336
Flags<[NoInteractiveOption, NoBatchOption, SwiftFormatOption]>,
337337
HelpText<"Use tabs for indentation.">;
338338

339+
def indent_switch_case : Flag<["-"], "indent-switch-case">,
340+
Group<code_formatting_Group>,
341+
Flags<[NoInteractiveOption, NoBatchOption, SwiftFormatOption]>,
342+
HelpText<"Indent cases in switch statements.">;
343+
339344
def in_place : Flag<["-"], "in-place">, Group<code_formatting_Group>,
340345
Flags<[NoInteractiveOption, NoBatchOption, SwiftFormatOption]>,
341346
HelpText<"Overwrite input file with formatted file.">;

lib/IDE/Formatting.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ class FormatContext {
8888
return InCommentLine;
8989
}
9090

91+
bool isSwitchControlStmt(unsigned LineIndex, StringRef Text) {
92+
if (!isSwitchContext())
93+
return false;
94+
StringRef LineText = swift::ide::getTrimmedTextForLine(LineIndex, Text);
95+
return LineText.startswith("break") || LineText.startswith("continue") ||
96+
LineText.startswith("return") || LineText.startswith("fallthrough");
97+
}
98+
9199
void padToSiblingColumn(StringBuilder &Builder) {
92100
assert(SiblingInfo.Loc.isValid() && "No sibling to align with.");
93101
CharSourceRange Range(SM, Lexer::getLocForStartOfLine(SM, SiblingInfo.Loc),
@@ -248,7 +256,8 @@ class FormatContext {
248256
return E->getEndLoc().isValid() && SM.getLineNumber(E->getEndLoc()) == Line;
249257
};
250258

251-
bool shouldAddIndentForLine(unsigned Line, TokenInfo TInfo) {
259+
bool shouldAddIndentForLine(unsigned Line, TokenInfo TInfo,
260+
const CodeFormatOptions &FmtOptions) {
252261
if (Cursor == Stack.rend())
253262
return false;
254263

@@ -276,7 +285,7 @@ class FormatContext {
276285
// case xyz: <-- No indent here, should be at same level as switch.
277286
Stmt *AtStmtStart = Start.getAsStmt();
278287
if (AtStmtStart && isa<CaseStmt>(AtStmtStart))
279-
return false;
288+
return FmtOptions.IndentSwitchCase;
280289

281290
// If we're at the open brace of the switch, don't add an indent.
282291
// For example:
@@ -292,7 +301,7 @@ class FormatContext {
292301
// // case comment <-- No indent here.
293302
// case 0:
294303
if (SM.getLineAndColumn(Case->swift::Stmt::getStartLoc()).first == Line + 1)
295-
return false;
304+
return FmtOptions.IndentSwitchCase;
296305
}
297306
}
298307
}
@@ -813,8 +822,18 @@ class CodeFormatter {
813822
ExpandedIndent -= ExpandedIndent % Width;
814823
};
815824

816-
if (LineAndColumn.second > 0 && FC.shouldAddIndentForLine(LineIndex, ToInfo))
825+
if (LineAndColumn.second > 0 &&
826+
FC.shouldAddIndentForLine(LineIndex, ToInfo, FmtOptions))
817827
AddIndentFunc();
828+
829+
// Control statements in switch align with the rest of the block in case.
830+
// For example:
831+
// switch ... {
832+
// case xyz:
833+
// break <-- Extra indent level here.
834+
if (FmtOptions.IndentSwitchCase && FC.isSwitchControlStmt(LineIndex, Text))
835+
AddIndentFunc();
836+
818837
if (FC.IsInDocCommentBlock()) {
819838

820839
// Inside doc comment block, the indent is one space, e.g.

test/swift-format/main.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
// RUN: diff -u %s.indent2.response %t.response
55
// RUN: %swift-format -use-tabs %s >%t.response
66
// RUN: diff -u %s.tabs.response %t.response
7-
// RUN: %swift-format -line-range 12:18 %s >%t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
88
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
911

1012
import Foundation
1113

12-
func collatz(n: Int) {
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
1324
var r: Int
1425
if n%2 == 0 {
1526
r = n/2

test/swift-format/main.swift.indent2.response

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
// RUN: diff -u %s.indent2.response %t.response
55
// RUN: %swift-format -use-tabs %s >%t.response
66
// RUN: diff -u %s.tabs.response %t.response
7-
// RUN: %swift-format -line-range 12:18 %s >%t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
88
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
911

1012
import Foundation
1113

12-
func collatz(n: Int) {
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
1324
var r: Int
1425
if n%2 == 0 {
1526
r = n/2
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %swift-format %s >%t.response
2+
// RUN: diff -u %s.response %t.response
3+
// RUN: %swift-format -indent-width 2 %s >%t.response
4+
// RUN: diff -u %s.indent2.response %t.response
5+
// RUN: %swift-format -use-tabs %s >%t.response
6+
// RUN: diff -u %s.tabs.response %t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
8+
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
11+
12+
import Foundation
13+
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
24+
var r: Int
25+
if n%2 == 0 {
26+
r = n/2
27+
} else {
28+
r = 3*n+1
29+
}
30+
print("Number: \(r)")
31+
if r == 1 {
32+
print("Reached one!")
33+
} else {
34+
collatz(r)
35+
}
36+
}

test/swift-format/main.swift.lines.response

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
// RUN: diff -u %s.indent2.response %t.response
55
// RUN: %swift-format -use-tabs %s >%t.response
66
// RUN: diff -u %s.tabs.response %t.response
7-
// RUN: %swift-format -line-range 12:18 %s >%t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
88
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
911

1012
import Foundation
1113

12-
func collatz(n: Int) {
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
1324
var r: Int
1425
if n%2 == 0 {
1526
r = n/2

test/swift-format/main.swift.response

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
// RUN: diff -u %s.indent2.response %t.response
55
// RUN: %swift-format -use-tabs %s >%t.response
66
// RUN: diff -u %s.tabs.response %t.response
7-
// RUN: %swift-format -line-range 12:18 %s >%t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
88
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
911

1012
import Foundation
1113

12-
func collatz(n: Int) {
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
1324
var r: Int
1425
if n%2 == 0 {
1526
r = n/2

test/swift-format/main.swift.tabs.response

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
// RUN: diff -u %s.indent2.response %t.response
55
// RUN: %swift-format -use-tabs %s >%t.response
66
// RUN: diff -u %s.tabs.response %t.response
7-
// RUN: %swift-format -line-range 12:18 %s >%t.response
7+
// RUN: %swift-format -line-range 24:29 %s >%t.response
88
// RUN: diff -u %s.lines.response %t.response
9+
// RUN: %swift-format -indent-switch-case %s >%t.response
10+
// RUN: diff -u %s.indentswitch.response %t.response
911

1012
import Foundation
1113

12-
func collatz(n: Int) {
14+
func collatz(n: Int, m: String?) {
15+
switch m {
16+
case .some(let s):
17+
print(s)
18+
case .none:
19+
print("nothing")
20+
default:
21+
print("not possible")
22+
break
23+
}
1324
var r: Int
1425
if n%2 == 0 {
1526
r = n/2

tools/driver/swift_format_main.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,8 @@ class SwiftFormatInvocation {
7979
std::string MainExecutablePath;
8080
std::string OutputFilename = "-";
8181
std::vector<std::string> InputFilenames;
82-
bool UseTabs = false;
82+
CodeFormatOptions FormatOptions;
8383
bool InPlace = false;
84-
unsigned TabWidth = 4;
85-
unsigned IndentWidth = 4;
8684
std::vector<std::string> LineRanges;
8785

8886
bool parseLineRange(StringRef Input, unsigned &FromLine, unsigned &ToLine) {
@@ -117,18 +115,21 @@ class SwiftFormatInvocation {
117115
}
118116

119117
if (ParsedArgs.getLastArg(OPT_use_tabs))
120-
UseTabs = true;
118+
FormatOptions.UseTabs = true;
119+
120+
if (ParsedArgs.getLastArg(OPT_indent_switch_case))
121+
FormatOptions.IndentSwitchCase = true;
121122

122123
if (ParsedArgs.getLastArg(OPT_in_place))
123124
InPlace = true;
124125

125126
if (const Arg *A = ParsedArgs.getLastArg(OPT_tab_width))
126-
if (StringRef(A->getValue()).getAsInteger(10, TabWidth))
127+
if (StringRef(A->getValue()).getAsInteger(10, FormatOptions.TabWidth))
127128
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
128129
A->getAsString(ParsedArgs), A->getValue());
129130

130131
if (const Arg *A = ParsedArgs.getLastArg(OPT_indent_width))
131-
if (StringRef(A->getValue()).getAsInteger(10, IndentWidth))
132+
if (StringRef(A->getValue()).getAsInteger(10, FormatOptions.IndentWidth))
132133
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
133134
A->getAsString(ParsedArgs), A->getValue());
134135

@@ -187,11 +188,6 @@ class SwiftFormatInvocation {
187188
LineRanges.push_back("1:" + std::to_string(UINT_MAX));
188189
}
189190

190-
CodeFormatOptions FormatOptions;
191-
FormatOptions.UseTabs = UseTabs;
192-
FormatOptions.IndentWidth = IndentWidth;
193-
FormatOptions.TabWidth = TabWidth;
194-
195191
std::string Output = Doc.memBuffer().getBuffer();
196192
for (unsigned Range = 0; Range < LineRanges.size(); ++Range) {
197193
unsigned FromLine;

0 commit comments

Comments
 (0)