@@ -18,13 +18,15 @@ use front::config;
1818
1919use std:: gc:: { Gc , GC } ;
2020use std:: slice;
21+ use std:: mem;
2122use std:: vec;
2223use syntax:: ast_util:: * ;
2324use syntax:: attr:: AttrMetaMethods ;
2425use syntax:: attr;
2526use syntax:: codemap:: { DUMMY_SP , Span , ExpnInfo , NameAndSpan , MacroAttribute } ;
2627use syntax:: codemap;
2728use syntax:: ext:: base:: ExtCtxt ;
29+ use syntax:: ext:: build:: AstBuilder ;
2830use syntax:: ext:: expand:: ExpansionConfig ;
2931use syntax:: fold:: Folder ;
3032use syntax:: fold;
@@ -46,8 +48,10 @@ struct Test {
4648struct TestCtxt < ' a > {
4749 sess : & ' a Session ,
4850 path : Vec < ast:: Ident > ,
51+ reexports : Vec < Vec < ast:: Ident > > ,
4952 ext_cx : ExtCtxt < ' a > ,
5053 testfns : Vec < Test > ,
54+ reexport_mod_ident : ast:: Ident ,
5155 is_test_crate : bool ,
5256 config : ast:: CrateConfig ,
5357}
@@ -107,25 +111,35 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
107111 should_fail : should_fail ( i)
108112 } ;
109113 self . cx . testfns . push ( test) ;
114+ self . cx . reexports . push ( self . cx . path . clone ( ) ) ;
110115 // debug!("have {} test/bench functions",
111116 // cx.testfns.len());
112117 }
113118 }
114119 }
115120
116- let res = fold:: noop_fold_item ( & * i, self ) ;
121+ // We don't want to recurse into anything other than mods, since
122+ // mods or tests inside of functions will break things
123+ let res = match i. node {
124+ ast:: ItemMod ( ..) => fold:: noop_fold_item ( & * i, self ) ,
125+ _ => SmallVector :: one ( i) ,
126+ } ;
117127 self . cx . path . pop ( ) ;
118128 res
119129 }
120130
121131 fn fold_mod ( & mut self , m : & ast:: Mod ) -> ast:: Mod {
132+ let reexports = mem:: replace ( & mut self . cx . reexports , Vec :: new ( ) ) ;
133+ let mut mod_folded = fold:: noop_fold_mod ( m, self ) ;
134+ let reexports = mem:: replace ( & mut self . cx . reexports , reexports) ;
135+
122136 // Remove any #[main] from the AST so it doesn't clash with
123137 // the one we're going to add. Only if compiling an executable.
124138
125139 fn nomain ( item : Gc < ast:: Item > ) -> Gc < ast:: Item > {
126140 box ( GC ) ast:: Item {
127141 attrs : item. attrs . iter ( ) . filter_map ( |attr| {
128- if !attr. name ( ) . equiv ( & ( "main" ) ) {
142+ if !attr. check_name ( "main" ) {
129143 Some ( * attr)
130144 } else {
131145 None
@@ -135,18 +149,37 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
135149 }
136150 }
137151
138- let mod_nomain = ast:: Mod {
139- inner : m. inner ,
140- view_items : m. view_items . clone ( ) ,
141- items : m. items . iter ( ) . map ( |i| nomain ( * i) ) . collect ( ) ,
142- } ;
152+ for i in mod_folded. items . mut_iter ( ) {
153+ * i = nomain ( * i) ;
154+ }
155+ mod_folded. items . push ( mk_reexport_mod ( & mut self . cx , reexports) ) ;
156+ self . cx . reexports . push ( self . cx . path . clone ( ) ) ;
157+
158+ mod_folded
159+ }
160+ }
143161
144- fold:: noop_fold_mod ( & mod_nomain, self )
162+ fn mk_reexport_mod ( cx : & mut TestCtxt , reexports : Vec < Vec < ast:: Ident > > )
163+ -> Gc < ast:: Item > {
164+ let view_items = reexports. move_iter ( ) . map ( |r| {
165+ cx. ext_cx . view_use_simple ( DUMMY_SP , ast:: Public , cx. ext_cx . path ( DUMMY_SP , r) )
166+ } ) . collect ( ) ;
167+ let reexport_mod = ast:: Mod {
168+ inner : DUMMY_SP ,
169+ view_items : view_items,
170+ items : Vec :: new ( ) ,
171+ } ;
172+ box ( GC ) ast:: Item {
173+ ident : cx. reexport_mod_ident . clone ( ) ,
174+ attrs : Vec :: new ( ) ,
175+ id : ast:: DUMMY_NODE_ID ,
176+ node : ast:: ItemMod ( reexport_mod) ,
177+ vis : ast:: Public ,
178+ span : DUMMY_SP ,
145179 }
146180}
147181
148- fn generate_test_harness ( sess : & Session , krate : ast:: Crate )
149- -> ast:: Crate {
182+ fn generate_test_harness ( sess : & Session , krate : ast:: Crate ) -> ast:: Crate {
150183 let mut cx: TestCtxt = TestCtxt {
151184 sess : sess,
152185 ext_cx : ExtCtxt :: new ( & sess. parse_sess , sess. opts . cfg . clone ( ) ,
@@ -155,7 +188,9 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
155188 crate_name : "test" . to_string ( ) ,
156189 } ) ,
157190 path : Vec :: new ( ) ,
191+ reexports : Vec :: new ( ) ,
158192 testfns : Vec :: new ( ) ,
193+ reexport_mod_ident : token:: str_to_ident ( "__test_reexports" ) ,
159194 is_test_crate : is_test_crate ( & krate) ,
160195 config : krate. config . clone ( ) ,
161196 } ;
@@ -170,7 +205,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
170205 } ) ;
171206
172207 let mut fold = TestHarnessGenerator {
173- cx : cx
208+ cx : cx,
174209 } ;
175210 let res = fold. fold_crate ( krate) ;
176211 fold. cx . ext_cx . bt_pop ( ) ;
@@ -274,7 +309,6 @@ fn add_test_module(cx: &TestCtxt, m: &ast::Mod) -> ast::Mod {
274309We're going to be building a module that looks more or less like:
275310
276311mod __test {
277- #![!resolve_unexported]
278312 extern crate test (name = "test", vers = "...");
279313 fn main() {
280314 test::test_main_static(::os::args().as_slice(), tests)
@@ -331,15 +365,9 @@ fn mk_test_module(cx: &TestCtxt) -> Gc<ast::Item> {
331365 } ;
332366 let item_ = ast:: ItemMod ( testmod) ;
333367
334- // This attribute tells resolve to let us call unexported functions
335- let resolve_unexported_str = InternedString :: new ( "!resolve_unexported" ) ;
336- let resolve_unexported_attr =
337- attr:: mk_attr_inner ( attr:: mk_attr_id ( ) ,
338- attr:: mk_word_item ( resolve_unexported_str) ) ;
339-
340368 let item = ast:: Item {
341369 ident : token:: str_to_ident ( "__test" ) ,
342- attrs : vec ! ( resolve_unexported_attr ) ,
370+ attrs : Vec :: new ( ) ,
343371 id : ast:: DUMMY_NODE_ID ,
344372 node : item_,
345373 vis : ast:: Public ,
@@ -367,18 +395,6 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
367395 }
368396}
369397
370- fn path_node_global ( ids : Vec < ast:: Ident > ) -> ast:: Path {
371- ast:: Path {
372- span : DUMMY_SP ,
373- global : true ,
374- segments : ids. move_iter ( ) . map ( |identifier| ast:: PathSegment {
375- identifier : identifier,
376- lifetimes : Vec :: new ( ) ,
377- types : OwnedSlice :: empty ( ) ,
378- } ) . collect ( )
379- }
380- }
381-
382398fn mk_tests ( cx : & TestCtxt ) -> Gc < ast:: Item > {
383399 // The vector of test_descs for this crate
384400 let test_descs = mk_test_descs ( cx) ;
@@ -430,7 +446,12 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> Gc<ast::Expr> {
430446 span : span
431447 } ;
432448
433- let fn_path = path_node_global ( path) ;
449+ let mut visible_path = Vec :: new ( ) ;
450+ for ident in path. move_iter ( ) {
451+ visible_path. push ( cx. reexport_mod_ident . clone ( ) ) ;
452+ visible_path. push ( ident) ;
453+ }
454+ let fn_path = cx. ext_cx . path_global ( DUMMY_SP , visible_path) ;
434455
435456 let fn_expr = box ( GC ) ast:: Expr {
436457 id : ast:: DUMMY_NODE_ID ,
0 commit comments