Skip to content

Commit bb38b33

Browse files
committed
Review update swiftlang#1
1 parent 0c014dc commit bb38b33

File tree

6 files changed

+65
-43
lines changed

6 files changed

+65
-43
lines changed

Sources/SwiftSyntax/RawSyntax.swift

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal struct RawSyntaxData {
2020
case layout(Layout)
2121
}
2222

23-
/// Token tyoically created with `SyntaxFactory.makeToken()`.
23+
/// Token typically created with `SyntaxFactory.makeToken()`.
2424
struct MaterializedToken {
2525
var tokenKind: RawTokenKind
2626
var tokenText: SyntaxText
@@ -34,6 +34,7 @@ internal struct RawSyntaxData {
3434
var kind: SyntaxKind
3535
var layout: RawSyntaxBuffer
3636
var byteLength: Int
37+
/// Number of nodes in this subtree, excluding this node.
3738
var descendantCount: Int
3839
}
3940

@@ -117,7 +118,7 @@ extension RawSyntax {
117118
}
118119
}
119120

120-
/// Leading trivia text of this node if this node is a token. 'nil' otherwise.
121+
/// The UTF-8 byte length of the leading trivia, assuming this node is a token.
121122
var tokenLeadingTriviaByteLength: Int {
122123
switch rawData.payload {
123124
case .materializedToken(let dat):
@@ -127,7 +128,7 @@ extension RawSyntax {
127128
}
128129
}
129130

130-
/// Leading trivia text of this node if this node is a token. 'nil' otherwise.
131+
/// The UTF-8 byte length of the trailing trivia, assuming this node is a token.
131132
var tokenTrailingTriviaByteLength: Int {
132133
switch rawData.payload {
133134
case .materializedToken(let dat):
@@ -142,7 +143,7 @@ extension RawSyntax {
142143
case .materializedToken(let dat):
143144
return dat.leadingTrivia
144145
case .layout(_):
145-
preconditionFailure("tokenLeadingRawTriviaPieces is called on non-token raw syntax")
146+
preconditionFailure("'tokenLeadingRawTriviaPieces' is called on non-token raw syntax")
146147
}
147148
}
148149

@@ -151,7 +152,7 @@ extension RawSyntax {
151152
case .materializedToken(let dat):
152153
return dat.trailingTrivia
153154
case .layout(_):
154-
preconditionFailure("tokenTrailingRawTriviaPieces is called on non-token raw syntax")
155+
preconditionFailure("'tokenTrailingRawTriviaPieces' is called on non-token raw syntax")
155156
}
156157
}
157158
}
@@ -211,11 +212,22 @@ extension RawSyntax {
211212
}
212213

213214
var presence: SourcePresence {
214-
let isMissing = (self.byteLength == 0 &&
215-
!self.isCollection &&
216-
!self.isUnknown &&
217-
!(isToken && self.rawTokenKind == .eof))
218-
return isMissing ? .missing : .present
215+
if self.byteLength != 0 {
216+
// The node has source text associated with it. It's present.
217+
return .present
218+
}
219+
if self.isCollection || self.isUnknown {
220+
// We always consider collections 'present' because they can just be empty.
221+
return .present
222+
}
223+
if isToken && self.rawTokenKind == .eof {
224+
// The end of file token never has source code associated with it but we
225+
// still consider it valid.
226+
return .present
227+
}
228+
229+
// If none of the above apply, the node is missing.
230+
return .missing
219231
}
220232

221233
/// The "width" of the node.
@@ -241,37 +253,29 @@ extension RawSyntax {
241253
}
242254
}
243255

244-
/// Returns the leading `Trivia` length for a token node.
245-
/// - Returns: .zero if called on a layout node.
256+
/// Returns the leading `Trivia` length, assuming this node is a token.
246257
var tokenLeadingTriviaLength: SourceLength {
247258
return SourceLength(utf8Length: tokenLeadingTriviaByteLength)
248259
}
249260

