rustdoc: Resolve imports and reexports
This commit is contained in:
parent
f7f73c79ec
commit
a5ede9d345
@ -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 std::list::{list, nil, cons};
|
||||
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 @@ export exec;
|
||||
|
||||
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 @@ type srv = {
|
||||
};
|
||||
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user