]> git.lizzy.rs Git - rust.git/commitdiff
Parse file mods from .rs files
authorBrian Anderson <banderson@mozilla.com>
Sat, 10 Nov 2012 00:31:44 +0000 (16:31 -0800)
committerBrian Anderson <banderson@mozilla.com>
Mon, 19 Nov 2012 02:09:41 +0000 (18:09 -0800)
src/libsyntax/parse/eval.rs
src/libsyntax/parse/parser.rs
src/test/compile-fail/mod_file_aux.rs [new file with mode: 0644]
src/test/compile-fail/mod_file_correct_spans.rs [new file with mode: 0644]
src/test/run-pass/mod_file.rs [new file with mode: 0644]
src/test/run-pass/mod_file_aux.rs [new file with mode: 0644]
src/test/run-pass/mod_file_with_path_attr.rs [new file with mode: 0644]

index 9a81d6463060d798bac0e4df7ca318b044aca985..660e88c7101d2c7f9cf12f698905b34c10b80cdc 100644 (file)
@@ -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) => {
index 2f96f6ba0a098f05585f6dfc06797f5bc634d0c3..12ae135e52550b92da09830cbb3d95ac6e68d179 100644 (file)
@@ -2958,13 +2958,26 @@ fn parse_item_const() -> item_info {
         (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 @@ fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool,
             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)));
diff --git a/src/test/compile-fail/mod_file_aux.rs b/src/test/compile-fail/mod_file_aux.rs
new file mode 100644 (file)
index 0000000..313efe5
--- /dev/null
@@ -0,0 +1,3 @@
+// xfail-test Not a test. Used by other tests
+
+pub fn foo() -> int { 10 }
diff --git a/src/test/compile-fail/mod_file_correct_spans.rs b/src/test/compile-fail/mod_file_correct_spans.rs
new file mode 100644 (file)
index 0000000..b34c11a
--- /dev/null
@@ -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
+}
\ No newline at end of file
diff --git a/src/test/run-pass/mod_file.rs b/src/test/run-pass/mod_file.rs
new file mode 100644 (file)
index 0000000..6e8cb22
--- /dev/null
@@ -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;
+}
\ No newline at end of file
diff --git a/src/test/run-pass/mod_file_aux.rs b/src/test/run-pass/mod_file_aux.rs
new file mode 100644 (file)
index 0000000..313efe5
--- /dev/null
@@ -0,0 +1,3 @@
+// xfail-test Not a test. Used by other tests
+
+pub fn foo() -> int { 10 }
diff --git a/src/test/run-pass/mod_file_with_path_attr.rs b/src/test/run-pass/mod_file_with_path_attr.rs
new file mode 100644 (file)
index 0000000..e719109
--- /dev/null
@@ -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;
+}
\ No newline at end of file