Skip to content

Commit 5c05b3c

Browse files
committed
Add target crates as inputs to reduce size of intermediates
Add tests for module-path remapping and scrape example options Find all crates with a given name
1 parent 829b1a9 commit 5c05b3c

File tree

9 files changed

+130
-31
lines changed

9 files changed

+130
-31
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,20 +1059,22 @@ impl Clean<Item> for ty::AssocItem {
10591059
ty::ImplContainer(_) => Some(self.defaultness),
10601060
ty::TraitContainer(_) => None,
10611061
};
1062-
let function = Function {
1063-
generics,
1064-
decl,
1065-
header: hir::FnHeader {
1066-
unsafety: sig.unsafety(),
1067-
abi: sig.abi(),
1068-
constness,
1069-
asyncness,
1062+
MethodItem(
1063+
Function {
1064+
generics,
1065+
decl,
1066+
header: hir::FnHeader {
1067+
unsafety: sig.unsafety(),
1068+
abi: sig.abi(),
1069+
constness,
1070+
asyncness,
1071+
},
1072+
def_id: self.def_id,
10701073
},
1071-
def_id: self.def_id,
1072-
};
1073-
MethodItem(function, defaultness)
1074+
defaultness,
1075+
)
10741076
} else {
1075-
let function = Function {
1077+
TyMethodItem(Function {
10761078
generics,
10771079
decl,
10781080
header: hir::FnHeader {
@@ -1082,8 +1084,7 @@ impl Clean<Item> for ty::AssocItem {
10821084
asyncness: hir::IsAsync::NotAsync,
10831085
},
10841086
def_id: self.def_id,
1085-
};
1086-
TyMethodItem(function)
1087+
})
10871088
}
10881089
}
10891090
ty::AssocKind::Type => {

src/librustdoc/config.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::html::render::StylePath;
2525
use crate::html::static_files;
2626
use crate::opts;
2727
use crate::passes::{self, Condition, DefaultPassOption};
28-
use crate::scrape_examples::AllCallLocations;
28+
use crate::scrape_examples::{AllCallLocations, ScrapeExamplesOptions};
2929
use crate::theme;
3030

3131
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -160,9 +160,9 @@ crate struct Options {
160160
/// Whether to skip capturing stdout and stderr of tests.
161161
crate nocapture: bool,
162162

163-
/// Path to output file to write JSON of call sites. If this option is Some(..) then
163+
/// Configuration for scraping examples from the current crate. If this option is Some(..) then
164164
/// the compiler will scrape examples and not generate documentation.
165-
crate scrape_examples: Option<PathBuf>,
165+
crate scrape_examples_options: Option<ScrapeExamplesOptions>,
166166
}
167167

168168
impl fmt::Debug for Options {
@@ -207,7 +207,7 @@ impl fmt::Debug for Options {
207207
.field("run_check", &self.run_check)
208208
.field("no_run", &self.no_run)
209209
.field("nocapture", &self.nocapture)
210-
.field("scrape_examples", &self.scrape_examples)
210+
.field("scrape_examples_options", &self.scrape_examples_options)
211211
.finish()
212212
}
213213
}
@@ -678,7 +678,7 @@ impl Options {
678678
return Err(1);
679679
}
680680

681-
let scrape_examples = matches.opt_str("scrape-examples").map(PathBuf::from);
681+
let scrape_examples_options = ScrapeExamplesOptions::new(&matches, &diag)?;
682682
let with_examples = matches.opt_strs("with-examples");
683683
let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?;
684684

@@ -753,7 +753,7 @@ impl Options {
753753
crate_name,
754754
output_format,
755755
json_unused_externs,
756-
scrape_examples,
756+
scrape_examples_options,
757757
})
758758
}
759759

