diff options
| author | Tom Jakubowski <tom@crystae.net> | 2014-07-19 23:02:14 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-07-21 09:54:29 -0700 |
| commit | ec70f2bb6e8cd3dd187abba351e6cf9eb14a37c1 (patch) | |
| tree | 0f181e1bdc3cc89102421429f7b86199f0a51673 | |
| parent | 97ca98f5ccda65589049397723662e634ada04a4 (diff) | |
| download | rust-ec70f2bb6e8cd3dd187abba351e6cf9eb14a37c1.tar.gz rust-ec70f2bb6e8cd3dd187abba351e6cf9eb14a37c1.zip | |
rustdoc: Add an --extern flag analagous to rustc's
This adds an `--extern` flag to `rustdoc` much like the compiler's to specify the path where a given crate can be found.
| -rw-r--r-- | src/librustc/driver/config.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/core.rs | 9 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 51 | ||||
| -rw-r--r-- | src/librustdoc/markdown.rs | 6 | ||||
| -rw-r--r-- | src/librustdoc/test.rs | 15 |
5 files changed, 66 insertions, 17 deletions
diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 2d200c82a94..dd951d963e0 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -582,7 +582,7 @@ pub fn optgroups() -> Vec<getopts::OptGroup> { always = always colorize output; never = never colorize output", "auto|always|never"), optmulti("", "extern", "Specify where an external rust library is located", - "PATH"), + "NAME=PATH"), ) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b1c715ae5b3..7f021510f4a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -77,8 +77,10 @@ pub struct CrateAnalysis { pub inlined: RefCell<Option<HashSet<ast::DefId>>>, } +pub type Externs = HashMap<String, Vec<String>>; + /// Parses, resolves, and typechecks the given crate -fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>) +fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>, externs: Externs) -> (DocContext, CrateAnalysis) { use syntax::codemap::dummy_spanned; use rustc::driver::driver::{FileInput, @@ -96,6 +98,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>) addl_lib_search_paths: RefCell::new(libs), crate_types: vec!(driver::config::CrateTypeRlib), lint_opts: vec!((warning_lint, lint::Allow)), + externs: externs, ..rustc::driver::config::basic_options().clone() }; @@ -148,9 +151,9 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>) }) } -pub fn run_core(libs: HashSet<Path>, cfgs: Vec<String>, path: &Path) +pub fn run_core(libs: HashSet<Path>, cfgs: Vec<String>, externs: Externs, path: &Path) -> (clean::Crate, CrateAnalysis) { - let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs); + let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs, externs); let ctxt = box(GC) ctxt; super::ctxtkey.replace(Some(ctxt)); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 245dc9a0a34..a7c9ac10118 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -30,6 +30,7 @@ extern crate time; use std::io; use std::io::{File, MemWriter}; use std::gc::Gc; +use std::collections::HashMap; use serialize::{json, Decodable, Encodable}; use externalfiles::ExternalHtml; @@ -104,6 +105,7 @@ pub fn opts() -> Vec<getopts::OptGroup> { optmulti("L", "library-path", "directory to add to crate search path", "DIR"), optmulti("", "cfg", "pass a --cfg to rustc", ""), + optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH"), optmulti("", "plugin-path", "directory to load plugins from", "DIR"), optmulti("", "passes", "space separated list of passes to also run, a \ value of `list` will print available passes", @@ -170,6 +172,13 @@ pub fn main_args(args: &[String]) -> int { let input = matches.free[0].as_slice(); let libs = matches.opt_strs("L").iter().map(|s| Path::new(s.as_slice())).collect(); + let externs = match parse_externs(&matches) { + Ok(ex) => ex, + Err(err) => { + println!("{}", err); + return 1; + } + }; let test_args = matches.opt_strs("test-args"); let test_args: Vec<String> = test_args.iter() @@ -193,10 +202,10 @@ pub fn main_args(args: &[String]) -> int { match (should_test, markdown_input) { (true, true) => { - return markdown::test(input, libs, test_args) + return markdown::test(input, libs, externs, test_args) } (true, false) => { - return test::run(input, cfgs, libs, test_args) + return test::run(input, cfgs, libs, externs, test_args) } (false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")), &matches, &external_html), @@ -215,7 +224,7 @@ pub fn main_args(args: &[String]) -> int { return 0; } - let (krate, res) = match acquire_input(input, &matches) { + let (krate, res) = match acquire_input(input, externs, &matches) { Ok(pair) => pair, Err(s) => { println!("input error: {}", s); @@ -252,27 +261,53 @@ pub fn main_args(args: &[String]) -> int { /// Looks inside the command line arguments to extract the relevant input format /// and files and then generates the necessary rustdoc output for formatting. fn acquire_input(input: &str, + externs: core::Externs, matches: &getopts::Matches) -> Result<Output, String> { match matches.opt_str("r").as_ref().map(|s| s.as_slice()) { - Some("rust") => Ok(rust_input(input, matches)), + Some("rust") => Ok(rust_input(input, externs, matches)), Some("json") => json_input(input), Some(s) => Err(format!("unknown input format: {}", s)), None => { if input.ends_with(".json") { json_input(input) } else { - Ok(rust_input(input, matches)) + Ok(rust_input(input, externs, matches)) } } } } +/// Extracts `--extern CRATE=PATH` arguments from `matches` and +/// returns a `HashMap` mapping crate names to their paths or else an +/// error message. +fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> { + let mut externs = HashMap::new(); + for arg in matches.opt_strs("extern").iter() { + let mut parts = arg.as_slice().splitn('=', 1); + let name = match parts.next() { + Some(s) => s, + None => { + return Err("--extern value must not be empty".to_string()); + } + }; + let location = match parts.next() { + Some(s) => s, + None => { + return Err("--extern value must be of the format `foo=bar`".to_string()); + } + }; + let locs = externs.find_or_insert(name.to_string(), Vec::new()); + locs.push(location.to_string()); + } + Ok(externs) +} + /// Interprets the input file as a rust source file, passing it through the /// compiler all the way through the analysis passes. The rustdoc output is then /// generated from the cleaned AST of the crate. /// /// This form of input will run all of the plug/cleaning passes -fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output { +fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matches) -> Output { let mut default_passes = !matches.opt_present("no-defaults"); let mut passes = matches.opt_strs("passes"); let mut plugins = matches.opt_strs("plugins"); @@ -283,12 +318,14 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output { .map(|s| Path::new(s.as_slice())) .collect(); let cfgs = matches.opt_strs("cfg"); + let cr = Path::new(cratefile); info!("starting to run rustc"); let (krate, analysis) = std::task::try(proc() { let cr = cr; - core::run_core(libs.move_iter().map(|x| x.clone()).collect(), + core::run_core(libs.move_iter().collect(), cfgs, + externs, &cr) }).map_err(|boxed_any|format!("{:?}", boxed_any)).unwrap(); info!("finished with rustc"); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index f9bc59888ae..47009c1f2cc 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -12,6 +12,7 @@ use std::collections::HashSet; use std::io; use std::string::String; +use core; use getopts; use testing; @@ -129,10 +130,11 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, } /// Run any tests/code examples in the markdown file `input`. -pub fn test(input: &str, libs: HashSet<Path>, mut test_args: Vec<String>) -> int { +pub fn test(input: &str, libs: HashSet<Path>, externs: core::Externs, + mut test_args: Vec<String>) -> int { let input_str = load_or_return!(input, 1, 2); - let mut collector = Collector::new(input.to_string(), libs, true); + let mut collector = Collector::new(input.to_string(), libs, externs, true); find_testable_code(input_str.as_slice(), &mut collector); test_args.unshift("rustdoctest".to_string()); testing::test_main(test_args.as_slice(), collector.tests); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 8fe28d1eab8..2ed35469dfa 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -40,6 +40,7 @@ use visit_ast::RustdocVisitor; pub fn run(input: &str, cfgs: Vec<String>, libs: HashSet<Path>, + externs: core::Externs, mut test_args: Vec<String>) -> int { let input_path = Path::new(input); @@ -49,10 +50,10 @@ pub fn run(input: &str, maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()), addl_lib_search_paths: RefCell::new(libs.clone()), crate_types: vec!(config::CrateTypeDylib), + externs: externs.clone(), ..config::basic_options().clone() }; - let codemap = CodeMap::new(); let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None); let span_diagnostic_handler = @@ -92,6 +93,7 @@ pub fn run(input: &str, let mut collector = Collector::new(krate.name.to_string(), libs, + externs, false); collector.fold_crate(krate); @@ -102,8 +104,8 @@ pub fn run(input: &str, 0 } -fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool, - no_run: bool, as_test_harness: bool) { +fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, externs: core::Externs, + should_fail: bool, no_run: bool, as_test_harness: bool) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` let test = maketest(test, Some(cratename), true, as_test_harness); @@ -115,6 +117,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool, crate_types: vec!(config::CrateTypeExecutable), output_types: vec!(link::OutputTypeExe), no_trans: no_run, + externs: externs, cg: config::CodegenOptions { prefer_dynamic: true, .. config::basic_codegen_options() @@ -237,6 +240,7 @@ pub struct Collector { pub tests: Vec<testing::TestDescAndFn>, names: Vec<String>, libs: HashSet<Path>, + externs: core::Externs, cnt: uint, use_headers: bool, current_header: Option<String>, @@ -244,12 +248,13 @@ pub struct Collector { } impl Collector { - pub fn new(cratename: String, libs: HashSet<Path>, + pub fn new(cratename: String, libs: HashSet<Path>, externs: core::Externs, use_headers: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), libs: libs, + externs: externs, cnt: 0, use_headers: use_headers, current_header: None, @@ -267,6 +272,7 @@ impl Collector { }; self.cnt += 1; let libs = self.libs.clone(); + let externs = self.externs.clone(); let cratename = self.cratename.to_string(); debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { @@ -279,6 +285,7 @@ impl Collector { runtest(test.as_slice(), cratename.as_slice(), libs, + externs, should_fail, no_run, as_test_harness); |
