Repository: rust-analyzer/rust-analyzer
Pull request #2867 (2020-01-17 10:49:48)

Nest attrs into exprs in function args


Patch:
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index a31a7a08d8..06c92645e0 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -19,6 +19,26 @@ pub(super) fn expr(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
     expr_bp(p, r, 1)
 }
 
+pub(super) fn expr_with_attrs(p: &mut Parser) -> bool {
+    let m = p.start();
+    let has_attrs = p.at(T![#]);
+    attributes::outer_attributes(p);
+
+    let (cm, _block_like) = expr(p);
+    let success = cm.is_some();
+
+    match (has_attrs, cm) {
+        (true, Some(cm)) => {
+            let kind = cm.kind();
+            cm.undo_completion(p).abandon(p);
+            m.complete(p, kind);
+        }
+        _ => m.abandon(p),
+    }
+
+    success
+}
+
 pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
     let r = Restrictions { forbid_structs: false, prefer_stmt: true };
     expr_bp(p, r, 1)
@@ -544,12 +564,9 @@ fn arg_list(p: &mut Parser) {
         // fn main() {
         //     foo(#[attr] 92)
         // }
-        attributes::outer_attributes(p);
-        if !p.at_ts(EXPR_FIRST) {
-            p.error("expected expression");
+        if !expr_with_attrs(p) {
             break;
         }
-        expr(p);
         if !p.at(T![')']) && !p.expect(T![,]) {
             break;
         }
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index a98a2a3ef5..2cc321473a 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -191,19 +191,8 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
 
         // test array_attrs
         // const A: &[i64] = &[1, #[cfg(test)] 2];
-        let m = p.start();
-        let has_attrs = p.at(T![#]);
-        attributes::outer_attributes(p);
-
-        let cm = expr(p).0;
-
-        match (has_attrs, cm) {
-            (true, Some(cm)) => {
-                let kind = cm.kind();
-                cm.undo_completion(p).abandon(p);
-                m.complete(p, kind);
-            }
-            _ => m.abandon(p),
+        if !expr_with_attrs(p) {
+            break;
         }
 
         if n_exprs == 1 && p.eat(T![;]) {


Test patch:
diff --git a/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.txt b/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.txt
index 310a824644..cb45eb2fc2 100644
--- a/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.txt
@@ -12,8 +12,8 @@ SOURCE_FILE@[0; 112)
       BLOCK@[7; 33)
         L_CURLY@[7; 8) "{"
         WHITESPACE@[8; 9) " "
-        EXPR_STMT@[9; 26)
-          ARRAY_EXPR@[9; 26)
+        EXPR_STMT@[9; 17)
+          ARRAY_EXPR@[9; 17)
             L_BRACK@[9; 10) "["
             LITERAL@[10; 11)
               INT_NUMBER@[10; 11) "1"
@@ -25,10 +25,13 @@ SOURCE_FILE@[0; 112)
             WHITESPACE@[15; 16) " "
             ERROR@[16; 17)
               AT@[16; 17) "@"
+        EXPR_STMT@[17; 18)
+          ERROR@[17; 18)
             COMMA@[17; 18) ","
-            WHITESPACE@[18; 19) " "
-            ERROR@[19; 25)
-              STRUCT_KW@[19; 25) "struct"
+        WHITESPACE@[18; 19) " "
+        STRUCT_DEF@[19; 26)
+          STRUCT_KW@[19; 25) "struct"
+          ERROR@[25; 26)
             COMMA@[25; 26) ","
         WHITESPACE@[26; 27) " "
         LET_STMT@[27; 31)
@@ -51,14 +54,14 @@ SOURCE_FILE@[0; 112)
       BLOCK@[41; 68)
         L_CURLY@[41; 42) "{"
         WHITESPACE@[42; 43) " "
-        EXPR_STMT@[43; 52)
-          CALL_EXPR@[43; 52)
+        EXPR_STMT@[43; 54)
+          CALL_EXPR@[43; 54)
             PATH_EXPR@[43; 46)
               PATH@[43; 46)
                 PATH_SEGMENT@[43; 46)
                   NAME_REF@[43; 46)
                     IDENT@[43; 46) "foo"
-            ARG_LIST@[46; 52)
+            ARG_LIST@[46; 54)
               L_PAREN@[46; 47) "("
               LITERAL@[47; 48)
                 INT_NUMBER@[47; 48) "1"
@@ -67,10 +70,9 @@ SOURCE_FILE@[0; 112)
               LITERAL@[50; 51)
                 INT_NUMBER@[50; 51) "2"
               COMMA@[51; 52) ","
-        WHITESPACE@[52; 53) " "
-        EXPR_STMT@[53; 54)
-          ERROR@[53; 54)
-            AT@[53; 54) "@"
+              WHITESPACE@[52; 53) " "
+              ERROR@[53; 54)
+                AT@[53; 54) "@"
         EXPR_STMT@[54; 55)
           ERROR@[54; 55)
             COMMA@[54; 55) ","
@@ -101,8 +103,8 @@ SOURCE_FILE@[0; 112)
       BLOCK@[76; 111)
         L_CURLY@[76; 77) "{"
         WHITESPACE@[77; 78) " "
-        EXPR_STMT@[78; 91)
-          METHOD_CALL_EXPR@[78; 91)
+        EXPR_STMT@[78; 93)
+          METHOD_CALL_EXPR@[78; 93)
             PATH_EXPR@[78; 81)
               PATH@[78; 81)
                 PATH_SEGMENT@[78; 81)
@@ -111,7 +113,7 @@ SOURCE_FILE@[0; 112)
             DOT@[81; 82) "."
             NAME_REF@[82; 85)
               IDENT@[82; 85) "bar"
-            ARG_LIST@[85; 91)
+            ARG_LIST@[85; 93)
               L_PAREN@[85; 86) "("
               LITERAL@[86; 87)
                 INT_NUMBER@[86; 87) "1"
@@ -120,10 +122,9 @@ SOURCE_FILE@[0; 112)
               LITERAL@[89; 90)
                 INT_NUMBER@[89; 90) "2"
               COMMA@[90; 91) ","
-        WHITESPACE@[91; 92) " "
-        EXPR_STMT@[92; 93)
-          ERROR@[92; 93)
-            AT@[92; 93) "@"
+              WHITESPACE@[91; 92) " "
+              ERROR@[92; 93)
+                AT@[92; 93) "@"
         EXPR_STMT@[93; 94)
           ERROR@[93; 94)
             COMMA@[93; 94) ","
@@ -148,15 +149,14 @@ SOURCE_FILE@[0; 112)
         R_CURLY@[110; 111) "}"
   WHITESPACE@[111; 112) "\n"
 error 16: expected expression
-error 19: expected expression
-error 26: expected expression
-error 26: expected COMMA
-error 26: expected R_BRACK
-error 26: expected SEMI
+error 17: expected R_BRACK
+error 17: expected SEMI
+error 17: expected expression
+error 18: expected SEMI
+error 25: expected a name
+error 26: expected `;`, `{`, or `(`
 error 30: expected pattern
 error 31: expected SEMI
-error 52: expected expression
-error 52: expected SEMI
 error 53: expected expression
 error 54: expected SEMI
 error 54: expected expression
@@ -168,8 +168,6 @@ error 61: expected SEMI
 error 65: expected pattern
 error 65: expected SEMI
 error 65: expected expression
-error 91: expected expression
-error 91: expected SEMI
 error 92: expected expression
 error 93: expected SEMI
 error 93: expected expression
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.txt
index 6b80ca8d08..8092d70099 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.txt
@@ -20,16 +20,16 @@ SOURCE_FILE@[0; 34)
                   IDENT@[16; 19) "foo"
           ARG_LIST@[19; 31)
             L_PAREN@[19; 20) "("
-            ATTR@[20; 27)
-              POUND@[20; 21) "#"
-              L_BRACK@[21; 22) "["
-              PATH@[22; 26)
-                PATH_SEGMENT@[22; 26)
-                  NAME_REF@[22; 26)
-                    IDENT@[22; 26) "attr"
-              R_BRACK@[26; 27) "]"
-            WHITESPACE@[27; 28) " "
-            LITERAL@[28; 30)
+            LITERAL@[20; 30)
+              ATTR@[20; 27)
+                POUND@[20; 21) "#"
+                L_BRACK@[21; 22) "["
+                PATH@[22; 26)
+                  PATH_SEGMENT@[22; 26)
+                    NAME_REF@[22; 26)
+                      IDENT@[22; 26) "attr"
+                R_BRACK@[26; 27) "]"
+              WHITESPACE@[27; 28) " "
               INT_NUMBER@[28; 30) "92"
             R_PAREN@[30; 31) ")"
         WHITESPACE@[31; 32) "\n"