@@ -18,12 +18,15 @@ open class BasicFormat: SyntaxRewriter {
18
18
19
19
/// As we reach a new indendation level, its indentation will be added to the
20
20
/// 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 ) ]
22
25
23
26
/// The trivia by which tokens should currently be indented.
24
27
public var currentIndentationLevel : Trivia {
25
28
// `popIndentationLevel` guarantees that there is always one item on the stack.
26
- return indentationStack. last!
29
+ return indentationStack. last!. indentation
27
30
}
28
31
29
32
/// For every token that is being put on a new line but did not have
@@ -39,16 +42,16 @@ open class BasicFormat: SyntaxRewriter {
39
42
40
43
public init ( indentationWidth: Trivia = . spaces( 4 ) , initialIndentation: Trivia = [ ] ) {
41
44
self . indentationWidth = indentationWidth
42
- self . indentationStack = [ initialIndentation]
45
+ self . indentationStack = [ ( indentation : initialIndentation, isUserDefined : false ) ]
43
46
}
44
47
45
48
// MARK: - Updating indentation level
46
49
47
- public func pushIndentationLevel ( increasingIndentationBy : Trivia ) {
48
- indentationStack. append ( currentIndentationLevel + increasingIndentationBy )
50
+ public func increaseIndentationLevel ( ) {
51
+ indentationStack. append ( ( currentIndentationLevel + indentationWidth , false ) )
49
52
}
50
53
51
- public func popIndentationLevel ( ) {
54
+ public func decreaseIndentationLevel ( ) {
52
55
precondition ( indentationStack. count > 1 , " Popping more indentation levels than have been pushed " )
53
56
indentationStack. removeLast ( )
54
57
}
@@ -60,16 +63,17 @@ open class BasicFormat: SyntaxRewriter {
60
63
!tokenIndentation. isEmpty
61
64
{
62
65
// 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 ) )
64
68
} else {
65
- pushIndentationLevel ( increasingIndentationBy : indentationWidth )
69
+ increaseIndentationLevel ( )
66
70
}
67
71
}
68
72
}
69
73
70
74
open override func visitPost( _ node: Syntax ) {
71
75
if requiresIndent ( node) {
72
- popIndentationLevel ( )
76
+ decreaseIndentationLevel ( )
73
77
}
74
78
}
75
79
@@ -197,7 +201,25 @@ open class BasicFormat: SyntaxRewriter {
197
201
// don't add a leading newline to the file.
198
202
return true
199
203
}
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
201
223
} ( )
202
224
203
225
lazy var nextTokenWillStartWithNewline : Bool = {
@@ -270,7 +292,7 @@ open class BasicFormat: SyntaxRewriter {
270
292
trailingTriviaIndentation = anchorPointIndentation
271
293
}
272
294
273
- leadingTrivia = leadingTrivia. indented ( indentation: leadingTriviaIndentation, isOnNewline: false )
295
+ leadingTrivia = leadingTrivia. indented ( indentation: leadingTriviaIndentation, isOnNewline: previousTokenIsStringLiteralEndingInNewline )
274
296
trailingTrivia = trailingTrivia. indented ( indentation: trailingTriviaIndentation, isOnNewline: false )
275
297
276
298
leadingTrivia = leadingTrivia. trimmingTrailingWhitespaceBeforeNewline ( isBeforeNewline: false )
0 commit comments