@@ -787,7 +787,7 @@ Parser::parseFunctionSignature(Identifier SimpleName,
787
787
788
788
// Check for the 'async' and 'throws' keywords.
789
789
rethrows = false ;
790
- parseAsyncThrows (SourceLoc (), asyncLoc, throwsLoc, &rethrows);
790
+ Status |= parseEffectsSpecifiers (SourceLoc (), asyncLoc, throwsLoc, &rethrows);
791
791
792
792
// If there's a trailing arrow, parse the rest as the result type.
793
793
SourceLoc arrowLoc;
@@ -802,7 +802,7 @@ Parser::parseFunctionSignature(Identifier SimpleName,
802
802
803
803
// Check for 'throws' and 'rethrows' after the arrow, but
804
804
// before the type, and correct it.
805
- parseAsyncThrows (arrowLoc, asyncLoc, throwsLoc, &rethrows);
805
+ parseEffectsSpecifiers (arrowLoc, asyncLoc, throwsLoc, &rethrows);
806
806
807
807
ParserResult<TypeRepr> ResultType =
808
808
parseDeclResultType (diag::expected_type_function_result);
@@ -812,7 +812,7 @@ Parser::parseFunctionSignature(Identifier SimpleName,
812
812
return Status;
813
813
814
814
// Check for 'throws' and 'rethrows' after the type and correct it.
815
- parseAsyncThrows (arrowLoc, asyncLoc, throwsLoc, &rethrows);
815
+ parseEffectsSpecifiers (arrowLoc, asyncLoc, throwsLoc, &rethrows);
816
816
} else {
817
817
// Otherwise, we leave retType null.
818
818
retType = nullptr ;
@@ -821,52 +821,88 @@ Parser::parseFunctionSignature(Identifier SimpleName,
821
821
return Status;
822
822
}
823
823
824
- void Parser::parseAsyncThrows (
825
- SourceLoc existingArrowLoc, SourceLoc &asyncLoc, SourceLoc &throwsLoc,
826
- bool *rethrows) {
827
- if (shouldParseExperimentalConcurrency () &&
828
- Tok.isContextualKeyword (" async" )) {
829
- asyncLoc = consumeToken ();
830
-
831
- if (existingArrowLoc.isValid ()) {
832
- diagnose (asyncLoc, diag::async_or_throws_in_wrong_position, 2 )
833
- .fixItRemove (asyncLoc)
834
- .fixItInsert (existingArrowLoc, " async " );
835
- }
836
- }
824
+ ParserStatus Parser::parseEffectsSpecifiers (SourceLoc existingArrowLoc,
825
+ SourceLoc &asyncLoc,
826
+ SourceLoc &throwsLoc,
827
+ bool *rethrows) {
828
+ ParserStatus status;
837
829
838
- if (Tok.isAny (tok::kw_throws, tok::kw_throw, tok::kw_try) ||
839
- (rethrows && Tok.is (tok::kw_rethrows))) {
840
- // If we allowed parsing rethrows, record whether we did in fact parse it.
841
- if (rethrows)
842
- *rethrows = Tok.is (tok::kw_rethrows);
830
+ while (true ) {
831
+ // 'async'
832
+ if (shouldParseExperimentalConcurrency () &&
833
+ Tok.isContextualKeyword (" async" )) {
843
834
844
- // Replace 'throw' or 'try' with 'throws'.
845
- if (Tok.isAny (tok::kw_throw, tok::kw_try)) {
846
- diagnose (Tok, diag::throw_in_function_type)
847
- .fixItReplace (Tok.getLoc (), " throws" );
835
+ if (asyncLoc.isValid ()) {
836
+ diagnose (Tok, diag::duplicate_effect_specifier, 2 )
837
+ .fixItRemove (Tok.getLoc ());
838
+ } else if (existingArrowLoc.isValid ()) {
839
+ SourceLoc insertLoc = existingArrowLoc;
840
+ if (throwsLoc.isValid () &&
841
+ SourceMgr.isBeforeInBuffer (throwsLoc, insertLoc))
842
+ insertLoc = throwsLoc;
843
+ diagnose (Tok, diag::async_or_throws_in_wrong_position, 2 )
844
+ .fixItRemove (Tok.getLoc ())
845
+ .fixItInsert (insertLoc, " async " );
846
+ } else if (throwsLoc.isValid ()) {
847
+ // 'async' cannot be after 'throws'.
848
+ assert (existingArrowLoc.isInvalid ());
849
+ diagnose (Tok, diag::async_after_throws, rethrows && *rethrows)
850
+ .fixItRemove (Tok.getLoc ())
851
+ .fixItInsert (throwsLoc, " async " );
852
+ }
853
+ if (asyncLoc.isInvalid ())
854
+ asyncLoc = Tok.getLoc ();
855
+ consumeToken ();
856
+ continue ;
848
857
}
849
858
850
- StringRef keyword = Tok.getText ();
851
- throwsLoc = consumeToken ();
859
+ // 'throws'/'rethrows', or diagnose 'throw'/'try'.
860
+ if (Tok.isAny (tok::kw_throws, tok::kw_rethrows) ||
861
+ (Tok.isAny (tok::kw_throw, tok::kw_try) && !Tok.isAtStartOfLine ())) {
862
+ bool isRethrows = Tok.is (tok::kw_rethrows);
863
+
864
+ if (Tok.isAny (tok::kw_throw, tok::kw_try)) {
865
+ // Replace 'throw' or 'try' with 'throws'.
866
+ diagnose (Tok, diag::throw_in_function_type)
867
+ .fixItReplace (Tok.getLoc (), " throws" );
868
+ } else if (!rethrows && isRethrows) {
869
+ // Replace 'rethrows' with 'throws' unless it's allowed.
870
+ diagnose (Tok, diag::rethrowing_function_type)
871
+ .fixItReplace (Tok.getLoc (), " throws" );
872
+ } else if (throwsLoc.isValid ()) {
873
+ diagnose (Tok, diag::duplicate_effect_specifier,
874
+ rethrows ? (isRethrows ? 1 : 0 ) : 0 )
875
+ .fixItRemove (Tok.getLoc ());
876
+ } else if (existingArrowLoc.isValid ()) {
877
+ diagnose (Tok, diag::async_or_throws_in_wrong_position,
878
+ rethrows ? (isRethrows ? 1 : 0 ) : 0 )
879
+ .fixItRemove (Tok.getLoc ())
880
+ .fixItInsert (existingArrowLoc, (Tok.getText () + " " ).str ());
881
+ }
852
882
853
- if (existingArrowLoc.isValid ()) {
854
- diagnose (throwsLoc, diag::async_or_throws_in_wrong_position,
855
- rethrows ? (*rethrows ? 1 : 0 ) : 0 )
856
- .fixItRemove (throwsLoc)
857
- .fixItInsert (existingArrowLoc, (keyword + " " ).str ());
883
+ if (throwsLoc.isInvalid ()) {
884
+ if (rethrows)
885
+ *rethrows = isRethrows;
886
+ throwsLoc = Tok.getLoc ();
887
+ }
888
+ consumeToken ();
889
+ continue ;
858
890
}
859
891
860
- if (shouldParseExperimentalConcurrency () &&
861
- Tok.isContextualKeyword (" async" )) {
862
- asyncLoc = consumeToken ();
863
-
864
- diagnose (asyncLoc, diag::async_after_throws, rethrows && *rethrows)
865
- .fixItRemove (asyncLoc)
866
- .fixItInsert (
867
- existingArrowLoc.isValid () ? existingArrowLoc : throwsLoc, " async " );
892
+ // Code completion.
893
+ if (Tok.is (tok::code_complete) && !Tok.isAtStartOfLine () &&
894
+ !existingArrowLoc.isValid ()) {
895
+ if (CodeCompletion)
896
+ CodeCompletion->completeEffectsSpecifier (asyncLoc.isValid (),
897
+ throwsLoc.isValid ());
898
+ consumeToken (tok::code_complete);
899
+ status.setHasCodeCompletionAndIsError ();
900
+ continue ;
868
901
}
902
+
903
+ break ;
869
904
}
905
+ return status;
870
906
}
871
907
872
908
// / Parse a pattern with an optional type annotation.
0 commit comments