@@ -3616,6 +3616,30 @@ static bool isParenthesizedUnowned(Parser &P) {
3616
3616
(P.Tok .getText () == " safe" || P.Tok .getText () == " unsafe" );
3617
3617
}
3618
3618
3619
+ static void skipAttribute (Parser &P) {
3620
+ // Consider unexpected tokens to be incomplete attributes.
3621
+
3622
+ // Parse the attribute name, which can be qualified, have
3623
+ // generic arguments, and so on.
3624
+ do {
3625
+ if (!P.consumeIf (tok::identifier) && !P.consumeIf (tok::code_complete))
3626
+ return ;
3627
+
3628
+ if (P.startsWithLess (P.Tok )) {
3629
+ P.consumeStartingLess ();
3630
+ P.skipUntilGreaterInTypeList ();
3631
+ }
3632
+ } while (P.consumeIf (tok::period));
3633
+
3634
+ // Skip an argument clause after the attribute name.
3635
+ if (P.consumeIf (tok::l_paren)) {
3636
+ while (P.Tok .isNot (tok::r_brace, tok::eof, tok::pound_endif)) {
3637
+ if (P.consumeIf (tok::r_paren)) break ;
3638
+ P.skipSingle ();
3639
+ }
3640
+ }
3641
+ }
3642
+
3619
3643
bool Parser::isStartOfSwiftDecl () {
3620
3644
// If this is obviously not the start of a decl, then we're done.
3621
3645
if (!isKeywordPossibleDeclStart (Tok)) return false ;
@@ -3645,23 +3669,14 @@ bool Parser::isStartOfSwiftDecl() {
3645
3669
if (Tok.is (tok::kw_try))
3646
3670
return peekToken ().isAny (tok::kw_let, tok::kw_var);
3647
3671
3648
- // Look through attribute list, because it may be an *type* attribute list.
3672
+ // Skip an attribute, since it might be a type attribute. This can't
3673
+ // happen at the top level of a scope, but we do use isStartOfSwiftDecl()
3674
+ // in positions like generic argument lists.
3649
3675
if (Tok.is (tok::at_sign)) {
3650
3676
BacktrackingScope backtrack (*this );
3651
- while (consumeIf (tok::at_sign)) {
3652
- // If not identifier or code complete token, consider '@' as an incomplete
3653
- // attribute.
3654
- if (Tok.isNot (tok::identifier, tok::code_complete))
3655
- continue ;
3656
- consumeToken ();
3657
- // Eat paren after attribute name; e.g. @foo(x)
3658
- if (consumeIf (tok::l_paren)) {
3659
- while (Tok.isNot (tok::r_brace, tok::eof, tok::pound_endif)) {
3660
- if (consumeIf (tok::r_paren)) break ;
3661
- skipSingle ();
3662
- }
3663
- }
3664
- }
3677
+ while (consumeIf (tok::at_sign))
3678
+ skipAttribute (*this );
3679
+
3665
3680
// If this attribute is the last element in the block,
3666
3681
// consider it is a start of incomplete decl.
3667
3682
if (Tok.isAny (tok::r_brace, tok::eof, tok::pound_endif))
0 commit comments