Skip to content

Commit 2a93296

Browse files
author
Nathan Hawes
committed
[SourceKit/CodeFormat] Simplify ContextOverride a little, and only propagate ContextLocs when necessary.
We don't actually need to set a ContextOverride unless the ContextLoc and L paren/brace/bracket are on different lines. Combined with the fact that we only set them if the L and R parens/braces/brackets are on different lines to, it guarantees there will be at most one override that's applicable on any given line, which lets us simplify the logic somewhat.
1 parent aedafe9 commit 2a93296

File tree

2 files changed

+46
-44
lines changed

2 files changed

+46
-44
lines changed

lib/IDE/Formatting.cpp

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -162,20 +162,25 @@ class ContextOverride {
162162
/// The location after which this override takes effect.
163163
SourceLoc ApplicableFrom;
164164
};
165+
166+
/// The current override, if set.
165167
Optional<Override> Value;
166168

167169
public:
170+
/// Clears this override.
171+
void clear() { Value = None; }
172+
168173
/// Sets this override to make an IndentContext indent relative to the exact
169174
/// column of AlignLoc if the IndentContext's ContextLoc is >= AlignLoc and
170175
/// on the same line.
171176
void setExact(SourceManager &SM, SourceLoc AlignLoc) {
172177
Value = {AlignLoc, IndentContext::Exact, AlignLoc};
173178
}
174179

175-
/// Sets this override to propagate the given ContextLoc along to any
180+
/// Sets this override to propagate the given ContextLoc and Kind along to any
176181
/// IndentContext with a ContextLoc >= L and on the same line. If this
177182
/// override's existing value applies to the provided ContextLoc, its
178-
/// ContextLoc is propagated instead.
183+
/// ContextLoc and Kind are propagated instead.
179184
///
180185
/// This propagation is necessary for cases like the trailing closure of 'bar'
181186
/// in the example below. It's direct ContextLoc is 'bar', but we want
@@ -197,55 +202,47 @@ class ContextOverride {
197202
if (R.isValid() && isOnSameLine(SM, L, R))
198203
return ContextLoc;
199204

200-
Override NewValue = {ContextLoc, Kind, L};
201-
if (Value) {
202-
// If the existing override applies to the same line, it's ContextLoc
203-
// should override this ContextLoc - don't propagate the intermediary.
204-
if (isOnSameLine(SM, Value->ApplicableFrom, NewValue.ApplicableFrom)) {
205-
assert(!SM.isBeforeInBuffer(NewValue.ContextLoc,
206-
Value->ContextLoc) &&
207-
"children walked before parents?");
208-
return ContextLoc;
209-
}
210-
// Apply the existing value to NewValue before we overwrite it so its
211-
// ContextLoc propagates.
212-
applyIfNeeded(SM, NewValue.ContextLoc, NewValue.Kind);
213-
}
214-
Value = NewValue;
215-
return Value->ContextLoc;
205+
// Similarly if the ContextLoc and L are on the same line, there's no need
206+
// to propagate. Overrides applicable to ContextLoc will already apply
207+
// to child ranges on the same line as L.
208+
if (isOnSameLine(SM, ContextLoc, L))
209+
return ContextLoc;
210+
211+
applyIfNeeded(SM, ContextLoc, Kind);
212+
Value = {ContextLoc, Kind, L};
213+
return ContextLoc;
216214
}
217215

218216
/// Applies the overriding ContextLoc and Kind to the given IndentContext if it
219217
/// starts after ApplicableFrom and on the same line.
220218
void applyIfNeeded(SourceManager &SM, IndentContext &Ctx) {
219+
// Exactly aligned indent contexts should always set a matching exact
220+
// alignment context override so child braces/parens/brackets are indented
221+
// correctly. If the given innermost indent context is Exact and the
222+
// override doesn't match its Kind and ContextLoc, something is wrong.
223+
assert((Ctx.Kind != IndentContext::Exact ||
224+
(Value && Value->Kind == IndentContext::Exact &&
225+
Value->ContextLoc == Ctx.ContextLoc)) &&
226+
"didn't set override ctx when exact innermost context was set?");
227+
221228
applyIfNeeded(SM, Ctx.ContextLoc, Ctx.Kind);
222229
}
223230

