@@ -65,7 +65,11 @@ private enum StructuralTokens: TokenSpecSet {
65
65
case rightAngle
66
66
67
67
init ? ( lexeme: Lexer . Lexeme , experimentalFeatures: Parser . ExperimentalFeatures ) {
68
- switch lexeme. rawTokenKind {
68
+ self . init ( lexeme. rawTokenKind)
69
+ }
70
+
71
+ init ? ( _ rawTokenKind: RawTokenKind ) {
72
+ switch rawTokenKind {
69
73
case . comma: self = . comma
70
74
case . colon: self = . colon
71
75
case . leftParen: self = . leftParen
@@ -124,6 +128,10 @@ extension TokenConsumer {
124
128
return operation ( & self )
125
129
}
126
130
131
+ typealias ModuleSelectorTokens = (
132
+ moduleNameOrUnexpected: Token , colonColonToken: Token , extra: [ Token ]
133
+ )
134
+
127
135
/// If the subsequent tokens have the form of a module selector, valid or otherwise, consume and return them;
128
136
/// otherwise consume nothing and return `nil`. Additionally consumes invalid chained module selectors.
129
137
///
@@ -134,9 +142,7 @@ extension TokenConsumer {
134
142
/// - `colonColonToken`: The `::` indicating this module selector. Always `.colonColon`, always present.
135
143
/// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors
136
144
/// can be validly chained.
137
- mutating func consumeModuleSelectorTokens( ) -> (
138
- moduleNameOrUnexpected: Token , colonColonToken: Token , extra: [ Token ]
139
- ) ? {
145
+ mutating func consumeModuleSelectorTokens( ) -> ModuleSelectorTokens ? {
140
146
guard self . isAtModuleSelector ( ) else {
141
147
return nil
142
148
}
@@ -166,61 +172,100 @@ extension TokenConsumer {
166
172
}
167
173
}
168
174
169
- extension Parser {
170
- /// Parses one or more module selectors, if present.
171
- mutating func parseModuleSelector( ) -> RawModuleSelectorSyntax ? {
172
- guard let ( moduleNameOrUnexpected, colonColon, extra) = consumeModuleSelectorTokens ( ) else {
173
- return nil
175
+ private func tokens( in node: ( some RawSyntaxNodeProtocol ) ? ) -> [ RawTokenSyntax ] {
176
+ var tokens : [ RawTokenSyntax ] = [ ]
177
+
178
+ func collect( from child: ( some RawSyntaxNodeProtocol ) ? ) {
179
+ guard let child else { return }
180
+
181
+ guard let token = child. as ( RawTokenSyntax . self) else {
182
+ for child in child. raw. layoutView!. children {
183
+ collect ( from: child)
184
+ }
185
+ return
174
186
}
175
187
188
+ if !token. isMissing {
189
+ tokens. append ( token)
190
+ }
191
+ }
192
+
193
+ collect ( from: node)
194
+
195
+ return tokens
196
+ }
197
+
198
+ extension Parser {
199
+ /// Helper to form a module selector from a set of tokens, divorced from their source.
200
+ private mutating func makeModuleSelector( from tokens: ModuleSelectorTokens ) -> RawModuleSelectorSyntax {
176
201
let leadingUnexpected : [ RawSyntax ]
177
202
let moduleName : RawTokenSyntax
178
203
let trailingUnexpected : [ RawSyntax ]
179
204
180
- if moduleNameOrUnexpected. tokenKind == . identifier {
205
+ if tokens . moduleNameOrUnexpected. tokenKind == . identifier {
181
206
leadingUnexpected = [ ]
182
- moduleName = moduleNameOrUnexpected
207
+ moduleName = tokens . moduleNameOrUnexpected
183
208
} else {
184
- leadingUnexpected = [ RawSyntax ( moduleNameOrUnexpected) ]
185
- moduleName = RawTokenSyntax . init ( missing : . identifier, arena : arena )
209
+ leadingUnexpected = [ RawSyntax ( tokens . moduleNameOrUnexpected) ]
210
+ moduleName = self . missingToken ( . identifier)
186
211
}
187
212
188
- trailingUnexpected = extra. map { RawSyntax ( $0) }
213
+ trailingUnexpected = tokens . extra. map { RawSyntax ( $0) }
189
214
190
215
return RawModuleSelectorSyntax (
191
216
RawUnexpectedNodesSyntax ( leadingUnexpected, arena: arena) ,
192
217
moduleName: moduleName,
193
- colonColon: colonColon ,
218
+ colonColon: tokens . colonColonToken ,
194
219
RawUnexpectedNodesSyntax ( trailingUnexpected, arena: arena) ,
195
220
arena: arena
196
221
)
197
222
}
198
223
199
- /// Convert a raw syntax node to `RawUnexpectedNodesSyntax` by extracting its tokens.
200
- func unexpected( _ node: ( some RawSyntaxNodeProtocol ) ? ) -> RawUnexpectedNodesSyntax ? {
201
- var tokens : [ RawTokenSyntax ] = [ ]
224
+ /// Parses one or more module selectors, if present.
225
+ mutating func parseModuleSelector( ) -> RawModuleSelectorSyntax ? {
226
+ guard let tokens = consumeModuleSelectorTokens ( ) else {
227
+ return nil
228
+ }
229
+ return makeModuleSelector ( from: tokens)
230
+ }
202
231
203
- func collect( from child: ( some RawSyntaxNodeProtocol ) ? ) {
204
- guard let child else { return }
232
+ /// If possible, convert a ``RawUnexpectedNodesSyntax`` back into a module selector. Used in some specialized
233
+ /// recovery paths.
234
+ mutating func recoverModuleSelector(
235
+ from unexpected: RawUnexpectedNodesSyntax ?
236
+ ) -> ( unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax ? , moduleSelector: RawModuleSelectorSyntax ? ) {
237
+ guard let unexpected, unexpected. containsToken ( where: { $0. tokenKind == . colonColon } ) else {
238
+ return ( unexpected, nil )
239
+ }
205
240
206
- guard let token = child. as ( RawTokenSyntax . self) else {
207
- for child in child. raw. layoutView!. children {
208
- collect ( from: child)
209
- }
210
- return
211
- }
241
+ var remainingTokens = tokens ( in: unexpected)
242
+ let selectorTokens : ModuleSelectorTokens
212
243
213
- if !token. isMissing {
214
- tokens. append ( token)
215
- }
216
- }
244
+ // Everything after the first `::` should be either extra (invalid) module selectors or just random extra garbage
245
+ // we skipped during recovery.
246
+ let afterColonColonIndex = remainingTokens. firstIndex ( where: { $0. tokenKind == . colonColon } ) ! + 1
247
+ selectorTokens. extra = Array ( remainingTokens [ afterColonColonIndex... ] )
248
+ remainingTokens. removeSubrange ( afterColonColonIndex... )
217
249
218
- collect ( from : node )
250
+ selectorTokens . colonColonToken = remainingTokens . removeLast ( )
219
251
220
- guard !tokens. isEmpty else {
221
- return nil
252
+ // This matches logic from `consumeModuleSelectorTokens()` and `isAtModuleSelector()`.
253
+ if let tokenBeforeColonColon = remainingTokens. last, StructuralTokens ( tokenBeforeColonColon. tokenKind) != nil {
254
+ selectorTokens. moduleNameOrUnexpected = tokenBeforeColonColon
255
+ remainingTokens. removeLast ( )
256
+ } else {
257
+ selectorTokens. moduleNameOrUnexpected = self . missingToken ( . identifier)
222
258
}
223
- return RawUnexpectedNodesSyntax ( tokens, arena: self . arena)
259
+
260
+ return (
261
+ RawUnexpectedNodesSyntax ( remainingTokens, arena: self . arena) ,
262
+ self . makeModuleSelector ( from: selectorTokens)
263
+ )
264
+ }
265
+
266
+ /// Convert a raw syntax node to `RawUnexpectedNodesSyntax` by extracting its tokens.
267
+ func unexpected( _ node: ( some RawSyntaxNodeProtocol ) ? ) -> RawUnexpectedNodesSyntax ? {
268
+ return RawUnexpectedNodesSyntax ( tokens ( in: node) , arena: self . arena)
224
269
}
225
270
226
271
/// Inject `moduleSelector` into `node`, its first child, its first child's first child, etc. If necessary,
0 commit comments