@@ -772,16 +772,17 @@ extension Parser {
772772 _ effectSpecifiers: inout S ?
773773 ) -> RawUnexpectedNodesSyntax ? {
774774 var synthesizedAsync : RawTokenSyntax ? = nil
775- var synthesizedThrows : RawTokenSyntax ? = nil
776- var unexpected : [ RawTokenSyntax ] = [ ]
775+ var synthesizedThrowsClause : RawThrowsClauseSyntax ? = nil
776+ var unexpected : [ RawSyntax ] = [ ]
777777 var loopProgress = LoopProgressCondition ( )
778+
778779 while self . hasProgressed ( & loopProgress) {
779780 if let ( spec, handle, matchedSubset) = self . at (
780781 anyIn: S . MisspelledAsyncTokenKinds. self,
781782 or: S . CorrectAsyncTokenKinds. self
782783 ) {
783784 let misspelledAsync = self . eat ( handle)
784- unexpected. append ( misspelledAsync)
785+ unexpected. append ( RawSyntax ( misspelledAsync) )
785786 if effectSpecifiers? . asyncSpecifier == nil {
786787 if matchedSubset == S . CorrectAsyncTokenKinds. self {
787788 synthesizedAsync = missingToken ( spec)
@@ -794,23 +795,82 @@ extension Parser {
794795 or: S . CorrectThrowsTokenKinds. self
795796 ) {
796797 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
803836 }
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+ )
804868 }
805869 } else {
806870 break
807871 }
808872 }
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 {
814874 if let specifiers = effectSpecifiers {
815875 effectSpecifiers = specifiers. withMisplaced (
816876 async : synthesizedAsync,
0 commit comments