Skip to content

Commit 72cc1ac

Browse files
committed
Parse file mods from .rs files
1 parent ddbff6f commit 72cc1ac

File tree

7 files changed

+88
-24
lines changed

7 files changed

+88
-24
lines changed

src/libsyntax/parse/eval.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use parser::{Parser, SOURCE_FILE};
22
use attr::parser_attr;
3+
use ast_util::mk_sp;
34

45
export eval_crate_directives_to_mod;
6+
export eval_src_mod;
57

68
type ctx =
79
@{sess: parse::parse_sess,
@@ -79,29 +81,46 @@ fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
7981
}
8082
}
8183

84+
fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident,
85+
outer_attrs: ~[ast::attribute]) -> (ast::item_, ~[ast::attribute]) {
86+
let file_path = Path(cdir_path_opt(
87+
cx.sess.interner.get(id) + ~".rs", outer_attrs));
88+
let full_path = if file_path.is_absolute {
89+
copy file_path
90+
} else {
91+
prefix.push_many(file_path.components)
92+
};
93+
let p0 =
94+
new_parser_from_file(cx.sess, cx.cfg,
95+
&full_path, SOURCE_FILE);
96+
let inner_attrs = p0.parse_inner_attrs_and_next();
97+
let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
98+
let first_item_outer_attrs = inner_attrs.next;
99+
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
100+
return (ast::item_mod(m0), mod_attrs);
101+
}
102+
103+
// XXX: Duplicated from parser.rs
104+
fn mk_item(ctx: ctx, lo: BytePos, hi: BytePos, +ident: ast::ident,
105+
+node: ast::item_, vis: ast::visibility,
106+
+attrs: ~[ast::attribute]) -> @ast::item {
107+
return @{ident: ident,
108+
attrs: attrs,
109+
id: next_node_id(ctx.sess),
110+
node: node,
111+
vis: vis,
112+
span: mk_sp(lo, hi)};
113+
}
114+
82115
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
83116
view_items: &mut ~[@ast::view_item],
84117
items: &mut ~[@ast::item]) {
85118
match cdir.node {
86119
ast::cdir_src_mod(vis, id, attrs) => {
87-
let file_path = Path(cdir_path_opt(
88-
cx.sess.interner.get(id) + ~".rs", attrs));
89-
let full_path = if file_path.is_absolute {
90-
copy file_path
91-
} else {
92-
prefix.push_many(file_path.components)
93-
};
94-
let p0 =
95-
new_parser_from_file(cx.sess, cx.cfg,
96-
&full_path, SOURCE_FILE);
97-
let inner_attrs = p0.parse_inner_attrs_and_next();
98-
let mod_attrs = vec::append(attrs, inner_attrs.inner);
99-
let first_item_outer_attrs = inner_attrs.next;
100-
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
101-
102-
let i = p0.mk_item(cdir.span.lo, cdir.span.hi,
120+
let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs);
121+
let i = mk_item(cx, cdir.span.lo, cdir.span.hi,
103122
/* FIXME (#2543) */ copy id,
104-
ast::item_mod(m0), vis, mod_attrs);
123+
m, vis, mod_attrs);
105124
items.push(i);
106125
}
107126
ast::cdir_dir_mod(vis, id, cdirs, attrs) => {

src/libsyntax/parse/parser.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,13 +2958,26 @@ impl Parser {
29582958
(id, item_const(ty, e), None)
29592959
}
29602960
2961-
fn parse_item_mod() -> item_info {
2961+
fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info {
29622962
let id = self.parse_ident();
2963-
self.expect(token::LBRACE);
2964-
let inner_attrs = self.parse_inner_attrs_and_next();
2965-
let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
2966-
self.expect(token::RBRACE);
2967-
(id, item_mod(m), Some(inner_attrs.inner))
2963+
if self.token == token::SEMI {
2964+
self.bump();
2965+
// This mod is in an external file. Let's go get it!
2966+
let eval_ctx = @{
2967+
sess: self.sess,
2968+
cfg: self.cfg
2969+
};
2970+
let prefix = Path(self.sess.cm.span_to_filename(copy self.span));
2971+
let prefix = prefix.dir_path();
2972+
let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id, outer_attrs);
2973+
(id, m, Some(move attrs))
2974+
} else {
2975+
self.expect(token::LBRACE);
2976+
let inner_attrs = self.parse_inner_attrs_and_next();
2977+
let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
2978+
self.expect(token::RBRACE);
2979+
(id, item_mod(m), Some(inner_attrs.inner))
2980+
}
29682981
}
29692982
29702983
fn parse_item_foreign_fn( +attrs: ~[attribute]) -> @foreign_item {
@@ -3360,7 +3373,7 @@ impl Parser {
33603373
return self.parse_item_foreign_mod(lo, visibility, attrs,
33613374
items_allowed);
33623375
} else if items_allowed && self.eat_keyword(~"mod") {
3363-
let (ident, item_, extra_attrs) = self.parse_item_mod();
3376+
let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
33643377
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
33653378
visibility,
33663379
maybe_append(attrs, extra_attrs)));

src/test/compile-fail/mod_file_aux.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// xfail-test Not a test. Used by other tests
2+
3+
pub fn foo() -> int { 10 }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Testing that the codemap is maintained correctly when parsing mods from external files
2+
3+
mod mod_file_aux;
4+
5+
fn main() {
6+
assert mod_file_aux::bar() == 10; //~ ERROR unresolved name
7+
}

src/test/run-pass/mod_file.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// xfail-pretty
2+
3+
// Testing that a plain .rs file can load modules from other source files
4+
5+
mod mod_file_aux;
6+
7+
fn main() {
8+
assert mod_file_aux::foo() == 10;
9+
}

src/test/run-pass/mod_file_aux.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// xfail-test Not a test. Used by other tests
2+
3+
pub fn foo() -> int { 10 }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// xfail-pretty
2+
3+
// Testing that a plain .rs file can load modules from other source files
4+
5+
#[path = "mod_file_aux.rs"]
6+
mod m;
7+
8+
fn main() {
9+
assert m::foo() == 10;
10+
}

0 commit comments

Comments
 (0)