Skip to content

Commit 8727fac

Browse files
Nathan Hawesrjmccall
authored andcommitted
[SourceKit/CodeFormat] Update indentation for braceless multiple trailing closures.
1 parent 6e20af9 commit 8727fac

File tree

3 files changed

+227
-75
lines changed

3 files changed

+227
-75
lines changed

lib/IDE/Formatting.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,15 @@ class RangeWalker: protected ASTWalker {
388388
public:
389389
explicit RangeWalker(SourceManager &SM) : SM(SM) {}
390390

391+
/// Called for every range bounded by a pair of parens, braces, square
392+
/// brackets, or angle brackets.
393+
///
391394
/// \returns true to continue walking.
392395
virtual bool handleRange(SourceLoc L, SourceLoc R, SourceLoc ContextLoc) = 0;
393396

397+
/// Called for ranges that have a separate ContextLoc but no bounding tokens.
398+
virtual void handleImplicitRange(SourceRange Range, SourceLoc ContextLoc) = 0;
399+
394400
private:
395401
bool handleBraces(SourceLoc L, SourceLoc R, SourceLoc ContextLoc) {
396402
L = getLocIfKind(SM, L, tok::l_brace);
@@ -634,12 +640,6 @@ class RangeWalker: protected ASTWalker {
634640
Arg = cast<SubscriptExpr>(E)->getIndex();
635641
}
636642

637-
auto handleTrailingClosure = [&](Expr *arg) -> bool {
638-
if (auto CE = findTrailingClosureFromArgument(arg))
639-
return handleBraceStmt(CE->getBody(), ContextLoc);
640-
return true;
641-
};
642-
643643
if (auto *PE = dyn_cast_or_null<ParenExpr>(Arg)) {
644644
if (isa<SubscriptExpr>(E)) {
645645
if (!handleSquares(PE->getLParenLoc(), PE->getRParenLoc(), ContextLoc))
@@ -649,8 +649,9 @@ class RangeWalker: protected ASTWalker {
649649
return Stop;
650650
}
651651
if (PE->hasTrailingClosure()) {
652-
if (!handleTrailingClosure(PE->getSubExpr()))
653-
return Stop;
652+
if (auto CE = findTrailingClosureFromArgument(PE->getSubExpr()))
653+
if (!handleBraceStmt(CE->getBody(), ContextLoc))
654+
return Stop;
654655
}
655656
} else if (auto *TE = dyn_cast_or_null<TupleExpr>(Arg)) {
656657
if (isa<SubscriptExpr>(E)) {
@@ -660,9 +661,10 @@ class RangeWalker: protected ASTWalker {
660661
if (!handleParens(TE->getLParenLoc(), TE->getRParenLoc(), ContextLoc))
661662
return Stop;
662663
}
663-
for (auto closure : TE->getTrailingElements()) {
664-
if (!handleTrailingClosure(closure))
665-
return Stop;
664+
if (TE->hasAnyTrailingClosures()) {
665+
SourceRange Range(TE->getTrailingElements().front()->getStartLoc(),
666+
TE->getEndLoc());
667+
handleImplicitRange(Range, ContextLoc);
666668
}
667669
}
668670
}
@@ -723,6 +725,16 @@ class OutdentChecker: protected RangeWalker {
723725
assert(CheckRange.isValid());
724726
}
725727

728+
void handleImplicitRange(SourceRange Range, SourceLoc ContextLoc) override {
729+
assert(Range.isValid() && ContextLoc.isValid());
730+
731+
// Ignore ranges outside of the open/closed check range.
732+
if (!isInCheckRange(Range.Start, Range.End))
733+
return;
734+
735+
propagateContextLocs(ContextLoc, Range.Start, Range.End);
736+
}
737+
726738
bool handleRange(SourceLoc L, SourceLoc R, SourceLoc ContextLoc) override {
727739
assert(L.isValid() && ContextLoc.isValid());
728740

@@ -2344,9 +2356,24 @@ class FormatWalker : public ASTWalker {
23442356
} else if (auto *TE = dyn_cast_or_null<TupleExpr>(Arg)) {
23452357
if (auto Ctx = getIndentContextFrom(TE, ContextLoc))
23462358
return Ctx;
2347-
for (auto arg : TE->getTrailingElements()) {
2348-
if (auto Ctx = getIndentContextFromTrailingClosure(arg))
2349-
return Ctx;
2359+
2360+
if (TE->hasAnyTrailingClosures()) {
2361+
Expr *Unlabeled = TE->getTrailingElements().front();
2362+
SourceRange ClosuresRange(Unlabeled->getStartLoc(), TE->getEndLoc());
2363+
2364+
if (overlapsTarget(ClosuresRange) || TrailingTarget) {
2365+
SourceRange ContextToEnd(ContextLoc, ClosuresRange.End);
2366+
ContextLoc = CtxOverride.propagateContext(SM, ContextLoc,
2367+
IndentContext::LineStart,
2368+
ClosuresRange.Start,
2369+
SourceLoc());
2370+
if (!TrailingTarget) {
2371+
return IndentContext {
2372+
ContextLoc,
2373+
!OutdentChecker::hasOutdent(SM, ContextToEnd, E)
2374+
};
2375+
}
2376+
}
23502377
}
23512378
}
23522379
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
func foo() {
2+
bar
3+
.fooooooooooo(first: 3,
4+
second)[x: 10] {} other: {
5+
6+
// RUN: %sourcekitd-test -req=format -line=5 -length=1 %s | %FileCheck --strict-whitespace %s
7+
// CHECK: key.sourcetext: " "

test/swift-indent/multiple-trailing-closures.swift

Lines changed: 179 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,227 @@
11
// RUN: %swift-indent %s >%t.response
22
// RUN: diff -u %s %t.response
33

4-
// XFAIL: *
5-
64
foo(c: 12, d: 34) {
7-
a: { print("foo") }
5+
print("foo")
86
}
97

10-
foo {
11-
a: { print("foo") }
8+
foo(c: 12, d: 34)
9+
{
10+
print("foo")
1211
}
1312

14-
foo {
15-
a: { print("foo") }
16-
b
13+
14+
someCall(c: 12, d: 34) {
15+
print("foo")
16+
} e: {
17+
print("foo")
18+
} f: {
19+
print("bar")
1720
}
1821

19-
foo (c: 12, d: 34) {
20-
a: { print("foo") }
21-
b:
22+
someCall(c: 12, d: 34) {
23+
print("foo")
24+
}
25+
e: {
26+
print("foo")
27+
}
28+
f: {
29+
print("bar")
2230
}
2331

24-
// Invalid, but we should still indent correctly.
25-
foo {
26-
a: {
27-
print("foo")
28-
}
29-
b: bar(a: 1,
30-
b: 2) {
31-
print("bar")
32-
}
32+
someCall(c: 12, d: 34)
33+
{
34+
print("foo")
35+
}
36+
e:
37+
{
38+
print("foo")
39+
}
40+
f:
41+
{
42+
print("bar")
3343
}
3444

35-
foo {
36-
a: {
37-
print("foo")
38-
}
39-
b: {
45+
someCall(c: 12, d: 34) { print("foo") }
46+
e: { print("foo") }
47+
f: {
4048
print("bar")
4149
}
42-
}
4350

44-
foo(c: 12, d: 34) {
45-
a: {
46-
print("foo")
51+
someCall(c: 12,
52+
d: 34) { print("foo") }
53+
e: { print("bar") }
54+
.other { print("foo") }
55+
a: { print("foo") }
56+
.next() {
57+
print("bar")
4758
}
48-
b: {
59+
60+
base
61+
.someCall(c: 12,
62+
d: 34) { print("foo") }
63+
e: { print("bar") }
64+
.other { print("foo") }
65+
a: { print("foo") }
66+
.next() {
4967
print("bar")
5068
}
69+
70+
someCall(
71+
c: 12,
72+
d: 34
73+
) { print("foo") }
74+
e: { print("bar") }
75+
76+
base
77+
.someCall(
78+
x: 10,
79+
y: 10
80+
) { $0 }
81+
next: { $0 }
82+
83+
base
84+
.foo(
85+
x: 10,
86+
y: 10) { } next: {
87+
88+
}
89+
other: {}
90+
91+
base
92+
.someCall(x: 120,
93+
y: 3030) { print("foo") } next:
94+
{
95+
print("foo")
96+
}
97+
other: {}
98+
99+
100+
someCall {
101+
print("foo")
102+
} e: {
103+
print("foo")
104+
} f: {
105+
print("bar")
51106
}
52107

53-
foo(c: 12, d: 34) { a: {
108+
someCall {
54109
print("foo")
55-
} b: {
110+
}
111+
e: {
112+
print("foo")
113+
}
114+
f: {
56115
print("bar")
57-
}}
116+
}
58117

59-
foo(c: 12, d: 34) { a: {print("foo")}
60-
b: {print("bar")} }
118+
someCall
119+
{
120+
print("foo")
121+
}
122+
e:
123+
{
124+
print("foo")
125+
}
126+
f:
127+
{
128+
print("bar")
129+
}
61130

62-
foo(c: 12, d: 34) { a: {print("foo")}
63-
/*comment*/b: {
131+
someCall { print("foo") }
132+
e: { print("foo") }
133+
f: {
64134
print("bar")
65-
}}
135+
}
66136

67-
foobar(c: 12,
68-
d: 34) {
69-
a: {
137+
doSomethingWith(someCall { print("foo") }
138+
e: { print("foo") }
139+
f: {
140+
print("bar")
141+
})
142+
143+
doSomethingWith(someCall {
144+
print("foo")
145+
}
146+
e: { print("foo") }
147+
f: {
148+
print("bar")
149+
})
150+
151+
func containIncomplete1() {
152+
someCall {
70153
print("foo")
71154
}
72-
b: {
73-
print("bar")
74-
}
155+
e
75156
}
76157

77-
foo(c: 12, d: 34)
78-
{
79-
a: {
158+
func containIncomplete2() {
159+
someCall {
80160
print("foo")
81161
}
82-
b: {
83-
print("bar")
162+
e:
163+
}
164+
165+
func containIncomplete3() {
166+
someCall
167+
{
168+
print("foo")
84169
}
170+
e
85171
}
86172

87-
foobar[c: 12,
88-
d: 34] {
89-
a: {
173+
func containIncomplete4() {
174+
someCall
175+
{
90176
print("foo")
91177
}
178+
e:
179+
}
180+
181+
func containIncomplete5() {
182+
someCall { print("foo") }
183+
e
184+
}
185+
186+
func containIncomplete6() {
187+
someCall { print("foo") }
188+
e:
189+
}
190+
191+
someCall(c: 12, d: 34) {{
192+
print("foo")
193+
}()} b: {{
194+
print("bar")
195+
}()}
196+
197+
someCall(c: 12, d: 34) { print("foo") }
198+
/*comment*/e: { print("bar") }
199+
/*comment*/f: {
200+
print("hi")
201+
}
202+
203+
someCall[c: 12,
204+
d: 34] { print("foo") }
92205
b: {
93206
print("bar")
94207
}
208+
209+
someSub[c: 12,
210+
d: 34] {
211+
print("foo")
212+
} b: {
213+
print("bar")
95214
}
96215

97-
foo(c: 12, d: 34)
98-
{
99-
a: {
100-
print("foo")
101-
}
216+
someSub[c: 12,
217+
d: 34] {
218+
print("foo")
219+
} b: {
220+
print("bar")
221+
}
222+
223+
someCall(c: 12, d: 34) { print("foo") }
102224
// comment
103225
b: {
104226
print("bar")
105227
}
106-
107-
func invalidCode() {
108-
print("blah")
109-
}

0 commit comments

Comments
 (0)