Skip to content

Commit 3018163

Browse files
committed
Fix indentation when there is a leading new line
1 parent e657dc0 commit 3018163

File tree

12 files changed

+759
-642
lines changed

12 files changed

+759
-642
lines changed

Sources/SwiftSyntax/Trivia.swift.gyb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,24 @@ extension TriviaPiece: CustomDebugStringConvertible {
7777
}
7878
}
7979

80+
extension TriviaPiece {
81+
/// Returns true if the trivia is `.newlines`, `.carriageReturns` or `.carriageReturnLineFeeds`
82+
public var isNewline: Bool {
83+
switch self {
84+
case .newlines,
85+
.carriageReturns,
86+
.carriageReturnLineFeeds:
87+
return true
88+
default:
89+
return false
90+
}
91+
}
92+
}
93+
8094
/// A collection of leading or trailing trivia. This is the main data structure
8195
/// for thinking about trivia.
8296
public struct Trivia {
83-
let pieces: [TriviaPiece]
97+
public let pieces: [TriviaPiece]
8498

8599
/// Creates Trivia with the provided underlying pieces.
86100
public init(pieces: [TriviaPiece]) {

Sources/SwiftSyntax/gyb_generated/Trivia.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,24 @@ extension TriviaPiece: CustomDebugStringConvertible {
123123
}
124124
}
125125

126+
extension TriviaPiece {
127+
/// Returns true if the trivia is `.newlines`, `.carriageReturns` or `.carriageReturnLineFeeds`
128+
public var isNewline: Bool {
129+
switch self {
130+
case .newlines,
131+
.carriageReturns,
132+
.carriageReturnLineFeeds:
133+
return true
134+
default:
135+
return false
136+
}
137+
}
138+
}
139+
126140
/// A collection of leading or trailing trivia. This is the main data structure
127141
/// for thinking about trivia.
128142
public struct Trivia {
129-
let pieces: [TriviaPiece]
143+
public let pieces: [TriviaPiece]
130144

131145
/// Creates Trivia with the provided underlying pieces.
132146
public init(pieces: [TriviaPiece]) {

Sources/SwiftSyntaxBuilder/BuildableCollectionNodes.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public struct ${type.buildable()}: ExpressibleByArrayLiteral, SyntaxBuildable, $
6565
})
6666
% end
6767
if let leadingTrivia = leadingTrivia {
68-
return result.withLeadingTrivia(leadingTrivia + (result.leadingTrivia ?? []))
68+
return result.withLeadingTrivia((leadingTrivia + (result.leadingTrivia ?? [])).addingSpacingAfterNewlinesIfNeeded())
6969
} else {
7070
return result
7171
}

Sources/SwiftSyntaxBuilder/BuildableNodes.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public struct ${type.buildable()}${conformance_clause(conformances)} {
120120
${',\n '.join(['%s: %s' % (child.name(), child.generate_expr_build_syntax_node(child.name(), 'format')) for child in children])}
121121
)
122122
let combinedLeadingTrivia = leadingTrivia + (additionalLeadingTrivia ?? []) + (result.leadingTrivia ?? [])
123-
return result.withLeadingTrivia(combinedLeadingTrivia)
123+
return result.withLeadingTrivia(combinedLeadingTrivia.addingSpacingAfterNewlinesIfNeeded())
124124
}
125125

126126
/// Conformance to `${base_type.buildable()}`.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
15+
extension Trivia {
16+
/// Re-indents trivia that form a block comment to have consistent indentation.
17+
///
18+
/// If the trivia start with a newline (i.e. the first non-whitespace trivia is on a fresh line) and that newline starts with spacing, the same spacing is applied to all the following lines. For example.
19+
/// ```
20+
/// // first line
21+
/// // second line
22+
/// // third line
23+
/// ```
24+
/// picks up the indentation from the first line and transforms the trivia to
25+
/// ```
26+
/// // first line
27+
/// // second line
28+
/// // third line
29+
/// ```
30+
func addingSpacingAfterNewlinesIfNeeded() -> Trivia {
31+
var updatedTriviaPieces = self.pieces
32+
if updatedTriviaPieces.count > 2,
33+
updatedTriviaPieces[0].isNewline,
34+
let indentation = self.makeIndentation(trivia: updatedTriviaPieces[1]) {
35+
36+
for i in (2..<updatedTriviaPieces.count).reversed() where updatedTriviaPieces[i].isNewline {
37+
updatedTriviaPieces.insert(indentation, at: i + 1)
38+
}
39+
}
40+
41+
return Trivia(pieces: updatedTriviaPieces)
42+
}
43+
44+
private func makeIndentation(trivia: TriviaPiece) -> TriviaPiece? {
45+
switch trivia {
46+
case .spaces,
47+
.tabs: return trivia
48+
default:
49+
return nil
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)