@@ -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
2530use std:: fs;
2631use 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 ) ]
2961crate 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
0 commit comments