Report errors better when failing to open files for sub-parsers

This commit is contained in:
Brian Anderson 2012-11-18 14:14:40 -08:00
parent 72cc1aca17
commit 74b2e99797
6 changed files with 72 additions and 25 deletions

View File

@ -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();
}

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -0,0 +1,5 @@
mod not_a_real_file; //~ ERROR not_a_real_file.rs
fn main() {
assert mod_file_aux::bar() == 10;
}

View File

@ -0,0 +1,6 @@
#[path = "not_a_real_file.rs"]
mod m; //~ ERROR not_a_real_file.rs
fn main() {
assert m::foo() == 10;
}