about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-07-25 22:18:47 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-07-26 13:12:42 -0700
commita3bf27b1db29887b49614934105a105d1b8d09fc (patch)
treecdfe2c8642eeab38388c495492305a932cb85b30
parent8dbbd81f7ed83943b870407ef44aecf6664e7679 (diff)
downloadrust-a3bf27b1db29887b49614934105a105d1b8d09fc.tar.gz
rust-a3bf27b1db29887b49614934105a105d1b8d09fc.zip
Suggest underscore when using dashes in crate namet push fork
-rw-r--r--src/libsyntax/parse/parser.rs44
-rw-r--r--src/test/ui/bad-crate-name.rs15
-rw-r--r--src/test/ui/bad-crate-name.stderr19
3 files changed, 75 insertions, 3 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2eaa56ebeb8..6dab7865eea 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6508,6 +6508,40 @@ impl<'a> Parser<'a> {
         })
     }
 
+    fn parse_crate_name_with_dashes(
+        &mut self,
+        error_msg: &str,
+        suggestion_msg: &str,
+    ) -> PResult<'a, ast::Ident> {
+        let mut ident = self.parse_ident()?;
+        let mut idents = vec![];
+        let mut replacement = vec![];
+        let mut fixed_crate_name = false;
+        // Accept `extern crate name-like-this` for better diagnostics
+        let dash = token::Token::BinOp(token::BinOpToken::Minus);
+        if self.token == dash {  // Do not include `-` as part of the expected tokens list
+            while self.eat(&dash) {
+                fixed_crate_name = true;
+                replacement.push((self.prev_span, "_".to_string()));
+                idents.push(self.parse_ident()?);
+            }
+        }
+        if fixed_crate_name {
+            let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
+            let mut fixed_name = format!("{}", ident.name);
+            for part in idents {
+                fixed_name.push_str(&format!("_{}", part.name));
+            }
+            ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
+
+            let mut err = self.struct_span_err(fixed_name_sp, error_msg);
+            err.span_label(fixed_name_sp, "dash-separated idents are not valid");
+            err.multipart_suggestion(suggestion_msg, replacement);
+            err.emit();
+        }
+        Ok(ident)
+    }
+
     /// Parse extern crate links
     ///
     /// # Examples
@@ -6519,11 +6553,15 @@ impl<'a> Parser<'a> {
                                visibility: Visibility,
                                attrs: Vec<Attribute>)
                                -> PResult<'a, P<Item>> {
-        let orig_name = self.parse_ident()?;
+        // Accept `extern crate name-like-this` for better diagnostics
+        let ident = self.parse_crate_name_with_dashes(
+            "crate name using dashes are not valid in `extern crate` statements",
+            "if the original crate name uses dashes you need to use underscores in the code",
+        )?;
         let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
-            (rename, Some(orig_name.name))
+            (rename, Some(ident.name))
         } else {
-            (orig_name, None)
+            (ident, None)
         };
         self.expect(&token::Semi)?;
 
diff --git a/src/test/ui/bad-crate-name.rs b/src/test/ui/bad-crate-name.rs
new file mode 100644
index 00000000000..70e1806a20b
--- /dev/null
+++ b/src/test/ui/bad-crate-name.rs
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate krate-name-here;
+//~^ ERROR crate name using dashes are not valid in `extern crate` statements
+//~| ERROR can't find crate for `krate_name_here`
+
+fn main() {}
diff --git a/src/test/ui/bad-crate-name.stderr b/src/test/ui/bad-crate-name.stderr
new file mode 100644
index 00000000000..8348badeeeb
--- /dev/null
+++ b/src/test/ui/bad-crate-name.stderr
@@ -0,0 +1,19 @@
+error: crate name using dashes are not valid in `extern crate` statements
+  --> $DIR/bad-crate-name.rs:11:14
+   |
+LL | extern crate krate-name-here;
+   |              ^^^^^^^^^^^^^^^ dash-separated idents are not valid
+help: if the original crate name uses dashes you need to use underscores in the code
+   |
+LL | extern crate krate_name_here;
+   |                   ^    ^
+
+error[E0463]: can't find crate for `krate_name_here`
+  --> $DIR/bad-crate-name.rs:11:1
+   |
+LL | extern crate krate-name-here;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0463`.