@@ -11,11 +11,14 @@ pub use self::MaybeTyped::*;
11
11
12
12
use rustc_driver:: driver;
13
13
use rustc:: session:: { mod, config} ;
14
+ use rustc:: metadata:: decoder;
14
15
use rustc:: middle:: { privacy, ty} ;
15
16
use rustc:: lint;
16
17
use rustc_trans:: back:: link;
17
18
18
- use syntax:: { ast, ast_map, codemap, diagnostic} ;
19
+ use syntax:: { ast, ast_map, ast_util, codemap, diagnostic} ;
20
+ use syntax:: parse:: token;
21
+ use syntax:: ptr:: P ;
19
22
20
23
use std:: cell:: RefCell ;
21
24
use std:: collections:: { HashMap , HashSet } ;
@@ -163,3 +166,184 @@ pub fn run_core(libs: Vec<Path>, cfgs: Vec<String>, externs: Externs,
163
166
* analysis. inlined . borrow_mut ( ) = map;
164
167
( krate, analysis)
165
168
}
169
+
170
+ pub fn run_core_with_lib ( libpath : & Path , srcpath : & Path ) -> ( clean:: Crate , CrateAnalysis ) {
171
+ let codemap = codemap:: CodeMap :: new ( ) ;
172
+ let diagnostic_handler = diagnostic:: default_handler ( diagnostic:: Auto , None ) ;
173
+ let span_diagnostic_handler = diagnostic:: mk_span_handler ( diagnostic_handler, codemap) ;
174
+
175
+ let dummy_crate_name = "__crate" ;
176
+ let dummy_view_name = "__view" ;
177
+
178
+ let mut opts = config:: basic_options ( ) ;
179
+ opts. externs . insert ( dummy_crate_name. into_string ( ) ,
180
+ vec ! [ libpath. as_str( ) . unwrap( ) . into_string( ) ] ) ;
181
+
182
+ let sess = session:: build_session_ ( opts, None , span_diagnostic_handler) ;
183
+
184
+ // dummy AST to faciliate the crate loading
185
+ let dummy_crate_ident = ast:: Ident :: new ( token:: gensym ( dummy_crate_name) ) ;
186
+ let dummy_view_ident = ast:: Ident :: new ( token:: gensym ( dummy_view_name) ) ;
187
+ let krate = ast:: Crate {
188
+ module : ast:: Mod {
189
+ inner : codemap:: DUMMY_SP ,
190
+ view_items : vec ! [
191
+ ast:: ViewItem {
192
+ node: ast:: ViewItemExternCrate (
193
+ dummy_view_ident,
194
+ Some ( ( token:: get_ident( dummy_crate_ident) , ast:: CookedStr ) ) ,
195
+ ast:: DUMMY_NODE_ID ) ,
196
+ attrs: Vec :: new( ) ,
197
+ vis: ast:: Inherited ,
198
+ span: codemap:: DUMMY_SP ,
199
+ } ,
200
+ ast:: ViewItem {
201
+ node: ast:: ViewItemUse (
202
+ P ( codemap:: dummy_spanned( ast:: ViewPathSimple (
203
+ dummy_crate_ident,
204
+ ast:: Path {
205
+ span: codemap:: DUMMY_SP ,
206
+ global: false ,
207
+ segments: vec![
208
+ ast:: PathSegment {
209
+ identifier: dummy_view_ident,
210
+ parameters: ast:: PathParameters :: none( ) ,
211
+ } ,
212
+ ] ,
213
+ } ,
214
+ ast:: DUMMY_NODE_ID )
215
+ ) )
216
+ ) ,
217
+ attrs: Vec :: new( ) ,
218
+ vis: ast:: Public ,
219
+ span: codemap:: DUMMY_SP ,
220
+ } ,
221
+ ] ,
222
+ items : Vec :: new ( ) ,
223
+ } ,
224
+ attrs : Vec :: new ( ) ,
225
+ config : Vec :: new ( ) ,
226
+ span : codemap:: DUMMY_SP ,
227
+ exported_macros : Vec :: new ( ) ,
228
+ } ;
229
+
230
+ let mut forest = ast_map:: Forest :: new ( krate) ;
231
+ let ast_map = driver:: assign_node_ids_and_map ( & sess, & mut forest) ;
232
+
233
+ let type_arena = TypedArena :: new ( ) ;
234
+ let ty:: CrateAnalysis {
235
+ exported_items, public_items, ty_cx, ..
236
+ } = driver:: phase_3_run_analysis_passes ( sess, ast_map, & type_arena,
237
+ dummy_crate_name. into_string ( ) ) ;
238
+
239
+ let ctxt = DocContext {
240
+ krate : ty_cx. map . krate ( ) ,
241
+ maybe_typed : Typed ( ty_cx) ,
242
+ src : srcpath. clone ( ) ,
243
+ external_traits : RefCell :: new ( Some ( HashMap :: new ( ) ) ) ,
244
+ external_typarams : RefCell :: new ( Some ( HashMap :: new ( ) ) ) ,
245
+ external_paths : RefCell :: new ( Some ( HashMap :: new ( ) ) ) ,
246
+ inlined : RefCell :: new ( Some ( HashSet :: new ( ) ) ) ,
247
+ populated_crate_impls : RefCell :: new ( HashSet :: new ( ) ) ,
248
+ } ;
249
+
250
+ // there should be only one Def available, namely reexport
251
+ let mut view_node_id = None ;
252
+ for ( id, _) in ctxt. tcx ( ) . def_map . borrow ( ) . iter ( ) {
253
+ assert ! ( view_node_id. is_none( ) , "multiple Defs available" ) ;
254
+ view_node_id = Some ( * id) ;
255
+ }
256
+ let view_node_id = view_node_id. expect ( "no Def available" ) ;
257
+
258
+ // we now have all necessary environments, try to inline.
259
+ let inlined = clean:: inline:: try_inline ( & ctxt, view_node_id, None ) ;
260
+ let inlined = inlined. expect ( "cannot inline crate" ) ;
261
+ if inlined. len ( ) != 1 {
262
+ panic ! ( "cannot inline crate" ) ;
263
+ }
264
+ let inlined = inlined. into_iter ( ) . next ( ) . unwrap ( ) ;
265
+
266
+ // we still have to fill some gaps, so get the crate data in our hands
267
+ let crate_num = 1 ; // we don't have std injection so this should be the first
268
+ let crate_data = ctxt. sess ( ) . cstore . get_crate_data ( crate_num) ;
269
+ let crate_name = crate_data. name ( ) ;
270
+
271
+ // fix external_paths for the given crate_num
272
+ {
273
+ let mut external_paths = ctxt. external_paths . borrow_mut ( ) ;
274
+ for ( def_id, & ( ref mut fqn, _) ) in external_paths. as_mut ( ) . unwrap ( ) . iter_mut ( ) {
275
+ if def_id. krate == crate_num {
276
+ assert_eq ! ( fqn. head( ) . map( |s| s. as_slice( ) ) , Some ( dummy_crate_name) ) ;
277
+ if fqn. len ( ) == 1 {
278
+ fqn[ 0 ] = "" . into_string ( ) ;
279
+ } else {
280
+ fqn. remove ( 0 ) ;
281
+ }
282
+ }
283
+ }
284
+ }
285
+
286
+ let postclean = RefCell :: new ( Some ( ( crate_name, srcpath. clone ( ) , inlined) ) ) ;
287
+ let mut krate = postclean. clean ( & ctxt) ;
288
+
289
+ // why do we have both crate attributes and item attributes?!
290
+ let crate_attrs = decoder:: get_crate_attributes ( crate_data. data ( ) ) ;
291
+ {
292
+ let mut attrs = & mut krate. module . as_mut ( ) . unwrap ( ) . attrs ;
293
+ attrs. extend ( crate_attrs. clean ( & ctxt) . into_iter ( ) ) ;
294
+ }
295
+
296
+ // the reconstructed crate doesn't have exported macros (yet)
297
+ let macros = decoder:: get_exported_macros ( crate_data. data ( ) ) ;
298
+ {
299
+ let mut module = match krate. module {
300
+ Some ( clean:: Item { inner : clean:: ModuleItem ( ref mut module) , .. } ) => module,
301
+ _ => panic ! ( "unexpectedly cleaned crate" )
302
+ } ;
303
+ for macro in macros. into_iter ( ) {
304
+ // XXX okay, this is bad. the metadata doesn't have a direct macro name.
305
+ // for now we try to recognize `macro_rules!\s*([^/({\[]+)`.
306
+ // hope someone doesn't come up with `macro_rules! /*screw doc*/ foo()`...
307
+ let macname = {
308
+ let macro = macro. trim_left ( ) ;
309
+ if macro. starts_with ( "macro_rules!" ) {
310
+ let macro = macro. slice_from ( 12 ) . trim_left ( ) ;
311
+ let sep = macro. find ( [ '/' , '(' , '{' , '[' ] . as_slice ( ) ) ;
312
+ if let Some ( sep) = sep {
313
+ Some ( format ! ( "{}!" , macro. slice_to( sep) . trim_right( ) ) )
314
+ } else {
315
+ None
316
+ }
317
+ } else {
318
+ None
319
+ }
320
+ } ;
321
+ module. items . push ( clean:: Item {
322
+ name : macname,
323
+ attrs : Vec :: new ( ) ,
324
+ source : clean:: Span :: empty ( ) ,
325
+ visibility : ast:: Public . clean ( & ctxt) ,
326
+ stability : None ,
327
+ def_id : ast_util:: local_def ( ast:: DUMMY_NODE_ID ) ,
328
+ inner : clean:: MacroItem ( clean:: Macro {
329
+ source : macro,
330
+ } ) ,
331
+ } ) ;
332
+ }
333
+ }
334
+
335
+ // we need the analysis for later uses
336
+ let DocContext {
337
+ external_paths, external_traits, external_typarams, inlined, ..
338
+ } = ctxt;
339
+ let analysis = CrateAnalysis {
340
+ exported_items : exported_items,
341
+ public_items : public_items,
342
+ external_paths : external_paths,
343
+ external_traits : external_traits,
344
+ external_typarams : external_typarams,
345
+ inlined : inlined,
346
+ } ;
347
+
348
+ ( krate, analysis)
349
+ }
0 commit comments