Report errors better when failing to open files for sub-parsers
This commit is contained in:
parent
72cc1aca17
commit
74b2e99797
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
5
src/test/compile-fail/mod_file_not_exist.rs
Normal file
5
src/test/compile-fail/mod_file_not_exist.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod not_a_real_file; //~ ERROR not_a_real_file.rs
|
||||
|
||||
fn main() {
|
||||
assert mod_file_aux::bar() == 10;
|
||||
}
|
6
src/test/compile-fail/mod_file_with_path_attr.rs
Normal file
6
src/test/compile-fail/mod_file_with_path_attr.rs
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user