rustc: Support 'companion mod's for crates and directory mods
Under this scheme when parsing foo.rc the parser will also look for foo.rs to fill in the crate-level module, and when evaluating a directory module directive it will look for a .rs file with the same name as the directory.
This commit is contained in:
parent
2cebef095e
commit
e0f44730e8
|
@ -1,5 +1,5 @@
|
|||
|
||||
import std::{str, option};
|
||||
import std::{str, option, result, io, fs};
|
||||
import std::option::{some, none};
|
||||
import syntax::ast;
|
||||
import syntax::parse::token;
|
||||
|
@ -25,11 +25,65 @@ fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str,
|
|||
}
|
||||
|
||||
fn eval_crate_directives_to_mod(cx: ctx, cdirs: [@ast::crate_directive],
|
||||
prefix: str) -> ast::_mod {
|
||||
prefix: str, suffix: option::t<str>)
|
||||
-> (ast::_mod, [ast::attribute]) {
|
||||
log #fmt("eval crate prefix: %s", prefix);
|
||||
log #fmt("eval crate suffix: %s",
|
||||
option::from_maybe("none", suffix));
|
||||
let (cview_items, citems, cattrs)
|
||||
= parse_companion_mod(cx, prefix, suffix);
|
||||
let view_items: [@ast::view_item] = [];
|
||||
let items: [@ast::item] = [];
|
||||
eval_crate_directives(cx, cdirs, prefix, view_items, items);
|
||||
ret {view_items: view_items, items: items};
|
||||
ret ({view_items: view_items + cview_items,
|
||||
items: items + citems},
|
||||
cattrs);
|
||||
}
|
||||
|
||||
/*
|
||||
The 'companion mod'. So .rc crates and directory mod crate directives define
|
||||
modules but not a .rs file to fill those mods with stuff. The companion mod is
|
||||
a convention for location a .rs file to go with them. For .rc files the
|
||||
companion mod is a .rs file with the same name; for directory mods the
|
||||
companion mod is a .rs file with the same name as the directory.
|
||||
|
||||
We build the path to the companion mod by combining the prefix and the
|
||||
optional suffix then adding the .rs extension.
|
||||
*/
|
||||
fn parse_companion_mod(cx: ctx, prefix: str, suffix: option::t<str>)
|
||||
-> ([@ast::view_item], [@ast::item], [ast::attribute]) {
|
||||
|
||||
fn companion_file(prefix: str, suffix: option::t<str>) -> str {
|
||||
alt suffix {
|
||||
option::some(s) { fs::connect(prefix, s) }
|
||||
option::none. { prefix }
|
||||
} + ".rs"
|
||||
}
|
||||
|
||||
fn file_exists(path: str) -> bool {
|
||||
// Crude, but there's no lib function for this and I'm not
|
||||
// up to writing it just now
|
||||
alt io::file_reader(path) {
|
||||
result::ok(_) { true }
|
||||
result::err(_) { false }
|
||||
}
|
||||
}
|
||||
|
||||
let modpath = companion_file(prefix, suffix);
|
||||
log #fmt("looking for companion mod %s", modpath);
|
||||
if file_exists(modpath) {
|
||||
log "found companion mod";
|
||||
let p0 = new_parser_from_file(cx.sess, cx.cfg, modpath,
|
||||
cx.chpos, cx.byte_pos, SOURCE_FILE);
|
||||
let inner_attrs = parse_inner_attrs_and_next(p0);
|
||||
let first_item_outer_attrs = inner_attrs.next;
|
||||
let m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
|
||||
cx.chpos = p0.get_chpos();
|
||||
cx.byte_pos = p0.get_byte_pos();
|
||||
ret (m0.view_items, m0.items, inner_attrs.inner);
|
||||
} else {
|
||||
ret ([], [], []);
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: str,
|
||||
|
@ -66,10 +120,11 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: str,
|
|||
if std::fs::path_is_absolute(path) {
|
||||
path
|
||||
} else { prefix + std::fs::path_sep() + path };
|
||||
let m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
|
||||
let (m0, a0) = eval_crate_directives_to_mod(
|
||||
cx, cdirs, full_path, none);
|
||||
let i =
|
||||
@{ident: id,
|
||||
attrs: attrs,
|
||||
attrs: attrs + a0,
|
||||
id: cx.sess.next_id,
|
||||
node: ast::item_mod(m0),
|
||||
span: cdir.span};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import std::{io, vec, str, option, either, result};
|
||||
import std::{io, vec, str, option, either, result, fs};
|
||||
import std::option::{some, none};
|
||||
import std::either::{left, right};
|
||||
import std::map::{hashmap, new_str_hash};
|
||||
|
@ -2599,13 +2599,15 @@ fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
|
|||
mutable chpos: p.get_chpos(),
|
||||
mutable byte_pos: p.get_byte_pos(),
|
||||
cfg: p.get_cfg()};
|
||||
let m = eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
|
||||
let (companionmod, _) = fs::splitext(fs::basename(input));
|
||||
let (m, attrs) = eval::eval_crate_directives_to_mod(
|
||||
cx, cdirs, prefix, option::some(companionmod));
|
||||
let hi = p.get_hi_pos();
|
||||
expect(p, token::EOF);
|
||||
ret @spanned(lo, hi,
|
||||
{directives: cdirs,
|
||||
module: m,
|
||||
attrs: crate_attrs,
|
||||
attrs: crate_attrs + attrs,
|
||||
config: p.get_cfg()});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std;
|
||||
|
||||
mod compiletest;
|
||||
mod procsrv;
|
||||
mod util;
|
||||
mod header;
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
use std;
|
||||
use rustc;
|
||||
|
||||
mod fuzzer;
|
||||
|
||||
// Local Variables:
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
use std;
|
||||
use rustc;
|
||||
|
||||
import std::{fs, io, getopts, math, vec, str, int, uint, option, result};
|
||||
import std::getopts::{optopt, opt_present, opt_str};
|
||||
import std::io::stdout;
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
import g = x::f;
|
||||
export g;
|
|
@ -0,0 +1 @@
|
|||
fn f() -> str { "ralph" }
|
|
@ -0,0 +1,2 @@
|
|||
import g = x::f;
|
||||
export g;
|
|
@ -0,0 +1 @@
|
|||
fn f() -> str { "nelson" }
|
|
@ -0,0 +1,10 @@
|
|||
// Test that crates and directory modules can contain code
|
||||
|
||||
mod a = "companionmod-src" {
|
||||
mod b {
|
||||
mod x;
|
||||
}
|
||||
mod c = "d" {
|
||||
mod x;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// This isn't really xfailed; it's used by the companionmod.rc test
|
||||
// xfail-test
|
||||
|
||||
fn main() {
|
||||
assert a::b::g() == "ralph";
|
||||
assert a::c::g() == "nelson";
|
||||
}
|
Loading…
Reference in New Issue