@@ -65,7 +65,11 @@ private enum StructuralTokens: TokenSpecSet {
6565 case rightAngle
6666
6767 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 {
6973 case . comma: self = . comma
7074 case . colon: self = . colon
7175 case . leftParen: self = . leftParen
@@ -124,6 +128,10 @@ extension TokenConsumer {
124128 return operation ( & self )
125129 }
126130
131+ typealias ModuleSelectorTokens = (
132+ moduleNameOrUnexpected: Token , colonColonToken: Token , extra: [ Token ]
133+ )
134+
127135 /// If the subsequent tokens have the form of a module selector, valid or otherwise, consume and return them;
128136 /// otherwise consume nothing and return `nil`. Additionally consumes invalid chained module selectors.
129137 ///
@@ -134,9 +142,7 @@ extension TokenConsumer {
134142 /// - `colonColonToken`: The `::` indicating this module selector. Always `.colonColon`, always present.
135143 /// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors
136144 /// can be validly chained.
137- mutating func consumeModuleSelectorTokens( ) -> (
138- moduleNameOrUnexpected: Token , colonColonToken: Token , extra: [ Token ]
139- ) ? {
145+ mutating func consumeModuleSelectorTokens( ) -> ModuleSelectorTokens ? {
140146 guard self . isAtModuleSelector ( ) else {
141147 return nil
142148 }
@@ -166,61 +172,100 @@ extension TokenConsumer {
166172 }
167173}
168174
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
174186 }
175187
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 {
176201 let leadingUnexpected : [ RawSyntax ]
177202 let moduleName : RawTokenSyntax
178203 let trailingUnexpected : [ RawSyntax ]
179204
180- if moduleNameOrUnexpected. tokenKind == . identifier {
205+ if tokens . moduleNameOrUnexpected. tokenKind == . identifier {
181206 leadingUnexpected = [ ]
182- moduleName = moduleNameOrUnexpected
207+ moduleName = tokens . moduleNameOrUnexpected
183208 } else {
184- leadingUnexpected = [ RawSyntax ( moduleNameOrUnexpected) ]
185- moduleName = RawTokenSyntax . init ( missing : . identifier, arena : arena )
209+ leadingUnexpected = [ RawSyntax ( tokens . moduleNameOrUnexpected) ]
210+ moduleName = self . missingToken ( . identifier)
186211 }
187212
188- trailingUnexpected = extra. map { RawSyntax ( $0) }
213+ trailingUnexpected = tokens . extra. map { RawSyntax ( $0) }
189214
190215 return RawModuleSelectorSyntax (
191216 RawUnexpectedNodesSyntax ( leadingUnexpected, arena: arena) ,
192217 moduleName: moduleName,
193- colonColon: colonColon ,
218+ colonColon: tokens . colonColonToken ,
194219 RawUnexpectedNodesSyntax ( trailingUnexpected, arena: arena) ,
195220 arena: arena
196221 )
197222 }
198223
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+ }
202231
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+ }
205240
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
212243
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... )
217249
218- collect ( from : node )
250+ selectorTokens . colonColonToken = remainingTokens . removeLast ( )
219251
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)
222258 }
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)
224269 }
225270
226271 /// Inject `moduleSelector` into `node`, its first child, its first child's first child, etc. If necessary,
0 commit comments