@@ -134,7 +134,7 @@ public enum EffectSpecifier: TokenSpecSet {
134
134
135
135
/// Raw syntax nodes don't have traits (because usually we don't need them).
136
136
/// Specify the effect specifiers trait manually as a one off.
137
- protocol RawEffectSpecifiersTrait {
137
+ protocol RawMisplacedEffectSpecifiersTrait {
138
138
/// The token kinds that should be consumed as misspelled `asyncSpecifier`.
139
139
/// Should be a subset of ``AsyncEffectSpecifier``.
140
140
associatedtype MisspelledAsyncTokenKinds : TokenSpecSet
@@ -151,10 +151,21 @@ protocol RawEffectSpecifiersTrait {
151
151
/// Should be a subset of ``ThrowsEffectSpecifier``.
152
152
associatedtype CorrectThrowsTokenKinds : TokenSpecSet
153
153
154
- var unexpectedBeforeAsyncSpecifier : RawUnexpectedNodesSyntax ? { get }
155
154
var asyncSpecifier : RawTokenSyntax ? { get }
156
- var unexpectedBetweenAsyncSpecifierAndThrowsSpecifier : RawUnexpectedNodesSyntax ? { get }
157
155
var throwsSpecifier : RawTokenSyntax ? { get }
156
+
157
+ init (
158
+ asyncSpecifier: RawTokenSyntax ? ,
159
+ throwsSpecifier: RawTokenSyntax ? ,
160
+ arena: __shared SyntaxArena
161
+ )
162
+
163
+ func withMisplaced( async misplacedAsyncKeyword: RawTokenSyntax ? , throws misplacedThrowsKeyword: RawTokenSyntax ? , arena: __shared SyntaxArena) -> Self
164
+ }
165
+
166
+ protocol RawEffectSpecifiersTrait : RawMisplacedEffectSpecifiersTrait {
167
+ var unexpectedBeforeAsyncSpecifier : RawUnexpectedNodesSyntax ? { get }
168
+ var unexpectedBetweenAsyncSpecifierAndThrowsSpecifier : RawUnexpectedNodesSyntax ? { get }
158
169
var unexpectedAfterThrowsSpecifier : RawUnexpectedNodesSyntax ? { get }
159
170
160
171
init (
@@ -168,6 +179,21 @@ protocol RawEffectSpecifiersTrait {
168
179
}
169
180
170
181
extension RawEffectSpecifiersTrait {
182
+ init (
183
+ asyncSpecifier: RawTokenSyntax ? ,
184
+ throwsSpecifier: RawTokenSyntax ? ,
185
+ arena: __shared SyntaxArena
186
+ ) {
187
+ self . init (
188
+ nil ,
189
+ asyncSpecifier: asyncSpecifier,
190
+ nil ,
191
+ throwsSpecifier: throwsSpecifier,
192
+ nil ,
193
+ arena: arena
194
+ )
195
+ }
196
+
171
197
func withMisplaced( async misplacedAsyncKeyword: RawTokenSyntax ? , throws misplacedThrowsKeyword: RawTokenSyntax ? , arena: __shared SyntaxArena) -> Self {
172
198
return Self . init (
173
199
self . unexpectedBeforeAsyncSpecifier,
@@ -415,7 +441,122 @@ extension RawAccessorEffectSpecifiersSyntax: RawEffectSpecifiersTrait {
415
441
}
416
442
}
417
443
}
444
+ }
445
+
446
+ extension RawDeinitEffectSpecifiersSyntax : RawMisplacedEffectSpecifiersTrait {
447
+ enum MisspelledAsyncTokenKinds : TokenSpecSet {
448
+ case await
449
+ case reasync
450
+
451
+ init ? ( lexeme: Lexer . Lexeme ) {
452
+ switch PrepareForKeywordMatch ( lexeme) {
453
+ case TokenSpec ( . await , allowAtStartOfLine: false ) : self = . await
454
+ case TokenSpec( . reasync) : self = . reasync
455
+ default : return nil
456
+ }
457
+ }
458
+
459
+ var spec : TokenSpec {
460
+ switch self {
461
+ case . await : return TokenSpec ( . await , allowAtStartOfLine: false )
462
+ case . reasync: return . keyword( . reasync)
463
+ }
464
+ }
465
+ }
466
+
467
+ enum CorrectAsyncTokenKinds : TokenSpecSet {
468
+ case async
469
+
470
+ init ? ( lexeme: Lexer . Lexeme ) {
471
+ switch PrepareForKeywordMatch ( lexeme) {
472
+ case TokenSpec ( . async) : self = . async
473
+ default : return nil
474
+ }
475
+ }
476
+
477
+ var spec : TokenSpec {
478
+ switch self {
479
+ case . async : return . keyword( . async)
480
+ }
481
+ }
482
+ }
483
+
484
+ enum MisspelledThrowsTokenKinds : TokenSpecSet {
485
+ case `rethrows`
486
+ case `try`
487
+ case `throw`
488
+ case `throws`
418
489
490
+ init ? ( lexeme: Lexer . Lexeme ) {
491
+ switch PrepareForKeywordMatch ( lexeme) {
492
+ case TokenSpec ( . rethrows) : self = . rethrows
493
+ case TokenSpec ( . try , allowAtStartOfLine: false ) : self = . try
494
+ case TokenSpec( . throw, allowAtStartOfLine: false ) : self = . throw
495
+ case TokenSpec ( . throws) : self = . throws
496
+ default : return nil
497
+ }
498
+ }
499
+
500
+ var spec : TokenSpec {
501
+ switch self {
502
+ case . rethrows: return . keyword( . rethrows)
503
+ case . try : return TokenSpec ( . try , allowAtStartOfLine: false )
504
+ case . throw: return TokenSpec ( . throw, allowAtStartOfLine: false )
505
+ case . throws: return . keyword( . throws)
506
+ }
507
+ }
508
+ }
509
+
510
+ enum CorrectThrowsTokenKinds : TokenSpecSet {
511
+ // Uninhabited
512
+
513
+ init ? ( lexeme: Lexer . Lexeme ) {
514
+ return nil
515
+ }
516
+
517
+ var spec : TokenSpec {
518
+ switch self {
519
+ }
520
+ }
521
+ }
522
+
523
+ var throwsSpecifier : RawTokenSyntax ? { nil }
524
+
525
+ init (
526
+ asyncSpecifier: RawTokenSyntax ? ,
527
+ throwsSpecifier: RawTokenSyntax ? ,
528
+ arena: __shared SwiftSyntax. SyntaxArena
529
+ ) {
530
+ // `throwsSpecifier` should never be present because `parseMisplacedEffectSpecifiers()` only creates missing tokens
531
+ // and `CorrectThrowsTokenKinds` is an empty `TokenSpecSet`.
532
+ //
533
+ // We don't want to insert missing `throws` for deinit case,
534
+ // so if `parseMisplacedEffectSpecifiers()` creates one it will be discarded here.
535
+ precondition ( throwsSpecifier? . isMissing ?? true )
536
+ self . init (
537
+ nil ,
538
+ asyncSpecifier: asyncSpecifier,
539
+ nil ,
540
+ arena: arena
541
+ )
542
+ }
543
+
544
+ func withMisplaced( async misplacedAsyncKeyword: RawTokenSyntax ? , throws misplacedThrowsKeyword: RawTokenSyntax ? , arena: SyntaxArena )
545
+ -> RawDeinitEffectSpecifiersSyntax
546
+ {
547
+ // `throwsSpecifier` should never be present because `parseMisplacedEffectSpecifiers()` only creates missing tokens
548
+ // and `CorrectThrowsTokenKinds` is an empty `TokenSpecSet`.
549
+ //
550
+ // We don't want to insert missing `throws` for deinit case,
551
+ // so if `parseMisplacedEffectSpecifiers()` creates one it will be discarded here.
552
+ precondition ( throwsSpecifier? . isMissing ?? true )
553
+ return Self . init (
554
+ self . unexpectedBeforeAsyncSpecifier,
555
+ asyncSpecifier: self . asyncSpecifier ?? misplacedAsyncKeyword,
556
+ self . unexpectedAfterAsyncSpecifier,
557
+ arena: arena
558
+ )
559
+ }
419
560
}
420
561
421
562
extension TokenConsumer {
@@ -521,11 +662,57 @@ extension Parser {
521
662
return parseEffectSpecifiers ( RawAccessorEffectSpecifiersSyntax . self)
522
663
}
523
664
665
+ mutating func parseDeinitEffectSpecifiers( ) -> RawDeinitEffectSpecifiersSyntax ? {
666
+ // Note that parseEffectSpecifiers() consumes deinit name as unexpected token
667
+ // But we want it to be handled on the higher level.
668
+ // So we parseEffectSpecifiers() is not reused here.
669
+
670
+ var unexpectedBeforeAsync : [ RawSyntax ? ] = [ ]
671
+ var asyncKeyword : RawTokenSyntax ?
672
+ var unexpectedAfterAsync : [ RawSyntax ? ] = [ ]
673
+
674
+ while let ( specifier, handle) = self . at ( anyIn: EffectSpecifiers . self) {
675
+ let beforeAsync = asyncKeyword? . isMissing ?? true
676
+ switch specifier {
677
+ case . async :
678
+ if beforeAsync {
679
+ asyncKeyword = self . eat ( handle)
680
+ } else {
681
+ unexpectedAfterAsync. append ( RawSyntax ( self . eat ( handle) ) )
682
+ }
683
+ case . await , . reasync:
684
+ if beforeAsync {
685
+ // Let's synthesize a missing 'async'. If we find a real async specifier
686
+ // later, we will replace the missing token by the present token.
687
+ asyncKeyword = missingToken ( . async)
688
+ }
689
+ fallthrough
690
+ default :
691
+ if beforeAsync {
692
+ unexpectedBeforeAsync. append ( RawSyntax ( self . eat ( handle) ) )
693
+ } else {
694
+ unexpectedAfterAsync. append ( RawSyntax ( self . eat ( handle) ) )
695
+ }
696
+ }
697
+ }
698
+
699
+ if unexpectedBeforeAsync. isEmpty && asyncKeyword == nil && unexpectedAfterAsync. isEmpty {
700
+ return nil
701
+ }
702
+
703
+ return RawDeinitEffectSpecifiersSyntax (
704
+ RawUnexpectedNodesSyntax ( unexpectedBeforeAsync, arena: self . arena) ,
705
+ asyncSpecifier: asyncKeyword,
706
+ RawUnexpectedNodesSyntax ( unexpectedAfterAsync, arena: self . arena) ,
707
+ arena: self . arena
708
+ )
709
+ }
710
+
524
711
/// Consume any misplaced effect specifiers and return them in as unexpected tokens.
525
712
/// When a misplaced effect specifier is consumed and `effectSpecifiers`
526
713
/// doesn't have an effect specifier of that kind, modify `effectSpecifiers`
527
714
/// to have a missing specifier of that kind.
528
- mutating func parseMisplacedEffectSpecifiers< S: RawEffectSpecifiersTrait > ( _ effectSpecifiers: inout S ? ) -> RawUnexpectedNodesSyntax ? {
715
+ mutating func parseMisplacedEffectSpecifiers< S: RawMisplacedEffectSpecifiersTrait > ( _ effectSpecifiers: inout S ? ) -> RawUnexpectedNodesSyntax ? {
529
716
var synthesizedAsync : RawTokenSyntax ? = nil
530
717
var synthesizedThrows : RawTokenSyntax ? = nil
531
718
var unexpected : [ RawTokenSyntax ] = [ ]
@@ -560,11 +747,8 @@ extension Parser {
560
747
effectSpecifiers = specifiers. withMisplaced ( async : synthesizedAsync, throws: synthesizedThrows, arena: self . arena)
561
748
} else {
562
749
effectSpecifiers = S (
563
- nil ,
564
750
asyncSpecifier: synthesizedAsync,
565
- nil ,
566
751
throwsSpecifier: synthesizedThrows,
567
- nil ,
568
752
arena: self . arena
569
753
)
570
754
}
0 commit comments