Skip to content

Commit 46aab36

Browse files
committed
Minor fixes to BasicFormat that I found while using it to run CodeGeneration
1 parent 1a555cf commit 46aab36

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

CodeGeneration/Sources/Utils/CodeGenerationFormat.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public class CodeGenerationFormat: BasicFormat {
106106
}
107107

108108
private func formatChildrenSeparatedByNewline<SyntaxType: SyntaxProtocol>(children: SyntaxChildren, elementType: SyntaxType.Type) -> [SyntaxType] {
109-
pushIndentationLevel(increasingIndentationBy: indentationWidth)
109+
increaseIndentationLevel()
110110
var formattedChildren = children.map {
111111
self.visit($0).as(SyntaxType.self)!
112112
}
@@ -117,7 +117,7 @@ public class CodeGenerationFormat: BasicFormat {
117117
return $0.with(\.leadingTrivia, indentedNewline + $0.leadingTrivia)
118118
}
119119
}
120-
popIndentationLevel()
120+
decreaseIndentationLevel()
121121
if !formattedChildren.isEmpty {
122122
formattedChildren[formattedChildren.count - 1] = formattedChildren[formattedChildren.count - 1].with(\.trailingTrivia, indentedNewline)
123123
}

Sources/SwiftBasicFormat/BasicFormat.swift

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ open class BasicFormat: SyntaxRewriter {
1818

1919
/// As we reach a new indendation level, its indentation will be added to the
2020
/// stack. As we exit that indentation level, the indendation will be popped.
21-
public var indentationStack: [Trivia]
21+
/// `isUserDefined` is `true` if the indentation was inferred from something
22+
/// the user provided manually instead of being inferred from the nesting
23+
/// level.
24+
public var indentationStack: [(indentation: Trivia, isUserDefined: Bool)]
2225

2326
/// The trivia by which tokens should currently be indented.
2427
public var currentIndentationLevel: Trivia {
2528
// `popIndentationLevel` guarantees that there is always one item on the stack.
26-
return indentationStack.last!
29+
return indentationStack.last!.indentation
2730
}
2831

2932
/// For every token that is being put on a new line but did not have
@@ -39,16 +42,16 @@ open class BasicFormat: SyntaxRewriter {
3942

4043
public init(indentationWidth: Trivia = .spaces(4), initialIndentation: Trivia = []) {
4144
self.indentationWidth = indentationWidth
42-
self.indentationStack = [initialIndentation]
45+
self.indentationStack = [(indentation: initialIndentation, isUserDefined: false)]
4346
}
4447

4548
// MARK: - Updating indentation level
4649

47-
public func pushIndentationLevel(increasingIndentationBy: Trivia) {
48-
indentationStack.append(currentIndentationLevel + increasingIndentationBy)
50+
public func increaseIndentationLevel() {
51+
indentationStack.append((currentIndentationLevel + indentationWidth, false))
4952
}
5053

51-
public func popIndentationLevel() {
54+
public func decreaseIndentationLevel() {
5255
precondition(indentationStack.count > 1, "Popping more indentation levels than have been pushed")
5356
indentationStack.removeLast()
5457
}
@@ -60,16 +63,17 @@ open class BasicFormat: SyntaxRewriter {
6063
!tokenIndentation.isEmpty
6164
{
6265
// If the first token in this block is indented, infer the indentation level from it.
63-
pushIndentationLevel(increasingIndentationBy: tokenIndentation)
66+
let lastNonUserDefinedIndentation = indentationStack.last(where: { !$0.isUserDefined })!.indentation
67+
indentationStack.append((indentation: lastNonUserDefinedIndentation + tokenIndentation, isUserDefined: true))
6468
} else {
65-
pushIndentationLevel(increasingIndentationBy: indentationWidth)
69+
increaseIndentationLevel()
6670
}
6771
}
6872
}
6973

7074
open override func visitPost(_ node: Syntax) {
7175
if requiresIndent(node) {
72-
popIndentationLevel()
76+
decreaseIndentationLevel()
7377
}
7478
}
7579

@@ -197,7 +201,25 @@ open class BasicFormat: SyntaxRewriter {
197201
// don't add a leading newline to the file.
198202
return true
199203
}
200-
return previousToken.trailingTrivia.endsWithNewline
204+
if previousToken.trailingTrivia.pieces.last?.isNewline ?? false {
205+
return true
206+
}
207+
if case .stringSegment(let segment) = previousToken.tokenKind, segment.last?.isNewline ?? false {
208+
return true
209+
}
210+
return false
211+
}()
212+
213+
lazy var previousTokenIsStringLiteralEndingInNewline: Bool = {
214+
guard let previousToken = previousToken else {
215+
// Assume that the start of the tree is equivalent to a newline so we
216+
// don't add a leading newline to the file.
217+
return true
218+
}
219+
if case .stringSegment(let segment) = previousToken.tokenKind, segment.last?.isNewline ?? false {
220+
return true
221+
}
222+
return false
201223
}()
202224

203225
lazy var nextTokenWillStartWithNewline: Bool = {
@@ -270,7 +292,7 @@ open class BasicFormat: SyntaxRewriter {
270292
trailingTriviaIndentation = anchorPointIndentation
271293
}
272294

273-
leadingTrivia = leadingTrivia.indented(indentation: leadingTriviaIndentation, isOnNewline: false)
295+
leadingTrivia = leadingTrivia.indented(indentation: leadingTriviaIndentation, isOnNewline: previousTokenIsStringLiteralEndingInNewline)
274296
trailingTrivia = trailingTrivia.indented(indentation: trailingTriviaIndentation, isOnNewline: false)
275297

276298
leadingTrivia = leadingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: false)

0 commit comments

Comments
 (0)