about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-01-31 07:00:19 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-02-13 15:16:36 +0100
commit511dfdb8b3d8c6d395b1b5a205c3464ae802509f (patch)
tree82ecae7c6d6dab0fe23ccfa8f8db2d7031a8f3aa
parent7737d0ffdef6f3d7395e80291e3143522f46b95b (diff)
downloadrust-511dfdb8b3d8c6d395b1b5a205c3464ae802509f.tar.gz
rust-511dfdb8b3d8c6d395b1b5a205c3464ae802509f.zip
parser: extract `recover_missing_kw_before_item`
-rw-r--r--src/librustc_parse/parser/item.rs174
1 files changed, 90 insertions, 84 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index f4ca84b005b..acbae7dfd68 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -203,101 +203,107 @@ impl<'a> Parser<'a> {
             return Ok(Some(macro_def));
         }
 
-        // Verify whether we have encountered a struct or method definition where the user forgot to
-        // add the `struct` or `fn` keyword after writing `pub`: `pub S {}`
         if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) {
-            // Space between `pub` keyword and the identifier
-            //
-            //     pub   S {}
-            //        ^^^ `sp` points here
-            let sp = self.prev_span.between(self.token.span);
-            let full_sp = self.prev_span.to(self.token.span);
-            let ident_sp = self.token.span;
-            if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) {
-                // possible public struct definition where `struct` was forgotten
-                let ident = self.parse_ident().unwrap();
-                let msg = format!("add `struct` here to parse `{}` as a public struct", ident);
-                let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
+            self.recover_missing_kw_before_item()?;
+        }
+        self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis)
+    }
+
+    /// Recover on encountering a struct or method definition where the user
+    /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`.
+    fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
+        // Space between `pub` keyword and the identifier
+        //
+        //     pub   S {}
+        //        ^^^ `sp` points here
+        let sp = self.prev_span.between(self.token.span);
+        let full_sp = self.prev_span.to(self.token.span);
+        let ident_sp = self.token.span;
+        if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) {
+            // possible public struct definition where `struct` was forgotten
+            let ident = self.parse_ident().unwrap();
+            let msg = format!("add `struct` here to parse `{}` as a public struct", ident);
+            let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
+            err.span_suggestion_short(
+                sp,
+                &msg,
+                " struct ".into(),
+                Applicability::MaybeIncorrect, // speculative
+            );
+            return Err(err);
+        } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
+            let ident = self.parse_ident().unwrap();
+            self.bump(); // `(`
+            let kw_name = self.recover_first_param();
+            self.consume_block(token::Paren, ConsumeClosingDelim::Yes);
+            let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
+                self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]);
+                self.bump(); // `{`
+                ("fn", kw_name, false)
+            } else if self.check(&token::OpenDelim(token::Brace)) {
+                self.bump(); // `{`
+                ("fn", kw_name, false)
+            } else if self.check(&token::Colon) {
+                let kw = "struct";
+                (kw, kw, false)
+            } else {
+                ("fn` or `struct", "function or struct", true)
+            };
+
+            let msg = format!("missing `{}` for {} definition", kw, kw_name);
+            let mut err = self.struct_span_err(sp, &msg);
+            if !ambiguous {
+                self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
+                let suggestion =
+                    format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name);
                 err.span_suggestion_short(
                     sp,
-                    &msg,
-                    " struct ".into(),
-                    Applicability::MaybeIncorrect, // speculative
+                    &suggestion,
+                    format!(" {} ", kw),
+                    Applicability::MachineApplicable,
                 );
-                return Err(err);
-            } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
-                let ident = self.parse_ident().unwrap();
-                self.bump(); // `(`
-                let kw_name = self.recover_first_param();
-                self.consume_block(token::Paren, ConsumeClosingDelim::Yes);
-                let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
-                    self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]);
-                    self.bump(); // `{`
-                    ("fn", kw_name, false)
-                } else if self.check(&token::OpenDelim(token::Brace)) {
-                    self.bump(); // `{`
-                    ("fn", kw_name, false)
-                } else if self.check(&token::Colon) {
-                    let kw = "struct";
-                    (kw, kw, false)
-                } else {
-                    ("fn` or `struct", "function or struct", true)
-                };
-
-                let msg = format!("missing `{}` for {} definition", kw, kw_name);
-                let mut err = self.struct_span_err(sp, &msg);
-                if !ambiguous {
-                    self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
-                    let suggestion =
-                        format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name);
-                    err.span_suggestion_short(
-                        sp,
-                        &suggestion,
-                        format!(" {} ", kw),
-                        Applicability::MachineApplicable,
+            } else {
+                if let Ok(snippet) = self.span_to_snippet(ident_sp) {
+                    err.span_suggestion(
+                        full_sp,
+                        "if you meant to call a macro, try",
+                        format!("{}!", snippet),
+                        // this is the `ambiguous` conditional branch
+                        Applicability::MaybeIncorrect,
                     );
                 } else {
-                    if let Ok(snippet) = self.span_to_snippet(ident_sp) {
-                        err.span_suggestion(
-                            full_sp,
-                            "if you meant to call a macro, try",
-                            format!("{}!", snippet),
-                            // this is the `ambiguous` conditional branch
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        err.help(
-                            "if you meant to call a macro, remove the `pub` \
+                    err.help(
+                        "if you meant to call a macro, remove the `pub` \
                                   and add a trailing `!` after the identifier",
-                        );
-                    }
-                }
-                return Err(err);
-            } else if self.look_ahead(1, |t| *t == token::Lt) {
-                let ident = self.parse_ident().unwrap();
-                self.eat_to_tokens(&[&token::Gt]);
-                self.bump(); // `>`
-                let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) {
-                    ("fn", self.recover_first_param(), false)
-                } else if self.check(&token::OpenDelim(token::Brace)) {
-                    ("struct", "struct", false)
-                } else {
-                    ("fn` or `struct", "function or struct", true)
-                };
-                let msg = format!("missing `{}` for {} definition", kw, kw_name);
-                let mut err = self.struct_span_err(sp, &msg);
-                if !ambiguous {
-                    err.span_suggestion_short(
-                        sp,
-                        &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name),
-                        format!(" {} ", kw),
-                        Applicability::MachineApplicable,
                     );
                 }
-                return Err(err);
             }
+            return Err(err);
+        } else if self.look_ahead(1, |t| *t == token::Lt) {
+            let ident = self.parse_ident().unwrap();
+            self.eat_to_tokens(&[&token::Gt]);
+            self.bump(); // `>`
+            let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) {
+                ("fn", self.recover_first_param(), false)
+            } else if self.check(&token::OpenDelim(token::Brace)) {
+                ("struct", "struct", false)
+            } else {
+                ("fn` or `struct", "function or struct", true)
+            };
+            let msg = format!("missing `{}` for {} definition", kw, kw_name);
+            let mut err = self.struct_span_err(sp, &msg);
+            if !ambiguous {
+                err.span_suggestion_short(
+                    sp,
+                    &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name),
+                    format!(" {} ", kw),
+                    Applicability::MachineApplicable,
+                );
+            }
+            return Err(err);
+        } else {
+            Ok(())
         }
-        self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis)
     }
 
     pub(super) fn mk_item_with_info(