Skip to content

Commit 13d5a8a

Browse files
author
Nathan Hawes
authored
Merge pull request #30870 from nathawes/mutiple-catch-pattern-indentation
[SourceKit/CodeFormat] Column-align multiple patterns in catch clauses
2 parents bae3146 + 19d6eff commit 13d5a8a

File tree

4 files changed

+95
-24
lines changed

4 files changed

+95
-24
lines changed

lib/IDE/Formatting.cpp

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,38 +1809,27 @@ class FormatWalker : public ASTWalker {
18091809

18101810
auto *CS = dyn_cast<CaseStmt>(S);
18111811
if (CS && CS->getParentKind() == CaseParentKind::Switch) {
1812-
if (TrailingTarget && !TrailingTarget->isEmpty())
1813-
return None;
1814-
18151812
SourceLoc CaseLoc = CS->getLoc();
18161813
if (!SM.isBeforeInBuffer(CaseLoc, TargetLocation))
18171814
return None;
18181815

18191816
SourceRange LabelItemsRange = CS->getLabelItemsRange();
18201817
SourceLoc ColonLoc = getLocIfKind(SM, LabelItemsRange.End, tok::colon);
18211818

1822-
if (isTargetContext(CaseLoc, ColonLoc)) {
1823-
ListAligner Aligner(SM, TargetLocation, CaseLoc, CaseLoc, ColonLoc);
1824-
for (auto &Elem: CS->getCaseLabelItems()) {
1825-
SourceRange ElemRange = Elem.getSourceRange();
1826-
Aligner.updateAlignment(ElemRange, CS);
1827-
if (isTargetContext(ElemRange)) {
1828-
Aligner.setAlignmentIfNeeded(CtxOverride);
1829-
return IndentContext {
1830-
ElemRange.Start,
1831-
!OutdentChecker::hasOutdent(SM, ElemRange, CS)
1832-
};
1833-
}
1834-
}
1835-
return Aligner.getContextAndSetAlignment(CtxOverride);
1836-
}
1837-
if (ColonLoc.isValid() && isTargetContext(ColonLoc, SourceLoc())) {
1819+
if (auto Ctx = getIndentContextFromCaseItems(CS, /*CloseLoc=*/ColonLoc))
1820+
return Ctx;
1821+
1822+
if (ColonLoc.isValid() && isTargetContext(ColonLoc, SourceLoc()) &&
1823+
(!TrailingTarget || TrailingTarget->isEmpty())) {
18381824
SourceRange ColonToEnd = SourceRange(ColonLoc, CS->getEndLoc());
18391825
return IndentContext {
18401826
CaseLoc,
18411827
!OutdentChecker::hasOutdent(SM, ColonToEnd, CS)
18421828
};
18431829
}
1830+
1831+
if (TrailingTarget)
1832+
return None;
18441833
return IndentContext {CaseLoc, false};
18451834
}
18461835

@@ -1858,13 +1847,21 @@ class FormatWalker : public ASTWalker {
18581847
}
18591848

18601849
if (CS && CS->getParentKind() == CaseParentKind::DoCatch) {
1861-
if (auto *BS = dyn_cast<BraceStmt>(CS->getBody())) {
1862-
if (auto Ctx = getIndentContextFrom(BS, CS->getStartLoc()))
1863-
return Ctx;
1864-
}
1850+
SourceLoc CatchLoc = CS->getLoc();
1851+
SourceLoc L;
1852+
1853+
auto *BS = dyn_cast<BraceStmt>(CS->getBody());
1854+
if (BS) L = getLocIfKind(SM, BS->getLBraceLoc(), tok::l_brace);
1855+
1856+
if (auto Ctx = getIndentContextFromCaseItems(CS, /*CloseLoc=*/L))
1857+
return Ctx;
1858+
1859+
if (auto Ctx = getIndentContextFrom(BS, CS->getStartLoc()))
1860+
return Ctx;
1861+
18651862
if (TrailingTarget)
18661863
return None;
1867-
return IndentContext {CS->getStartLoc(), true};
1864+
return IndentContext {CatchLoc, false};
18681865
}
18691866

18701867
if (auto *IS = dyn_cast<IfStmt>(S)) {
@@ -2086,6 +2083,33 @@ class FormatWalker : public ASTWalker {
20862083
return Bounds;
20872084
}
20882085

2086+
Optional<IndentContext>
2087+
getIndentContextFromCaseItems(CaseStmt *CS, SourceLoc CloseLoc) {
2088+
SourceLoc IntroducerLoc = CS->getLoc();
2089+
if (!isTargetContext(IntroducerLoc, CloseLoc))
2090+
return None;
2091+
2092+
ListAligner Aligner(SM, TargetLocation, IntroducerLoc, IntroducerLoc,
2093+
CloseLoc);
2094+
for (auto &Elem: CS->getCaseLabelItems()) {
2095+
// Skip the implicit 'error' pattern for empty catch CaseStmts.
2096+
if ((!Elem.getPattern() || Elem.getPattern()->isImplicit()) &&
2097+
Elem.getWhereLoc().isInvalid())
2098+
continue;
2099+
2100+
SourceRange ElemRange = Elem.getSourceRange();
2101+
Aligner.updateAlignment(ElemRange, CS);
2102+
if (isTargetContext(ElemRange)) {
2103+
Aligner.setAlignmentIfNeeded(CtxOverride);
2104+
return IndentContext {
2105+
ElemRange.Start,
2106+
!OutdentChecker::hasOutdent(SM, ElemRange, CS)
2107+
};
2108+
}
2109+
}
2110+
return Aligner.getContextAndSetAlignment(CtxOverride);
2111+
}
2112+
20892113
#pragma mark Expression indent contexts
20902114

20912115
Optional<IndentContext>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
do {
2+
print("hello")
3+
} catch MyErr.a(let code),
4+
MyErr.b(let code),
5+
6+
// RUN: %sourcekitd-test -req=format -line=5 -length=1 %s | %FileCheck --strict-whitespace %s
7+
// CHECK: key.sourcetext: " "
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
do {
2+
print("hello")
3+
} catch MyErr.a(let code),
4+
MyErr.b(let code)
5+
6+
// RUN: %sourcekitd-test -req=format -line=5 -length=1 %s | %FileCheck --strict-whitespace %s
7+
// CHECK: key.sourcetext: ""

test/swift-indent/basic.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,3 +945,36 @@ IncrementedFirst++
945945
}++
946946
.baz()
947947

948+
949+
// Multiple patterns in catch should align exactly.
950+
951+
do {
952+
print("hello")
953+
} catch MyErr.a(let code, let message),
954+
MyErr.b(
955+
let code,
956+
let message
957+
),
958+
MyErr.c(let code, let message) {
959+
print("ahhh!")
960+
}
961+
962+
do {
963+
throw MyErr.a
964+
} catch where foo == 0,
965+
where bar == 1 {
966+
}
967+
968+
do
969+
{
970+
print("hello")
971+
}
972+
catch MyErr.a(let code, let message),
973+
MyErr.b(
974+
let code,
975+
let message
976+
),
977+
MyErr.c(let code, let message)
978+
{
979+
print("ahhh!")
980+
}

0 commit comments

Comments
 (0)