@@ -16,10 +16,21 @@ typealias RawTriviaPieceBuffer = UnsafeBufferPointer<RawTriviaPiece>
16
16
/// Node data for RawSyntax tree. Tagged union plus common data.
17
17
internal struct RawSyntaxData {
18
18
internal enum Payload {
19
+ case parsedToken( ParsedToken )
19
20
case materializedToken( MaterializedToken )
20
21
case layout( Layout )
21
22
}
22
23
24
+ /// Token with lazy trivia parsing.
25
+ ///
26
+ /// The RawSyntax's `arena` must have a valid trivia parsing function to
27
+ /// lazily materialize the leading/trailing trivia.
28
+ struct ParsedToken {
29
+ var tokenKind : RawTokenKind
30
+ var wholeText : SyntaxText
31
+ var textRange : Range < SyntaxText . Index >
32
+ }
33
+
23
34
/// Token typically created with `TokenSyntax.<someToken>`.
24
35
struct MaterializedToken {
25
36
var tokenKind : RawTokenKind
@@ -42,6 +53,18 @@ internal struct RawSyntaxData {
42
53
fileprivate var arenaReference : SyntaxArenaRef
43
54
}
44
55
56
+ extension RawSyntaxData . ParsedToken {
57
+ var tokenText : SyntaxText {
58
+ SyntaxText ( rebasing: wholeText [ textRange] )
59
+ }
60
+ var leadingTriviaText : SyntaxText {
61
+ SyntaxText ( rebasing: wholeText [ ..< textRange. lowerBound] )
62
+ }
63
+ var trailingTriviaText : SyntaxText {
64
+ SyntaxText ( rebasing: wholeText [ textRange. upperBound... ] )
65
+ }
66
+ }
67
+
45
68
extension RawSyntaxData . MaterializedToken {
46
69
var leadingTrivia : RawTriviaPieceBuffer {
47
70
RawTriviaPieceBuffer ( rebasing: triviaPieces [ ..< Int ( numLeadingTrivia) ] )
@@ -94,6 +117,8 @@ extension RawSyntax {
94
117
switch rawData. payload {
95
118
case . materializedToken( let dat) :
96
119
return dat. tokenKind
120
+ case . parsedToken( let dat) :
121
+ return dat. tokenKind
97
122
case . layout( _) :
98
123
preconditionFailure ( " 'tokenKind' is not available for non-token node " )
99
124
}
@@ -102,6 +127,8 @@ extension RawSyntax {
102
127
/// Token text of this node assuming this node is a token.
103
128
var rawTokenText : SyntaxText {
104
129
switch rawData. payload {
130
+ case . parsedToken( let dat) :
131
+ return dat. tokenText
105
132
case . materializedToken( let dat) :
106
133
return dat. tokenText
107
134
case . layout( _) :
@@ -112,6 +139,8 @@ extension RawSyntax {
112
139
/// The UTF-8 byte length of the leading trivia, assuming this node is a token.
113
140
var tokenLeadingTriviaByteLength : Int {
114
141
switch rawData. payload {
142
+ case . parsedToken( let dat) :
143
+ return dat. leadingTriviaText. count
115
144
case . materializedToken( let dat) :
116
145
return dat. leadingTrivia. reduce ( 0 ) { $0 + $1. byteLength }
117
146
case . layout( _) :
@@ -122,26 +151,32 @@ extension RawSyntax {
122
151
/// The UTF-8 byte length of the trailing trivia, assuming this node is a token.
123
152
var tokenTrailingTriviaByteLength : Int {
124
153
switch rawData. payload {
154
+ case . parsedToken( let dat) :
155
+ return dat. trailingTriviaText. count
125
156
case . materializedToken( let dat) :
126
157
return dat. trailingTrivia. reduce ( 0 ) { $0 + $1. byteLength }
127
158
case . layout( _) :
128
159
preconditionFailure ( " 'tokenTrailingTriviaByteLength' is not available for non-token node " )
129
160
}
130
161
}
131
162
132
- var tokenLeadingRawTriviaPieces : RawTriviaPieceBuffer {
163
+ var tokenLeadingRawTriviaPieces : [ RawTriviaPiece ] {
133
164
switch rawData. payload {
165
+ case . parsedToken( let dat) :
166
+ return self . arena. parseTrivia ( source: dat. leadingTriviaText, isTrailing: false )
134
167
case . materializedToken( let dat) :
135
- return dat. leadingTrivia
168
+ return Array ( dat. leadingTrivia)
136
169
case . layout( _) :
137
170
preconditionFailure ( " 'tokenLeadingRawTriviaPieces' is called on non-token raw syntax " )
138
171
}
139
172
}
140
173
141
- var tokenTrailingRawTriviaPieces : RawTriviaPieceBuffer {
174
+ var tokenTrailingRawTriviaPieces : [ RawTriviaPiece ] {
142
175
switch rawData. payload {
176
+ case . parsedToken( let dat) :
177
+ return self . arena. parseTrivia ( source: dat. trailingTriviaText, isTrailing: false )
143
178
case . materializedToken( let dat) :
144
- return dat. trailingTrivia
179
+ return Array ( dat. trailingTrivia)
145
180
case . layout( _) :
146
181
preconditionFailure ( " 'tokenTrailingRawTriviaPieces' is called on non-token raw syntax " )
147
182
}
@@ -152,6 +187,7 @@ extension RawSyntax {
152
187
/// The syntax kind of this raw syntax.
153
188
var kind : SyntaxKind {
154
189
switch rawData. payload {
190
+ case . parsedToken( _) : return . token
155
191
case . materializedToken( _) : return . token
156
192
case . layout( let dat) : return dat. kind
157
193
}
@@ -175,8 +211,11 @@ extension RawSyntax {
175
211
/// Child nodes.
176
212
var children : RawSyntaxBuffer {
177
213
switch rawData. payload {
178
- case . materializedToken( _) : return . init( start: nil , count: 0 )
179
- case . layout( let dat) : return dat. layout
214
+ case . parsedToken( _) ,
215
+ . materializedToken( _) :
216
+ return . init( start: nil , count: 0 )
217
+ case . layout( let dat) :
218
+ return dat. layout
180
219
}
181
220
}
182
221
@@ -197,8 +236,11 @@ extension RawSyntax {
197
236
/// Total number of nodes in this sub-tree, including `self` node.
198
237
var totalNodes : Int {
199
238
switch rawData. payload {
200
- case . materializedToken( _) : return 1
201
- case . layout( let dat) : return dat. descendantCount + 1
239
+ case . parsedToken( _) ,
240
+ . materializedToken( _) :
241
+ return 1
242
+ case . layout( let dat) :
243
+ return dat. descendantCount + 1
202
244
}
203
245
}
204
246
@@ -226,6 +268,7 @@ extension RawSyntax {
226
268
/// Sum of text byte lengths of all descendant token nodes.
227
269
var byteLength : Int {
228
270
switch rawData. payload {
271
+ case . parsedToken( let dat) : return dat. wholeText. count
229
272
case . materializedToken( let dat) : return Int ( dat. byteLength)
230
273
case . layout( let dat) : return dat. byteLength
231
274
}
@@ -237,6 +280,8 @@ extension RawSyntax {
237
280
238
281
func formTokenKind( ) -> TokenKind ? {
239
282
switch rawData. payload {
283
+ case . parsedToken( let dat) :
284
+ return TokenKind . fromRaw ( kind: dat. tokenKind, text: dat. tokenText)
240
285
case . materializedToken( let dat) :
241
286
return TokenKind . fromRaw ( kind: dat. tokenKind, text: dat. tokenText)
242
287
case . layout( _) :
@@ -280,7 +325,13 @@ extension RawSyntax {
280
325
/// Assuming this node is a token, returns a `RawSyntax` node with the same
281
326
/// source text but with the token kind changed to `newValue`.
282
327
func withTokenKind( _ newValue: TokenKind ) -> RawSyntax {
283
- switch payload {
328
+ switch rawData. payload {
329
+ case . parsedToken( _) :
330
+ return . makeMaterializedToken(
331
+ kind: newValue,
332
+ leadingTrivia: formLeadingTrivia ( ) !,
333
+ trailingTrivia: formTokenTrailingTrivia ( ) !,
334
+ arena: arena)
284
335
case . materializedToken( var payload) :
285
336
let decomposed = newValue. decomposeToRaw ( )
286
337
let rawKind = decomposed. rawKind
@@ -517,6 +568,9 @@ extension RawSyntax: TextOutputStreamable, CustomStringConvertible {
517
568
/// - Parameter stream: The stream on which to output this node.
518
569
public func write< Target: TextOutputStream > ( to target: inout Target ) {
519
570
switch rawData. payload {
571
+ case . parsedToken( let dat) :
572
+ String ( syntaxText: dat. wholeText) . write ( to: & target)
573
+ break
520
574
case . materializedToken( let dat) :
521
575
for p in dat. leadingTrivia { p. write ( to: & target) }
522
576
String ( syntaxText: dat. tokenText) . write ( to: & target)
@@ -594,6 +648,8 @@ extension RawSyntax {
594
648
/// is a token node.
595
649
var tokenTextByteLength : Int {
596
650
switch rawData. payload {
651
+ case . parsedToken( let dat) :
652
+ return dat. tokenText. count
597
653
case . materializedToken( let dat) :
598
654
return dat. tokenText. count
599
655
case . layout( _) :
@@ -640,6 +696,24 @@ private func makeRawTriviaPieces(leadingTrivia: Trivia, trailingTrivia: Trivia,
640
696
}
641
697
642
698
extension RawSyntax {
699
+ /// "Designated" factory method to create a parsed token node.
700
+ ///
701
+ /// - Parameters:
702
+ /// - kind: Token kind.
703
+ /// - wholeText: Whole text of this token including trailing/leading trivia.
704
+ /// - textRange: Range of the token text in `wholeText`.
705
+ /// - arena: SyntaxArea to the result node data resides.
706
+ internal static func parsedToken(
707
+ kind: RawTokenKind ,
708
+ wholeText: SyntaxText ,
709
+ textRange: Range < SyntaxText . Index > ,
710
+ arena: SyntaxArena
711
+ ) -> RawSyntax {
712
+ let payload = RawSyntaxData . ParsedToken (
713
+ tokenKind: kind, wholeText: wholeText, textRange: textRange)
714
+ return RawSyntax ( arena: arena, payload: . parsedToken( payload) )
715
+ }
716
+
643
717
/// "Designated" factory method to create a materialized token node.
644
718
///
645
719
/// This should not be called directly.
@@ -864,6 +938,11 @@ extension RawSyntax: CustomDebugStringConvertible {
864
938
private func debugWrite< Target: TextOutputStream > ( to target: inout Target , indent: Int , withChildren: Bool = false ) {
865
939
let childIndent = indent + 2
866
940
switch rawData. payload {
941
+ case . parsedToken( let dat) :
942
+ target. write ( " .parsedToken( " )
943
+ target. write ( String ( describing: dat. tokenKind) )
944
+ target. write ( " wholeText= \( dat. tokenText. debugDescription) " )
945
+ target. write ( " textRange= \( dat. textRange. description) " )
867
946
case . materializedToken( let dat) :
868
947
target. write ( " .materializedToken( " )
869
948
target. write ( String ( describing: dat. tokenKind) )
0 commit comments