224-
/// Applies the overriding ContextLoc and Kind to the given ContextLoc and
225-
/// Kind if the given ContextLoc starts after ApplicableFrom and on the same
226-
/// line.
231+
/// Applies the overriding ContextLoc and Kind to the given Override if its
232+
/// ContextLoc starts after ApplicableFrom and on the same line.
227233
void applyIfNeeded(SourceManager &SM, SourceLoc &ContextLoc,
228234
IndentContext::ContextKind &Kind) {
229-
if (!Value)
230-
return;
231-
232-
if (!isOnSameLine(SM, ContextLoc, Value->ApplicableFrom) ||
233-
SM.isBeforeInBuffer(ContextLoc, Value->ApplicableFrom))
235+
if (!isApplicableTo(SM, ContextLoc))
234236
return;
235-
236-
// Exactly aligned indent contexts should always set a matching exact
237-
// alignment context override so child braces/parens/brackets are indented
238-
// correctly. If the given innermost indent context is Exact and the
239-
// override doesn't match its Kind and ContextLoc, something is wrong.
240-
assert((Kind != IndentContext::Exact ||
241-
(Value->Kind == IndentContext::Exact &&
242-
ContextLoc == Value->ContextLoc)) &&
243-
"didn't set override ctx when exact innermost context was set?");
244237
ContextLoc = Value->ContextLoc;
245238
Kind = Value->Kind;
246239
}
247240

248-
void clear() { Value = None; }
241+
private:
242+
bool isApplicableTo(SourceManager &SM, SourceLoc Loc) const {
243+
return Value && isOnSameLine(SM, Loc, Value->ApplicableFrom) &&
244+
!SM.isBeforeInBuffer(Loc, Value->ApplicableFrom);
245+
}
249246
};
250247

251248

@@ -826,18 +823,23 @@ class OutdentChecker: protected RangeWalker {
826823
}
827824

828825
SourceLoc propagateContextLocs(SourceLoc ContextLoc, SourceLoc L, SourceLoc R) {
826+
bool HasSeparateContext = !isOnSameLine(SM, L, ContextLoc);
827+
829828
// Update ContextLoc for the currently active override on its line.
830-
ContextOverride &CtxOverride = getOverrideForLineContaining(ContextLoc);
829+
ContextOverride &Upstream = getOverrideForLineContaining(ContextLoc);
831830
IndentContext::ContextKind Kind = IndentContext::LineStart;
832-
CtxOverride.applyIfNeeded(SM, ContextLoc, Kind);
831+
Upstream.applyIfNeeded(SM, ContextLoc, Kind);
833832

834-
// If ContextLoc is L there's nothing to propagate.
835-
if (L == ContextLoc)
833+
// If the original ContextLoc and L were on the same line, there's no need
834+
// to propagate anything. Child ranges later on the same line will pick up
835+
// whatever override we picked up above anyway, and if there wasn't
836+
// one, their normal ContextLoc should already be correct.
837+
if (!HasSeparateContext)
836838
return ContextLoc;
837839

838-
// Set an override to propagate the context loc onto the line of L.
839-
ContextOverride &Propagated = getOverrideForLineContaining(L);
840-
ContextLoc = Propagated.propagateContext(SM, ContextLoc,
840+
// Set an override to propagate the context loc onto the line of L.
841+
ContextOverride &Downstream = getOverrideForLineContaining(L);
842+
ContextLoc = Downstream.propagateContext(SM, ContextLoc,
841843
Kind, L, R);
842844
return ContextLoc;
843845
}

test/SourceKit/CodeFormat/indent-trailing/trailing-string-element.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ let foo = Bar.Stuff(
33
description: "No \(thing) was found at path \(path)"
44

55
// RUN: %sourcekitd-test -req=format -line=4 -length=1 %s | %FileCheck --strict-whitespace %s
6-
// CHECK: key.sourcetext: ""
6+
// CHECK: key.sourcetext: ""

0 commit comments

Comments
 (0)