about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-11-18 14:14:40 -0800
committerBrian Anderson <banderson@mozilla.com>2012-11-18 18:09:41 -0800
commit74b2e9979738ce413209aa4342fc35afe68c68de (patch)
tree1a6c24b0e8ea072cb651f60170e420e1a64686ae
parent72cc1aca175044ceb003a8b270940bec1da85460 (diff)
downloadrust-74b2e9979738ce413209aa4342fc35afe68c68de.tar.gz
rust-74b2e9979738ce413209aa4342fc35afe68c68de.zip
Report errors better when failing to open files for sub-parsers
-rw-r--r--src/libsyntax/ext/source_util.rs7
-rw-r--r--src/libsyntax/parse.rs59
-rw-r--r--src/libsyntax/parse/eval.rs16
-rw-r--r--src/libsyntax/parse/parser.rs4
-rw-r--r--src/test/compile-fail/mod_file_not_exist.rs5
-rw-r--r--src/test/compile-fail/mod_file_with_path_attr.rs6
6 files changed, 72 insertions, 25 deletions
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index baf92175e7d..1bd3ec8423e 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -58,9 +58,10 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                   _body: ast::mac_body) -> @ast::expr {
     let args = get_mac_args(cx, sp, arg, 1u, option::Some(1u), ~"include");
     let file = expr_to_str(cx, args[0], ~"include_str! requires a string");
-    let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(),
-                                        &res_rel_file(cx, sp, &Path(file)),
-                                        parse::parser::SOURCE_FILE);
+    let p = parse::new_sub_parser_from_file(
+        cx.parse_sess(), cx.cfg(),
+        &res_rel_file(cx, sp, &Path(file)),
+        parse::parser::SOURCE_FILE, sp);
     return p.parse_expr();
 }
 
diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs
index 593ff6d034e..fc9474bab24 100644
--- a/src/libsyntax/parse.rs
+++ b/src/libsyntax/parse.rs
@@ -6,6 +6,7 @@ export next_node_id;
 export new_parser_from_file, new_parser_etc_from_file;
 export new_parser_from_source_str;
 export new_parser_from_tt;
+export new_sub_parser_from_file;
 export parse_crate_from_file, parse_crate_from_crate_file;
 export parse_crate_from_source_str;
 export parse_expr_from_source_str, parse_item_from_source_str;
@@ -20,7 +21,7 @@ use util::interner;
 use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter};
 use lexer::{reader, string_reader};
 use parse::token::{ident_interner, mk_ident_interner};
-use codemap::{CodeMap, FileMap, CharPos, BytePos};
+use codemap::{span, CodeMap, FileMap, CharPos, BytePos};
 
 type parse_sess = @{
     cm: @codemap::CodeMap,
@@ -61,8 +62,8 @@ fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
 
 fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
-    let p = new_parser_from_file(sess, cfg, input,
-                                 parser::CRATE_FILE);
+    let p = new_crate_parser_from_file(sess, cfg, input,
+                                       parser::CRATE_FILE);
     let lo = p.span.lo;
     let prefix = input.dir_path();
     let leading_attrs = p.parse_inner_attrs_and_next();
@@ -84,8 +85,8 @@ fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
 
 fn parse_crate_from_source_file(input: &Path, cfg: ast::crate_cfg,
                                 sess: parse_sess) -> @ast::crate {
-    let p = new_parser_from_file(sess, cfg, input,
-                                 parser::SOURCE_FILE);
+    let p = new_crate_parser_from_file(sess, cfg, input,
+                                       parser::SOURCE_FILE);
     let r = p.parse_crate_mod(cfg);
     return r;
 }
@@ -163,17 +164,45 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
 }
 
 fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
-                        path: &Path, ftype: parser::file_type) -> Parser {
-    let res = io::read_whole_file_str(path);
-    match res {
-      result::Ok(_) => { /* Continue. */ }
-      result::Err(e) => sess.span_diagnostic.handler().fatal(e)
+                        path: &Path,
+                        ftype: parser::file_type) -> Result<Parser, ~str> {
+    match io::read_whole_file_str(path) {
+      result::Ok(move src) => {
+          let filemap = sess.cm.new_filemap(path.to_str(), @move src);
+          let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
+                                              sess.interner);
+
+          Ok(Parser(sess, cfg, srdr as reader, ftype))
+
+      }
+      result::Err(move e) => Err(move e)
+    }
+}
+
+/// Create a new parser for an entire crate, handling errors as appropriate
+/// if the file doesn't exist
+fn new_crate_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+                              path: &Path,
+                              ftype: parser::file_type) -> Parser {
+    match new_parser_from_file(sess, cfg, path, ftype) {
+        Ok(move parser) => move parser,
+        Err(move e) => {
+            sess.span_diagnostic.handler().fatal(e)
+        }
+    }
+}
+
+/// Create a new parser based on a span from an existing parser. Handles
+/// error messages correctly when the file does not exist.
+fn new_sub_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+                            path: &Path, ftype: parser::file_type,
+                            sp: span) -> Parser {
+    match new_parser_from_file(sess, cfg, path, ftype) {
+        Ok(move parser) => move parser,
+        Err(move e) => {
+            sess.span_diagnostic.span_fatal(sp, e)
+        }
     }
-    let src = @result::unwrap(res);
-    let filemap = sess.cm.new_filemap(path.to_str(), src);
-    let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
-                                        sess.interner);
-    return Parser(sess, cfg, srdr as reader, ftype);
 }
 
 fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg,
diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs
index 660e88c7101..1873a346270 100644
--- a/src/libsyntax/parse/eval.rs
+++ b/src/libsyntax/parse/eval.rs
@@ -1,6 +1,7 @@
 use parser::{Parser, SOURCE_FILE};
 use attr::parser_attr;
 use ast_util::mk_sp;
+use codemap::span;
 
 export eval_crate_directives_to_mod;
 export eval_src_mod;
@@ -64,8 +65,10 @@ fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &Option<Path>)
     let modpath = &companion_file(prefix, suffix);
     if file_exists(modpath) {
         debug!("found companion mod");
-        let p0 = new_parser_from_file(cx.sess, cx.cfg,
-                                      modpath, SOURCE_FILE);
+        // XXX: Using a dummy span, but this code will go away soon
+        let p0 = new_sub_parser_from_file(cx.sess, cx.cfg,
+                                          modpath, SOURCE_FILE,
+                                          ast_util::dummy_sp());
         let inner_attrs = p0.parse_inner_attrs_and_next();
         let m0 = p0.parse_mod_items(token::EOF, inner_attrs.next);
         return (m0.view_items, m0.items, inner_attrs.inner);
@@ -82,7 +85,8 @@ fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
 }
 
 fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident,
-                outer_attrs: ~[ast::attribute]) -> (ast::item_, ~[ast::attribute]) {
+                outer_attrs: ~[ast::attribute],
+                sp: span) -> (ast::item_, ~[ast::attribute]) {
     let file_path = Path(cdir_path_opt(
         cx.sess.interner.get(id) + ~".rs", outer_attrs));
     let full_path = if file_path.is_absolute {
@@ -91,8 +95,8 @@ fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident,
         prefix.push_many(file_path.components)
     };
     let p0 =
-        new_parser_from_file(cx.sess, cx.cfg,
-                             &full_path, SOURCE_FILE);
+        new_sub_parser_from_file(cx.sess, cx.cfg,
+                                 &full_path, SOURCE_FILE, sp);
     let inner_attrs = p0.parse_inner_attrs_and_next();
     let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
     let first_item_outer_attrs = inner_attrs.next;
@@ -117,7 +121,7 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
                         items: &mut ~[@ast::item]) {
     match cdir.node {
       ast::cdir_src_mod(vis, id, attrs) => {
-        let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs);
+        let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs, cdir.span);
         let i = mk_item(cx, cdir.span.lo, cdir.span.hi,
                            /* FIXME (#2543) */ copy id,
                            m, vis, mod_attrs);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 12ae135e525..9d71f83b28d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2959,6 +2959,7 @@ impl Parser {
     }
 
     fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info {
+        let id_span = self.span;
         let id = self.parse_ident();
         if self.token == token::SEMI {
             self.bump();
@@ -2969,7 +2970,8 @@ impl Parser {
             };
             let prefix = Path(self.sess.cm.span_to_filename(copy self.span));
             let prefix = prefix.dir_path();
-            let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id, outer_attrs);
+            let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id,
+                                                outer_attrs, id_span);
             (id, m, Some(move attrs))
         } else {
             self.expect(token::LBRACE);
diff --git a/src/test/compile-fail/mod_file_not_exist.rs b/src/test/compile-fail/mod_file_not_exist.rs
new file mode 100644
index 00000000000..5e571af8955
--- /dev/null
+++ b/src/test/compile-fail/mod_file_not_exist.rs
@@ -0,0 +1,5 @@
+mod not_a_real_file; //~ ERROR not_a_real_file.rs
+
+fn main() {
+    assert mod_file_aux::bar() == 10;
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/mod_file_with_path_attr.rs b/src/test/compile-fail/mod_file_with_path_attr.rs
new file mode 100644
index 00000000000..3baa18be9f1
--- /dev/null
+++ b/src/test/compile-fail/mod_file_with_path_attr.rs
@@ -0,0 +1,6 @@
+#[path = "not_a_real_file.rs"]
+mod m; //~ ERROR not_a_real_file.rs
+
+fn main() {
+    assert m::foo() == 10;
+}
\ No newline at end of file