@@ -772,16 +772,17 @@ extension Parser {
772
772
_ effectSpecifiers: inout S ?
773
773
) -> RawUnexpectedNodesSyntax ? {
774
774
var synthesizedAsync : RawTokenSyntax ? = nil
775
- var synthesizedThrows : RawTokenSyntax ? = nil
776
- var unexpected : [ RawTokenSyntax ] = [ ]
775
+ var synthesizedThrowsClause : RawThrowsClauseSyntax ? = nil
776
+ var unexpected : [ RawSyntax ] = [ ]
777
777
var loopProgress = LoopProgressCondition ( )
778
+
778
779
while self . hasProgressed ( & loopProgress) {
779
780
if let ( spec, handle, matchedSubset) = self . at (
780
781
anyIn: S . MisspelledAsyncTokenKinds. self,
781
782
or: S . CorrectAsyncTokenKinds. self
782
783
) {
783
784
let misspelledAsync = self . eat ( handle)
784
- unexpected. append ( misspelledAsync)
785
+ unexpected. append ( RawSyntax ( misspelledAsync) )
785
786
if effectSpecifiers? . asyncSpecifier == nil {
786
787
if matchedSubset == S . CorrectAsyncTokenKinds. self {
787
788
synthesizedAsync = missingToken ( spec)
@@ -794,23 +795,82 @@ extension Parser {
794
795
or: S . CorrectThrowsTokenKinds. self
795
796
) {
796
797
let misspelledThrows = self . eat ( handle)
797
- unexpected. append ( misspelledThrows)
798
- if effectSpecifiers? . throwsClause == nil {
799
- if matchedSubset == S . CorrectThrowsTokenKinds. self {
800
- synthesizedThrows = missingToken ( spec)
801
- } else {
802
- synthesizedThrows = missingToken ( . throws)
798
+ unexpected. append ( RawSyntax ( misspelledThrows) )
799
+ guard effectSpecifiers? . throwsClause == nil else {
800
+ continue
801
+ }
802
+ if matchedSubset == S . CorrectThrowsTokenKinds. self {
803
+ let synthesizedThrows = missingToken ( spec)
804
+
805
+ // avoid generating diagnotics that suggest moving `throws` and the following type if there is any trivia
806
+ // between `throws` and the following left parenthesis, because the following type is likely to be the
807
+ // return type.
808
+ // e.g. -> throws (Int, Int)
809
+ //
810
+ // prefer pessimistic diagnostics even if they might be suboptimal.
811
+ // e.g. -> throws (any Error) Int
812
+ guard misspelledThrows. trailingTriviaByteLength == 0 && self . currentToken. leadingTriviaByteLength == 0 else {
813
+ synthesizedThrowsClause = RawThrowsClauseSyntax (
814
+ throwsSpecifier: synthesizedThrows,
815
+ leftParen: nil ,
816
+ type: nil ,
817
+ rightParen: nil ,
818
+ arena: self . arena
819
+ )
820
+ continue
821
+ }
822
+
823
+ guard
824
+ withLookahead ( { lookahead in
825
+ lookahead. consume ( if: . leftParen) != nil && lookahead. canParseType ( )
826
+ } )
827
+ else {
828
+ synthesizedThrowsClause = RawThrowsClauseSyntax (
829
+ throwsSpecifier: synthesizedThrows,
830
+ leftParen: nil ,
831
+ type: nil ,
832
+ rightParen: nil ,
833
+ arena: self . arena
834
+ )
835
+ continue
803
836
}
837
+
838
+ let ( unexpectedBeforeLeftParen, leftParen) = self . expect ( . leftParen)
839
+ if let unexpectedBeforeLeftParen {
840
+ unexpected += unexpectedBeforeLeftParen. elements
841
+ }
842
+ unexpected. append ( RawSyntax ( leftParen) )
843
+ let type = self . parseType ( )
844
+ unexpected. append ( RawSyntax ( type) )
845
+ let ( unexpectedBeforeRightParen, rightParen) = self . expect ( . rightParen)
846
+ if let unexpectedBeforeRightParen {
847
+ unexpected += unexpectedBeforeRightParen. elements
848
+ }
849
+ if !rightParen. isMissing {
850
+ unexpected. append ( RawSyntax ( rightParen) )
851
+ }
852
+
853
+ synthesizedThrowsClause = RawThrowsClauseSyntax (
854
+ throwsSpecifier: synthesizedThrows,
855
+ leftParen: missingToken ( . leftParen) ,
856
+ type: self . withAllTokensMarkedMissing ( syntax: type) ,
857
+ rightParen: rightParen. isMissing ? nil : missingToken ( . rightParen) ,
858
+ arena: self . arena
859
+ )
860
+ } else {
861
+ synthesizedThrowsClause = RawThrowsClauseSyntax (
862
+ throwsSpecifier: missingToken ( . throws) ,
863
+ leftParen: nil ,
864
+ type: nil ,
865
+ rightParen: nil ,
866
+ arena: self . arena
867
+ )
804
868
}
805
869
} else {
806
870
break
807
871
}
808
872
}
809
- if synthesizedAsync != nil || synthesizedThrows != nil {
810
- let synthesizedThrowsClause = synthesizedThrows. map {
811
- RawThrowsClauseSyntax ( throwsSpecifier: $0, leftParen: nil , type: nil , rightParen: nil , arena: self . arena)
812
- }
813
-
873
+ if synthesizedAsync != nil || synthesizedThrowsClause != nil {
814
874
if let specifiers = effectSpecifiers {
815
875
effectSpecifiers = specifiers. withMisplaced (
816
876
async : synthesizedAsync,
0 commit comments