250-
/// Returns the trailing `Trivia` length for a token node.
251-
/// - Returns: .zero if called on a layout node.
261+
/// Returns the trailing `Trivia` length, assuming this node is a token.
252262
var tokenTrailingTriviaLength: SourceLength {
253263
return SourceLength(utf8Length: tokenTrailingTriviaByteLength)
254264
}
255265

256-
/// Returns the leading `Trivia` for a token node.
257-
/// - Returns: nil if called on a layout node.
266+
/// Returns the leading `Trivia`, assuming this node is a token.
258267
func formTokenLeadingTrivia() -> Trivia? {
259-
guard isToken else { return nil }
260268
return Trivia(pieces: tokenLeadingRawTriviaPieces.map({ TriviaPiece(raw: $0) }))
261269
}
262270

263-
/// Returns the trailing `Trivia` for a token node.
271+
/// Returns the trailing `Trivia`, assuming this node is a token.
264272
/// - Returns: nil if called on a layout node.
265273
func formTokenTrailingTrivia() -> Trivia? {
266-
guard isToken else { return nil }
267274
return Trivia(pieces: tokenTrailingRawTriviaPieces.map({ TriviaPiece(raw: $0) }))
268275
}
269276

270-
/// Passes token info to the provided closure as `UnsafeTokenText`.
271-
/// - Parameters:
272-
/// - body: The closure that accepts the `UnsafeTokenText` value. This value
273-
/// must not escape the closure.
274-
/// - Returns: Return value of `body`.
277+
/// Calls `body` with the token text, assuming this node is a token. The token
278+
/// text value must not escape the closure.
275279
func withUnsafeTokenText<Result>(
276280
_ body: (SyntaxText?) -> Result
277281
) -> Result {
@@ -282,6 +286,8 @@ extension RawSyntax {
282286
Array(children)
283287
}
284288

289+
/// Assuming this node is a token, returns a `RawSyntax` node with the same
290+
/// source text but with the token kind changed to `newValue`.
285291
func withTokenKind(_ newValue: TokenKind) -> RawSyntax {
286292
switch payload {
287293
case .materializedToken(var payload):
@@ -294,7 +300,7 @@ extension RawSyntax {
294300
payload.tokenText = text
295301
return RawSyntax(arena: arena, payload: .materializedToken(payload))
296302
default:
297-
preconditionFailure("withTokenKind() is called on non-token raw syntax")
303+
preconditionFailure("'withTokenKind()' is called on non-token raw syntax")
298304
}
299305
}
300306

@@ -318,8 +324,8 @@ extension RawSyntax {
318324
return nil
319325
}
320326

321-
/// Replaces the trailing trivia of the first token in this syntax tree by `trailingTrivia`.
322-
/// If the syntax tree did not contain a token and thus no trivia could be attached to it, `nil` is returned.
327+
/// Replaces the trailing trivia of the last token in this syntax tree by `trailingTrivia`.
328+
/// If the syntax tree did not contain a token and thus no trivia could be attached to it, `nil` is returned.
323329
/// - Parameters:
324330
/// - trailingTrivia: The trivia to attach.
325331
func withTrailingTrivia(_ trailingTrivia: Trivia) -> RawSyntax? {
@@ -355,11 +361,13 @@ extension RawSyntax {
355361
/// - Parameter kind: The token kind.
356362
/// - Returns: A new RawSyntax `.token` with the provided kind, no
357363
/// leading/trailing trivia, and `.missing` source presence.
358-
// @available(*, deprecated, message: "use 'makeEmptyToken()' with SyntaxArena")
364+
// @available(*, deprecated, message: "use 'makeMissingToken()' with SyntaxArena")
359365
static func missingToken(_ kind: TokenKind) -> RawSyntax {
360-
.makeEmptyToken(arena: .default, kind: kind)
366+
.makeMissingToken(arena: .default, kind: kind)
361367
}
362368

369+
/// Assuming this node is a layout node, creates a new node of the same kind
370+
/// but with children replaced by `elements`.
363371
func replacingLayout<C: Collection>(
364372
with elements: C,
365373
arena: SyntaxArena
@@ -453,6 +461,7 @@ extension RawSyntax {
453461
with elements: C,
454462
arena: SyntaxArena
455463
) -> RawSyntax where C.Element == RawSyntax? {
464+
precondition(!self.isToken)
456465
let newCount = children.count - range.count + elements.count
457466
return .makeLayout(arena: arena,
458467
kind: kind,
@@ -537,7 +546,7 @@ extension RawSyntax: TextOutputStreamable, CustomStringConvertible {
537546
}
538547

539548
extension RawSyntax {
540-
/// Return the first `present` token of a layout node or self if it is a token.
549+
/// Return the first token of a layout node that should be traversed by `viewMode`.
541550
func firstToken(viewMode: SyntaxTreeViewMode) -> RawSyntax? {
542551
guard viewMode.shouldTraverse(node: self) else { return nil }
543552
if isToken { return self }
@@ -549,7 +558,7 @@ extension RawSyntax {
549558
return nil
550559
}
551560

552-
/// Return the last `present` token of a layout node or self if it is a token.
561+
/// Return the last token of a layout node that should be traversed by `viewMode`.
553562
func lastToken(viewMode: SyntaxTreeViewMode) -> RawSyntax? {
554563
guard viewMode.shouldTraverse(node: self) else { return nil }
555564
if isToken { return self }
@@ -579,12 +588,17 @@ extension RawSyntax {
579588
lastToken(viewMode: .sourceAccurate)?.tokenTrailingTriviaByteLength ?? 0
580589
}
581590

591+
/// The length of this node’s content, without the first leading and the last
592+
/// trailing trivia. Intermediate trivia inside a layout node is included in
593+
/// this.
582594
var contentByteLength: Int {
583595
let result = byteLength - leadingTriviaByteLength - trailingTriviaByteLength
584596
assert(result >= 0)
585597
return result
586598
}
587599

600+
/// The length of the token without leading or trailing trivia, assuming this
601+
/// is a token node.
588602
var tokenTextByteLength: Int {
589603
switch rawData.payload {
590604
case .materializedToken(let dat):
@@ -612,6 +626,8 @@ extension RawSyntax {
612626
}
613627
}
614628

629+
// MARK: - Factories.
630+
615631
private func makeRawTriviaPieces(arena: SyntaxArena, leadingTrivia: Trivia, trailingTrivia: Trivia) -> (pieces: RawTriviaPieceBuffer, byteLength: Int) {
616632
let totalTriviaCount = leadingTrivia.count + trailingTrivia.count
617633

@@ -626,19 +642,16 @@ private func makeRawTriviaPieces(arena: SyntaxArena, leadingTrivia: Trivia, trai
626642
}
627643
return (pieces: .init(buffer), byteLength: byteLength)
628644
} else {
629-
630645
return (pieces: .init(start: nil, count: 0), byteLength: 0)
631646
}
632647
}
633648

634-
// MARK: - Factories.
635-
636649
extension RawSyntax {
637650
/// "Designated" factory method to create a materialized token node.
638651
///
639652
/// This should not be called directly.
640653
/// Use `makeMaterializedToken(arena:kind:leadingTrivia:trailingTrivia:)` or
641-
/// `makeEmptyToken(arena:kind:)` instead.
654+
/// `makeMissingToken(arena:kind:)` instead.
642655
///
643656
/// - Parameters:
644657
/// - arena: SyntaxArea to the result node data resides.
@@ -697,7 +710,7 @@ extension RawSyntax {
697710
byteLength: numericCast(byteLength))
698711
}
699712

700-
static func makeEmptyToken(
713+
static func makeMissingToken(
701714
arena: SyntaxArena,
702715
kind: TokenKind
703716
) -> RawSyntax {

Sources/SwiftSyntax/SyntaxArena.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ public class SyntaxArena {
1616
/// Source file buffer the Syntax tree represents.
1717
private var sourceBuffer: UnsafeBufferPointer<UInt8>
1818

19-
/// "children" arena.
19+
/// If the syntax tree that’s allocated in this arena references nodes from
20+
/// other arenas, `children` contains those arenas to keep them alive.
2021
private var children: Set<SyntaxArena>
2122
/// Whether or not this arena has been added to other arenas as a child.
23+
/// Used to make sure we don’t introduce retain cycles between arenas.
2224
private var hasParent: Bool
2325

2426
public init() {
@@ -84,7 +86,7 @@ public class SyntaxArena {
8486
return value
8587
}
8688

87-
let allocated = allocator.allocate(UInt8.self, count: value.count)
89+
let allocated = allocateTextBuffer(count: value.count)
8890
_ = allocated.initialize(from: value)
8991
return SyntaxText(baseAddress: allocated.baseAddress, count: allocated.count)
9092
}
@@ -95,7 +97,7 @@ public class SyntaxArena {
9597
if value.isEmpty { return SyntaxText() }
9698
var value = value
9799
return value.withUTF8 { utf8 in
98-
let allocated = allocator.allocate(UInt8.self, count: utf8.count)
100+
let allocated = allocateTextBuffer(count: utf8.count)
99101
_ = allocated.initialize(from: utf8)
100102
return SyntaxText(baseAddress: allocated.baseAddress, count: utf8.count)
101103
}

Sources/SwiftSyntax/SyntaxClassifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extension RawTriviaPiece {
4848
}
4949
}
5050

51-
struct TokenKindAndText {
51+
fileprivate struct TokenKindAndText {
5252
let kind: RawTokenKind
5353
let text: SyntaxText
5454

Sources/SwiftSyntax/TokenKind.swift.gyb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ public enum RawTokenKind {
173173
}
174174

175175
extension TokenKind {
176+
/// If the `rawKind` has a `defaultText`, `text` can be empty.
176177
static func fromRaw(kind rawKind: RawTokenKind, text: SyntaxText) -> TokenKind {
177178
switch rawKind {
178179
case .eof: return .eof
@@ -188,6 +189,8 @@ extension TokenKind {
188189
}
189190
}
190191

192+
/// Returns the `RawTokenKind` of this `TokenKind` and, if this `TokenKind`
193+
/// has associated text, the associated text, otherwise `nil`.
191194
func decomposeToRaw() -> (rawKind: RawTokenKind, string: String?) {
192195
switch self {
193196
case .eof: return (.eof, nil)

Sources/SwiftSyntax/Trivia.swift.gyb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,15 @@ extension TriviaPiece {
232232
}
233233

234234
/// Trivia piece for token RawSyntax.
235+
///
236+
/// In contrast to `TriviaPiece`, a `RawTriviaPiece` does not own the source
237+
/// text of a the trivia.
235238
enum RawTriviaPiece {
236239
% for trivia in TRIVIAS:
237240
% if trivia.is_collection():
238-
case ${trivia.lower_name}s(Int)
241+
case ${trivia.lower_name}s(Int)
239242
% else:
240-
case ${trivia.lower_name}(SyntaxText)
243+
case ${trivia.lower_name}(SyntaxText)
241244
% end
242245
% end
243246

@@ -293,7 +296,6 @@ extension RawTriviaPiece {
293296
}
294297
}
295298

296-
297299
extension RawTriviaPiece {
298300
static func fromRawValue(kind: UInt8, text: SyntaxText) -> RawTriviaPiece {
299301
switch kind {

Tests/PerformanceTest/ParsingPerformanceTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ public class ParsingPerformanceTests: XCTestCase {
1414
func testParsingPerformance() {
1515
measure {
1616
do {
17+
for _ in 0 ..< 500 {
1718
_ = try SyntaxParser.parse(inputFile)
19+
}
1820
} catch {
1921
XCTFail(error.localizedDescription)
2022
}

0 commit comments

Comments
 (0)