提交 a5ede9d3 编写于 作者: B Brian Anderson

rustdoc: Resolve imports and reexports

上级 f7f73c79
......@@ -440,17 +440,27 @@ fn build_session_options(match: getopts::match,
fn build_session(sopts: @session::options, input: str,
demitter: diagnostic::emitter) -> session {
let codemap = codemap::new_codemap();
let diagnostic_handler =
diagnostic::mk_handler(some(demitter));
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);
build_session_(sopts, input, codemap, demitter,
span_diagnostic_handler)
}
fn build_session_(
sopts: @session::options, input: str,
codemap: codemap::codemap,
demitter: diagnostic::emitter,
span_diagnostic_handler: diagnostic::span_handler
) -> session {
let target_cfg = build_target_config(sopts, demitter);
let cstore = cstore::mk_cstore();
let filesearch = filesearch::mk_filesearch(
sopts.maybe_sysroot,
sopts.target_triple,
sopts.addl_lib_search_paths);
let codemap = codemap::new_codemap();
let diagnostic_handler =
diagnostic::mk_handler(some(demitter));
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);
@{targ_cfg: target_cfg,
opts: sopts,
cstore: cstore,
......
......@@ -19,7 +19,7 @@
import option::{is_none, is_some};
import syntax::print::pprust::*;
export resolve_crate;
export resolve_crate, resolve_crate_reexports;
export def_map, ext_map, exp_map, impl_map;
export _impl, iscopes, method_info;
......@@ -155,24 +155,7 @@ enum ns_value_type { ns_a_enum, ns_any_value, }
fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
{def_map: def_map, exp_map: exp_map, impl_map: impl_map} {
let e =
@{cstore: sess.cstore,
def_map: new_int_hash(),
ast_map: amap,
imports: new_int_hash(),
exp_map: new_str_hash(),
mod_map: new_int_hash(),
block_map: new_int_hash(),
ext_map: new_def_hash(),
impl_map: new_int_hash(),
impl_cache: new_def_hash(),
ext_cache: new_ext_hash(),
used_imports: {mutable track: false, mutable data: []},
mutable reported: [],
mutable ignored_imports: [],
mutable current_tp: none,
mutable resolve_unexported: false,
sess: sess};
let e = create_env(sess, amap);
map_crate(e, crate);
resolve_imports(*e);
check_exports(e);
......@@ -187,6 +170,36 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
ret {def_map: e.def_map, exp_map: e.exp_map, impl_map: e.impl_map};
}
// Used by rustdoc
fn resolve_crate_reexports(sess: session, amap: ast_map::map,
crate: @ast::crate) -> exp_map {
let e = create_env(sess, amap);
map_crate(e, crate);
resolve_imports(*e);
check_exports(e);
ret e.exp_map;
}
fn create_env(sess: session, amap: ast_map::map) -> @env {
@{cstore: sess.cstore,
def_map: new_int_hash(),
ast_map: amap,
imports: new_int_hash(),
exp_map: new_str_hash(),
mod_map: new_int_hash(),
block_map: new_int_hash(),
ext_map: new_def_hash(),
impl_map: new_int_hash(),
impl_cache: new_def_hash(),
ext_cache: new_ext_hash(),
used_imports: {mutable track: false, mutable data: []},
mutable reported: [],
mutable ignored_imports: [],
mutable current_tp: none,
mutable resolve_unexported: false,
sess: sess}
}
// Locate all modules and imports and index them, so that the next passes can
// resolve through them.
fn map_crate(e: @env, c: @ast::crate) {
......
......@@ -10,11 +10,14 @@
import rustc::driver::session;
import rustc::driver::driver;
import rustc::driver::diagnostic;
import rustc::driver::diagnostic::handler;
import rustc::syntax::ast;
import rustc::syntax::codemap;
import rustc::middle::ast_map;
import rustc::back::link;
import rustc::util::filesearch;
import rustc::front;
import rustc::middle::resolve;
export ctxt;
export ctxt_handler;
......@@ -25,7 +28,8 @@
type ctxt = {
ast: @ast::crate,
ast_map: ast_map::map
ast_map: ast_map::map,
exp_map: resolve::exp_map
};
type ctxt_handler<T> = fn~(ctxt: ctxt) -> T;
......@@ -35,36 +39,43 @@
};
fn mk_srv_from_str(source: str) -> srv {
let sess = build_session();
let (sess, ignore_errors) = build_session();
{
ctxt: build_ctxt(sess, parse::from_str_sess(sess, source))
ctxt: build_ctxt(sess, parse::from_str_sess(sess, source),
ignore_errors)
}
}
fn mk_srv_from_file(file: str) -> srv {
let sess = build_session();
let (sess, ignore_errors) = build_session();
{
ctxt: build_ctxt(sess, parse::from_file_sess(sess, file))
ctxt: build_ctxt(sess, parse::from_file_sess(sess, file),
ignore_errors)
}
}
fn build_ctxt(sess: session::session, ast: @ast::crate) -> ctxt {
fn build_ctxt(sess: session::session, ast: @ast::crate,
ignore_errors: @mutable bool) -> ctxt {
import rustc::front::config;
let ast = config::strip_unconfigured_items(ast);
let ast = front::test::modify_for_testing(sess, ast);
let ast_map = ast_map::map_crate(*ast);
*ignore_errors = true;
let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast);
*ignore_errors = false;
{
ast: ast,
ast_map: ast_map,
exp_map: exp_map
}
}
// FIXME: this whole structure should not be duplicated here. makes it
// painful to add or remove options.
fn build_session() -> session::session {
fn build_session() -> (session::session, @mutable bool) {
let sopts: @session::options = @{
crate_type: session::lib_crate,
static: false,
......@@ -89,7 +100,73 @@ fn build_session() -> session::session {
monomorphize: false,
warn_unused_imports: false
};
driver::build_session(sopts, ".", diagnostic::emit)
let codemap = codemap::new_codemap();
let error_handlers = build_error_handlers(codemap);
let {emitter, span_handler, ignore_errors} = error_handlers;
let session = driver::build_session_(sopts, ".", codemap, emitter,
span_handler);
(session, ignore_errors)
}
type error_handlers = {
emitter: diagnostic::emitter,
span_handler: diagnostic::span_handler,
ignore_errors: @mutable bool
};
// Build a custom error handler that will allow us to ignore non-fatal
// errors
fn build_error_handlers(
codemap: codemap::codemap
) -> error_handlers {
type diagnostic_handler = {
inner: diagnostic::handler,
ignore_errors: @mutable bool
};
impl of diagnostic::handler for diagnostic_handler {
fn fatal(msg: str) -> ! { self.inner.fatal(msg) }
fn err(msg: str) { self.inner.err(msg) }
fn bump_err_count() {
if !(*self.ignore_errors) {
self.inner.bump_err_count();
}
}
fn has_errors() -> bool { self.inner.has_errors() }
fn abort_if_errors() { self.inner.abort_if_errors() }
fn warn(msg: str) { self.inner.warn(msg) }
fn note(msg: str) { self.inner.note(msg) }
fn bug(msg: str) -> ! { self.inner.bug(msg) }
fn unimpl(msg: str) -> ! { self.inner.unimpl(msg) }
fn emit(cmsp: option<(codemap::codemap, codemap::span)>,
msg: str, lvl: diagnostic::level) {
self.inner.emit(cmsp, msg, lvl)
}
}
let ignore_errors = @mutable false;
let emitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
msg: str, lvl: diagnostic::level) {
if !(*ignore_errors) {
diagnostic::emit(cmsp, msg, lvl);
}
};
let inner_handler = diagnostic::mk_handler(some(emitter));
let handler = {
inner: inner_handler,
ignore_errors: ignore_errors
};
let span_handler = diagnostic::mk_span_handler(
handler as diagnostic::handler, codemap);
{
emitter: emitter,
span_handler: span_handler,
ignore_errors: ignore_errors
}
}
#[test]
......@@ -111,14 +188,12 @@ fn srv_should_build_ast_map() {
}
#[test]
#[ignore]
fn srv_should_build_reexport_map() {
// FIXME
/*let source = "import a::b; export b; mod a { mod b { } }";
let source = "import a::b; export b; mod a { mod b { } }";
let srv = mk_srv_from_str(source);
exec(srv) {|ctxt|
assert ctxt.exp_map.size() != 0u
};*/
};
}
#[test]
......@@ -137,6 +212,20 @@ fn srv_should_resolve_core_crate() {
mk_srv_from_str(source);
}
#[test]
fn srv_should_resolve_non_existant_imports() {
// We want to ignore things we can't resolve. Shouldn't
// need to be able to find external crates to create docs.
let source = "import wooboo; fn a() { }";
mk_srv_from_str(source);
}
#[test]
fn srv_sholud_resolve_non_existant_uses() {
let source = "use forble; fn a() { }";
mk_srv_from_str(source);
}
fn exec<T>(
srv: srv,
f: fn~(ctxt: ctxt) -> T
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册