Parse file mods from .rs files
This commit is contained in:
parent
ddbff6fd2a
commit
72cc1aca17
@ -1,7 +1,9 @@
|
||||
use parser::{Parser, SOURCE_FILE};
|
||||
use attr::parser_attr;
|
||||
use ast_util::mk_sp;
|
||||
|
||||
export eval_crate_directives_to_mod;
|
||||
export eval_src_mod;
|
||||
|
||||
type ctx =
|
||||
@{sess: parse::parse_sess,
|
||||
@ -79,29 +81,46 @@ 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]) {
|
||||
let file_path = Path(cdir_path_opt(
|
||||
cx.sess.interner.get(id) + ~".rs", outer_attrs));
|
||||
let full_path = if file_path.is_absolute {
|
||||
copy file_path
|
||||
} else {
|
||||
prefix.push_many(file_path.components)
|
||||
};
|
||||
let p0 =
|
||||
new_parser_from_file(cx.sess, cx.cfg,
|
||||
&full_path, SOURCE_FILE);
|
||||
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;
|
||||
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
|
||||
return (ast::item_mod(m0), mod_attrs);
|
||||
}
|
||||
|
||||
// XXX: Duplicated from parser.rs
|
||||
fn mk_item(ctx: ctx, lo: BytePos, hi: BytePos, +ident: ast::ident,
|
||||
+node: ast::item_, vis: ast::visibility,
|
||||
+attrs: ~[ast::attribute]) -> @ast::item {
|
||||
return @{ident: ident,
|
||||
attrs: attrs,
|
||||
id: next_node_id(ctx.sess),
|
||||
node: node,
|
||||
vis: vis,
|
||||
span: mk_sp(lo, hi)};
|
||||
}
|
||||
|
||||
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
|
||||
view_items: &mut ~[@ast::view_item],
|
||||
items: &mut ~[@ast::item]) {
|
||||
match cdir.node {
|
||||
ast::cdir_src_mod(vis, id, attrs) => {
|
||||
let file_path = Path(cdir_path_opt(
|
||||
cx.sess.interner.get(id) + ~".rs", attrs));
|
||||
let full_path = if file_path.is_absolute {
|
||||
copy file_path
|
||||
} else {
|
||||
prefix.push_many(file_path.components)
|
||||
};
|
||||
let p0 =
|
||||
new_parser_from_file(cx.sess, cx.cfg,
|
||||
&full_path, SOURCE_FILE);
|
||||
let inner_attrs = p0.parse_inner_attrs_and_next();
|
||||
let mod_attrs = vec::append(attrs, inner_attrs.inner);
|
||||
let first_item_outer_attrs = inner_attrs.next;
|
||||
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
|
||||
|
||||
let i = p0.mk_item(cdir.span.lo, cdir.span.hi,
|
||||
let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs);
|
||||
let i = mk_item(cx, cdir.span.lo, cdir.span.hi,
|
||||
/* FIXME (#2543) */ copy id,
|
||||
ast::item_mod(m0), vis, mod_attrs);
|
||||
m, vis, mod_attrs);
|
||||
items.push(i);
|
||||
}
|
||||
ast::cdir_dir_mod(vis, id, cdirs, attrs) => {
|
||||
|
@ -2958,13 +2958,26 @@ impl Parser {
|
||||
(id, item_const(ty, e), None)
|
||||
}
|
||||
|
||||
fn parse_item_mod() -> item_info {
|
||||
fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info {
|
||||
let id = self.parse_ident();
|
||||
self.expect(token::LBRACE);
|
||||
let inner_attrs = self.parse_inner_attrs_and_next();
|
||||
let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
|
||||
self.expect(token::RBRACE);
|
||||
(id, item_mod(m), Some(inner_attrs.inner))
|
||||
if self.token == token::SEMI {
|
||||
self.bump();
|
||||
// This mod is in an external file. Let's go get it!
|
||||
let eval_ctx = @{
|
||||
sess: self.sess,
|
||||
cfg: self.cfg
|
||||
};
|
||||
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);
|
||||
(id, m, Some(move attrs))
|
||||
} else {
|
||||
self.expect(token::LBRACE);
|
||||
let inner_attrs = self.parse_inner_attrs_and_next();
|
||||
let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
|
||||
self.expect(token::RBRACE);
|
||||
(id, item_mod(m), Some(inner_attrs.inner))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_item_foreign_fn( +attrs: ~[attribute]) -> @foreign_item {
|
||||
@ -3360,7 +3373,7 @@ impl Parser {
|
||||
return self.parse_item_foreign_mod(lo, visibility, attrs,
|
||||
items_allowed);
|
||||
} else if items_allowed && self.eat_keyword(~"mod") {
|
||||
let (ident, item_, extra_attrs) = self.parse_item_mod();
|
||||
let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
|
||||
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs)));
|
||||
|
3
src/test/compile-fail/mod_file_aux.rs
Normal file
3
src/test/compile-fail/mod_file_aux.rs
Normal file
@ -0,0 +1,3 @@
|
||||
// xfail-test Not a test. Used by other tests
|
||||
|
||||
pub fn foo() -> int { 10 }
|
7
src/test/compile-fail/mod_file_correct_spans.rs
Normal file
7
src/test/compile-fail/mod_file_correct_spans.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// Testing that the codemap is maintained correctly when parsing mods from external files
|
||||
|
||||
mod mod_file_aux;
|
||||
|
||||
fn main() {
|
||||
assert mod_file_aux::bar() == 10; //~ ERROR unresolved name
|
||||
}
|
9
src/test/run-pass/mod_file.rs
Normal file
9
src/test/run-pass/mod_file.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// xfail-pretty
|
||||
|
||||
// Testing that a plain .rs file can load modules from other source files
|
||||
|
||||
mod mod_file_aux;
|
||||
|
||||
fn main() {
|
||||
assert mod_file_aux::foo() == 10;
|
||||
}
|
3
src/test/run-pass/mod_file_aux.rs
Normal file
3
src/test/run-pass/mod_file_aux.rs
Normal file
@ -0,0 +1,3 @@
|
||||
// xfail-test Not a test. Used by other tests
|
||||
|
||||
pub fn foo() -> int { 10 }
|
10
src/test/run-pass/mod_file_with_path_attr.rs
Normal file
10
src/test/run-pass/mod_file_with_path_attr.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// xfail-pretty
|
||||
|
||||
// Testing that a plain .rs file can load modules from other source files
|
||||
|
||||
#[path = "mod_file_aux.rs"]
|
||||
mod m;
|
||||
|
||||
fn main() {
|
||||
assert m::foo() == 10;
|
||||
}
|
Loading…
Reference in New Issue
Block a user