Skip to content

Commit defac25

Browse files
author
Nathan Hawes
authored
Merge pull request #31941 from nathawes/pattern-binding-decl-indentation
[SourceKit/CodeFormat] Don't column-align PatternBindingDecl entries in certain cases.
2 parents cae7a70 + 99edbf0 commit defac25

File tree

4 files changed

+81
-22
lines changed

4 files changed

+81
-22
lines changed

lib/IDE/Formatting.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -993,9 +993,14 @@ class ListAligner {
993993
SourceLoc AlignLoc;
994994
SourceLoc LastEndLoc;
995995
bool HasOutdent = false;
996+
bool BreakAlignment = false;
996997

997998
public:
998999

1000+
/// Don't column-align if any element starts on the same line as IntroducerLoc
1001+
/// but ends on a later line.
1002+
bool BreakAlignmentIfSpanning = false;
1003+
9991004
/// Constructs a new \c ListAligner for a list bounded by separate opening and
10001005
/// closing tokens, e.g. tuples, array literals, parameter lists, etc.
10011006
///
@@ -1068,8 +1073,11 @@ class ListAligner {
10681073
assert(Range.isValid());
10691074
LastEndLoc = Range.End;
10701075

1071-
HasOutdent |= isOnSameLine(SM, IntroducerLoc, Range.Start) &&
1072-
OutdentChecker::hasOutdent(SM, Range, WalkableParent);
1076+
if (isOnSameLine(SM, IntroducerLoc, Range.Start)) {
1077+
HasOutdent |= OutdentChecker::hasOutdent(SM, Range, WalkableParent);
1078+
if (BreakAlignmentIfSpanning)
1079+
BreakAlignment |= !isOnSameLine(SM, IntroducerLoc, Range.End);
1080+
}
10731081

10741082
if (HasOutdent || !SM.isBeforeInBuffer(Range.Start, TargetLoc))
10751083
return;
@@ -1128,7 +1136,7 @@ class ListAligner {
11281136
}
11291137

11301138
bool ShouldIndent = shouldIndent(HasTrailingComma, TargetIsTrailing);
1131-
if (ShouldIndent && AlignLoc.isValid()) {
1139+
if (ShouldIndent && !BreakAlignment && AlignLoc.isValid()) {
11321140
setAlignmentIfNeeded(Override);
11331141
return IndentContext {AlignLoc, false, IndentContext::Exact};
11341142
}
@@ -1140,7 +1148,7 @@ class ListAligner {
11401148
/// This should be called before returning an \c IndentContext for a subrange
11411149
/// of the list.
11421150
void setAlignmentIfNeeded(ContextOverride &Override) {
1143-
if (HasOutdent || AlignLoc.isInvalid())
1151+
if (HasOutdent || BreakAlignment || AlignLoc.isInvalid())
11441152
return;
11451153
Override.setExact(SM, AlignLoc);
11461154
}
@@ -1676,6 +1684,36 @@ class FormatWalker : public ASTWalker {
16761684
SourceLoc ContextLoc = PBD->getStartLoc(), IntroducerLoc = PBD->getLoc();
16771685

16781686
ListAligner Aligner(SM, TargetLocation, ContextLoc, IntroducerLoc);
1687+
1688+
// Don't column align PBD entries if any entry spans from the same line as
1689+
// the IntroducerLoc (var/let) to another line. E.g.
1690+
//
1691+
// let foo = someItem
1692+
// .getValue(), // Column-alignment looks ok here, but...
1693+
// bar = otherItem
1694+
// .getValue()
1695+
//
1696+
// getAThing()
1697+
// .andDoStuffWithIt()
1698+
// let foo = someItem
1699+
// .getValue() // looks over-indented here, which is more common...
1700+
// getOtherThing()
1701+
// .andDoStuffWithIt()
1702+
//
1703+
// getAThing()
1704+
// .andDoStuffWithIt()
1705+
// let foo = someItem
1706+
// .getValue() // so break column alignment in this case...
1707+
// doOtherThing()
1708+
//
1709+
// let foo = someItem.getValue(),
1710+
// bar = otherItem.getValue() // but not in this case.
1711+
//
1712+
// Using this rule, rather than handling single and multi-entry PBDs
1713+
// differently, ensures that the as-typed-out indentation matches the
1714+
// re-indented indentation for multi-entry PBDs.
1715+
Aligner.BreakAlignmentIfSpanning = true;
1716+
16791717
for (auto I: range(PBD->getNumPatternEntries())) {
16801718
SourceRange EntryRange = PBD->getEqualLoc(I);
16811719
VarDecl *SingleVar = nullptr;

test/SourceKit/CodeFormat/indent-multiline-string.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ this is line1,
1717
// CHECK: key.sourcetext: "this is line1,"
1818
// CHECK: key.sourcetext: " this is line2,"
1919
// CHECK: key.sourcetext: "\"\"\""
20-
// CHECK: key.sourcetext: " \"content\""
20+
// CHECK: key.sourcetext: " \"content\""

test/SourceKit/CodeFormat/rdar_32789463.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ $
1212
1313
// CHECK: key.sourcetext: "struct $ {"
1414
// CHECK: key.sourcetext: " let $: <#Type#>"
15-
// CHECK: key.sourcetext: " = foo(\"foo \\($) bar\") {"
15+
// CHECK: key.sourcetext: " = foo(\"foo \\($) bar\") {"
1616
// CHECK: key.sourcetext: " $"

test/swift-indent/basic.swift

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ test(arg1: 1,
6868
}
6969

7070
let x = [1, 2, 3]
71-
.filter {$0 < $1}
72-
.filter {$0 < $1}
73-
.filter {$0 < $1}
71+
.filter {$0 < $1}
72+
.filter {$0 < $1}
73+
.filter {$0 < $1}
7474

7575
bax(34949494949)
7676
.foo(a: Int,
@@ -141,11 +141,11 @@ if #available(
141141
// do the same.
142142
//
143143
let _ = []
144-
.map {
145-
f {
146-
print()
147-
} ?? 0
148-
}
144+
.map {
145+
f {
146+
print()
147+
} ?? 0
148+
}
149149

150150
basename
151151
.foo(a: Int,
@@ -234,10 +234,10 @@ let arrayC = [2]
234234
let arrayD = [3]
235235

236236
let array1 =
237-
arrayA +
238-
arrayB +
239-
arrayC +
240-
arrayD
237+
arrayA +
238+
arrayB +
239+
arrayC +
240+
arrayD
241241

242242
array1 =
243243
arrayA +
@@ -254,9 +254,9 @@ arrayC +
254254
arrayD
255255

256256
let array2 = arrayA +
257-
arrayB +
258-
arrayC +
259-
arrayD
257+
arrayB +
258+
arrayC +
259+
arrayD
260260

261261

262262
// Comments should not break exact alignment, and leading comments should be aligned, rather than the label.
@@ -867,7 +867,7 @@ func foo(
867867
) {}
868868

869869
var (d, e):
870-
(Int, Int) = (1, 3),
870+
(Int, Int) = (1, 3),
871871
(f, g): (
872872
Int,
873873
Int
@@ -1015,3 +1015,24 @@ catch MyErr.a(let code, let message),
10151015
{
10161016
print("ahhh!")
10171017
}
1018+
1019+
// Pattern binding decls should only column-align if no element spans from the first line to beyond it.
1020+
1021+
public let x = 10,
1022+
y = 20
1023+
1024+
private var firstThing = 20,
1025+
secondThing = item
1026+
.filter {},
1027+
thirdThing = 42
1028+
1029+
public let myVar = itemWithALongName
1030+
.filter { $0 >= $1 && $0 - $1 < 50}
1031+
1032+
public let first = 45, second = itemWithALongName
1033+
.filter { $0 >= $1 && $0 - $1 < 50}
1034+
1035+
private var secondThing = item
1036+
.filter {},
1037+
firstThing = 20,
1038+
thirdThing = 56

0 commit comments

Comments
 (0)