src/librustdoc/lib.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,20 @@ fn opts() -> Vec<RustcOptGroup> {
621621
"Make the identifiers in the HTML source code pages navigable",
622622
)
623623
}),
624-
unstable("scrape-examples", |o| {
624+
unstable("scrape-examples-output-path", |o| {
625625
o.optopt(
626626
"",
627-
"scrape-examples",
627+
"scrape-examples-output-path",
628628
"",
629-
"collect function call information (for use with `--with-examples`)",
629+
"collect function call information and output at the given path",
630+
)
631+
}),
632+
unstable("scrape-examples-target-crate", |o| {
633+
o.optmulti(
634+
"",
635+
"scrape-examples-target-crate",
636+
"",
637+
"collect function call information for functions from the target crate",
630638
)
631639
}),
632640
unstable("with-examples", |o| {
@@ -750,7 +758,7 @@ fn main_options(options: config::Options) -> MainResult {
750758
// FIXME: fix this clone (especially render_options)
751759
let manual_passes = options.manual_passes.clone();
752760
let render_options = options.render_options.clone();
753-
let scrape_examples = options.scrape_examples.clone();
761+
let scrape_examples_options = options.scrape_examples_options.clone();
754762
let config = core::create_config(options);
755763

756764
interface::create_compiler_and_run(config, |compiler| {
@@ -787,8 +795,8 @@ fn main_options(options: config::Options) -> MainResult {
787795
});
788796
info!("finished with rustc");
789797

790-
if let Some(example_path) = scrape_examples {
791-
return scrape_examples::run(krate, render_opts, cache, tcx, example_path);
798+
if let Some(options) = scrape_examples_options {
799+
return scrape_examples::run(krate, render_opts, cache, tcx, options);
792800
}
793801

794802
cache.crate_version = crate_version;

src/librustdoc/scrape_examples.rs

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,43 @@ use rustc_serialize::{
2020
opaque::{Decoder, FileEncoder},
2121
Decodable, Encodable,
2222
};
23-
use rustc_span::{def_id::DefId, edition::Edition, BytePos, FileName, SourceFile};
23+
use rustc_session::getopts;
24+
use rustc_span::{
25+
def_id::{CrateNum, DefId},
26+
edition::Edition,
27+
BytePos, FileName, SourceFile,
28+
};
2429

2530
use std::fs;
2631
use std::path::PathBuf;
2732

33+
#[derive(Debug, Clone)]
34+
crate struct ScrapeExamplesOptions {
35+
output_path: PathBuf,
36+
target_crates: Vec<String>,
37+
}
38+
39+
impl ScrapeExamplesOptions {
40+
crate fn new(
41+
matches: &getopts::Matches,
42+
diag: &rustc_errors::Handler,
43+
) -> Result<Option<Self>, i32> {
44+
let output_path = matches.opt_str("scrape-examples-output-path");
45+
let target_crates = matches.opt_strs("scrape-examples-target-crate");
46+
match (output_path, !target_crates.is_empty()) {
47+
(Some(output_path), true) => Ok(Some(ScrapeExamplesOptions {
48+
output_path: PathBuf::from(output_path),
49+
target_crates,
50+
})),
51+
(Some(_), false) | (None, true) => {
52+
diag.err(&format!("must use --scrape-examples-output-path and --scrape-examples-target-crate together"));
53+
Err(1)
54+
}
55+
(None, false) => Ok(None),
56+
}
57+
}
58+
}
59+
2860
#[derive(Encodable, Decodable, Debug, Clone)]
2961
crate struct SyntaxRange {
3062
crate byte_span: (u32, u32),
@@ -83,6 +115,7 @@ struct FindCalls<'a, 'tcx> {
83115
tcx: TyCtxt<'tcx>,
84116
map: Map<'tcx>,
85117
cx: Context<'tcx>,
118+
target_crates: Vec<CrateNum>,
86119
calls: &'a mut AllCallLocations,
87120
}
88121

@@ -130,6 +163,11 @@ where
130163

131164
// Save call site if the function resolves to a concrete definition
132165
if let ty::FnDef(def_id, _) = ty.kind() {
166+
// Ignore functions not from the crate being documented
167+
if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
168+
return;
169+
}
170+
133171
let file = tcx.sess.source_map().lookup_char_pos(span.lo()).file;
134172
let file_path = match file.name.clone() {
135173
FileName::Real(real_filename) => real_filename.into_local_path(),
@@ -143,7 +181,7 @@ where
143181
let clean_span = crate::clean::types::Span::new(span);
144182
let url = cx.href_from_span(clean_span).unwrap();
145183
let display_name = file_path.display().to_string();
146-
let edition = tcx.sess.edition();
184+
let edition = span.edition();
147185
CallData { locations: Vec::new(), url, display_name, edition }
148186
};
149187

@@ -162,19 +200,34 @@ crate fn run(
162200
renderopts: config::RenderOptions,
163201
cache: formats::cache::Cache,
164202
tcx: TyCtxt<'_>,
165-
example_path: PathBuf,
203+
options: ScrapeExamplesOptions,
166204
) -> interface::Result<()> {
167205
let inner = move || -> Result<(), String> {
168206
// Generates source files for examples
169207
let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
170208

209+
// Collect CrateIds corresponding to provided target crates
210+
// If two different versions of the crate in the dependency tree, then examples will be collcted from both.
211+
let find_crates_with_name = |target_crate: String| {
212+
tcx.crates(())
213+
.iter()
214+
.filter(move |crate_num| tcx.crate_name(**crate_num).as_str() == target_crate)
215+
.copied()
216+
};
217+
let target_crates = options
218+
.target_crates
219+
.into_iter()
220+
.map(find_crates_with_name)
221+
.flatten()
222+
.collect::<Vec<_>>();
223+
171224
// Run call-finder on all items
172225
let mut calls = FxHashMap::default();
173-
let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx };
226+
let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
174227
tcx.hir().krate().visit_all_item_likes(&mut finder.as_deep_visitor());
175228

176229
// Save output to provided path
177-
let mut encoder = FileEncoder::new(example_path).map_err(|e| e.to_string())?;
230+
let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?;
178231
calls.encode(&mut encoder).map_err(|e| e.to_string())?;
179232
encoder.flush().map_err(|e| e.to_string())?;
180233

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
OUTPUT_DIR := "$(TMPDIR)/rustdoc"
4+
5+
all:
6+
# 1. compile the library crate and emit an rmeta
7+
$(RUSTC) src/lib.rs --crate-name foobar --crate-type lib --emit=metadata
8+
9+
# 2. scrape examples from the reverse-dependency into an ex.calls file
10+
$(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin \
11+
--extern foobar=$(TMPDIR)/libfoobar.rmeta \
12+
-Z unstable-options \
13+
--scrape-examples-output-path $(TMPDIR)/ex.calls \
14+
--scrape-examples-target-crate foobar
15+
16+
# 3. pass those examples to rustdoc when documenting the library crate
17+
$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
18+
-Z unstable-options \
19+
--with-examples $(TMPDIR)/ex.calls
20+
21+
# 4. check that the examples were scraped successfully
22+
$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
foobar::b::foo();
3+
foobar::c::foo();
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn foo() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @has foobar/b/fn.foo.html '//*[@class="scraped-example"]' 'ex.rs'
2+
// @has foobar/c/fn.foo.html '//*[@class="scraped-example"]' 'ex.rs'
3+
4+
#[path = "a.rs"]
5+
pub mod b;
6+
7+
#[path = "a.rs"]
8+
pub mod c;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// should-fail
2+
// compile-flags: --scrape-examples-target-crate foobar

0 commit comments

Comments
 (0)