@@ -5691,33 +5691,61 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
56915691}
56925692
56935693static bool
5694- isParenthesizedModifier (Parser &P, StringRef name,
5695- std::initializer_list<StringRef> allowedArguments) {
5694+ consumeIfParenthesizedModifier (Parser &P, StringRef name,
5695+ std::initializer_list<StringRef> allowedArguments) {
56965696 assert ((P.Tok .getText () == name) && P.peekToken ().is (tok::l_paren) &&
56975697 " Invariant violated" );
56985698
56995699 // Look ahead to parse the parenthesized expression.
5700- Parser::BacktrackingScope Backtrack (P);
5700+ Parser::CancellableBacktrackingScope backtrack (P);
57015701 P.consumeToken (tok::identifier);
57025702 P.consumeToken (tok::l_paren);
5703+
5704+ const Token &Tok2 = P.peekToken ();
5705+ if (P.consumeIf (tok::code_complete)) {
5706+ // If a code complete token is present, recover from missing/incorrect argument and missing '('
5707+ P.consumeIf (tok::identifier);
5708+ P.consumeIf (tok::r_paren);
5709+ backtrack.cancelBacktrack ();
5710+ return true ;
5711+ }
5712+
5713+ if (P.Tok .is (tok::identifier) && !P.Tok .isContextualDeclKeyword () && Tok2.is (tok::code_complete)) {
5714+ P.consumeToken (tok::identifier);
5715+ P.consumeToken (tok::code_complete);
5716+
5717+ // If a code complete is present with a non-keyword token before it, recover from missing/incorrect argument and missing '('
5718+ if (!P.Tok .isContextualDeclKeyword ()) {
5719+ P.consumeIf (tok::identifier);
5720+ }
5721+ P.consumeIf (tok::r_paren);
5722+ backtrack.cancelBacktrack ();
5723+ return true ;
5724+ }
57035725
57045726 const bool argumentIsAllowed =
57055727 std::find (allowedArguments.begin (), allowedArguments.end (),
57065728 P.Tok .getText ()) != allowedArguments.end ();
5707- return argumentIsAllowed && P.Tok .is (tok::identifier) &&
5708- P.peekToken ().is (tok::r_paren);
5729+
5730+ if (argumentIsAllowed && P.Tok .is (tok::identifier) &&
5731+ P.peekToken ().is (tok::r_paren)) {
5732+ backtrack.cancelBacktrack ();
5733+ return true ;
5734+ }
5735+
5736+ return false ;
57095737}
57105738
57115739// / Given a current token of 'unowned', check to see if it is followed by a
5712- // / "(safe)" or "(unsafe)" specifier.
5713- static bool isParenthesizedUnowned (Parser &P) {
5714- return isParenthesizedModifier (P, " unowned" , {" safe" , " unsafe" });
5740+ // / "(safe)" or "(unsafe)" specifier and consumes if it is .
5741+ static bool consumeIfParenthesizedUnowned (Parser &P) {
5742+ return consumeIfParenthesizedModifier (P, " unowned" , {" safe" , " unsafe" });
57155743}
57165744
57175745// / Given a current token of 'nonisolated', check to see if it is followed by an
5718- // / "(unsafe)" specifier.
5719- static bool isParenthesizedNonisolated (Parser &P) {
5720- return isParenthesizedModifier (P, " nonisolated" , {" unsafe" });
5746+ // / "(unsafe)" specifier and consumes if it is .
5747+ static bool consumeIfParenthesizedNonisolated (Parser &P) {
5748+ return consumeIfParenthesizedModifier (P, " nonisolated" , {" unsafe" });
57215749}
57225750
57235751static void skipAttribute (Parser &P) {
@@ -5878,27 +5906,21 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
58785906 // If it might be, we do some more digging.
58795907
58805908 // If this is 'unowned', check to see if it is valid.
5881- if (Tok.getText () == " unowned" && Tok2.is (tok::l_paren) &&
5882- isParenthesizedUnowned (*this )) {
5909+ if (Tok.getText () == " unowned" && Tok2.is (tok::l_paren)) {
58835910 Parser::BacktrackingScope Backtrack (*this );
5884- consumeToken (tok::identifier);
5885- consumeToken (tok::l_paren);
5886- consumeToken (tok::identifier);
5887- consumeToken (tok::r_paren);
5888- return isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false ,
5889- /* hadAttrsOrModifiers=*/ true );
5911+ if (consumeIfParenthesizedUnowned (*this )) {
5912+ return isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false ,
5913+ /* hadAttrsOrModifiers=*/ true );
5914+ }
58905915 }
58915916
58925917 // If this is 'nonisolated', check to see if it is valid.
5893- if (Tok.isContextualKeyword (" nonisolated" ) && Tok2.is (tok::l_paren) &&
5894- isParenthesizedNonisolated (*this )) {
5918+ if (Tok.isContextualKeyword (" nonisolated" ) && Tok2.is (tok::l_paren)) {
58955919 BacktrackingScope backtrack (*this );
5896- consumeToken (tok::identifier);
5897- consumeToken (tok::l_paren);
5898- consumeToken (tok::identifier);
5899- consumeToken (tok::r_paren);
5900- return isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false ,
5901- /* hadAttrsOrModifiers=*/ true );
5920+ if (consumeIfParenthesizedNonisolated (*this )) {
5921+ return isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false ,
5922+ /* hadAttrsOrModifiers=*/ true );
5923+ }
59025924 }
59035925
59045926 if (Tok.isContextualKeyword (" actor" )) {
0 commit comments