@@ -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