@@ -18,13 +18,15 @@ use front::config;
18
18
19
19
use std:: gc:: { Gc , GC } ;
20
20
use std:: slice;
21
+ use std:: mem;
21
22
use std:: vec;
22
23
use syntax:: ast_util:: * ;
23
24
use syntax:: attr:: AttrMetaMethods ;
24
25
use syntax:: attr;
25
26
use syntax:: codemap:: { DUMMY_SP , Span , ExpnInfo , NameAndSpan , MacroAttribute } ;
26
27
use syntax:: codemap;
27
28
use syntax:: ext:: base:: ExtCtxt ;
29
+ use syntax:: ext:: build:: AstBuilder ;
28
30
use syntax:: ext:: expand:: ExpansionConfig ;
29
31
use syntax:: fold:: Folder ;
30
32
use syntax:: fold;
@@ -46,8 +48,10 @@ struct Test {
46
48
struct TestCtxt < ' a > {
47
49
sess : & ' a Session ,
48
50
path : Vec < ast:: Ident > ,
51
+ reexports : Vec < Vec < ast:: Ident > > ,
49
52
ext_cx : ExtCtxt < ' a > ,
50
53
testfns : Vec < Test > ,
54
+ reexport_mod_ident : ast:: Ident ,
51
55
is_test_crate : bool ,
52
56
config : ast:: CrateConfig ,
53
57
}
@@ -107,25 +111,35 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
107
111
should_fail : should_fail ( i)
108
112
} ;
109
113
self . cx . testfns . push ( test) ;
114
+ self . cx . reexports . push ( self . cx . path . clone ( ) ) ;
110
115
// debug!("have {} test/bench functions",
111
116
// cx.testfns.len());
112
117
}
113
118
}
114
119
}
115
120
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
+ } ;
117
127
self . cx . path . pop ( ) ;
118
128
res
119
129
}
120
130
121
131
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
+
122
136
// Remove any #[main] from the AST so it doesn't clash with
123
137
// the one we're going to add. Only if compiling an executable.
124
138
125
139
fn nomain ( item : Gc < ast:: Item > ) -> Gc < ast:: Item > {
126
140
box ( GC ) ast:: Item {
127
141
attrs : item. attrs . iter ( ) . filter_map ( |attr| {
128
- if !attr. name ( ) . equiv ( & ( "main" ) ) {
142
+ if !attr. check_name ( "main" ) {
129
143
Some ( * attr)
130
144
} else {
131
145
None
@@ -135,18 +149,37 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
135
149
}
136
150
}
137
151
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
+ }
143
161
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 ,
145
179
}
146
180
}
147
181
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 {
150
183
let mut cx: TestCtxt = TestCtxt {
151
184
sess : sess,
152
185
ext_cx : ExtCtxt :: new ( & sess. parse_sess , sess. opts . cfg . clone ( ) ,
@@ -155,7 +188,9 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
155
188
crate_name : "test" . to_string ( ) ,
156
189
} ) ,
157
190
path : Vec :: new ( ) ,
191
+ reexports : Vec :: new ( ) ,
158
192
testfns : Vec :: new ( ) ,
193
+ reexport_mod_ident : token:: str_to_ident ( "__test_reexports" ) ,
159
194
is_test_crate : is_test_crate ( & krate) ,
160
195
config : krate. config . clone ( ) ,
161
196
} ;
@@ -170,7 +205,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
170
205
} ) ;
171
206
172
207
let mut fold = TestHarnessGenerator {
173
- cx : cx
208
+ cx : cx,
174
209
} ;
175
210
let res = fold. fold_crate ( krate) ;
176
211
fold. cx . ext_cx . bt_pop ( ) ;
@@ -274,7 +309,6 @@ fn add_test_module(cx: &TestCtxt, m: &ast::Mod) -> ast::Mod {
274
309
We're going to be building a module that looks more or less like:
275
310
276
311
mod __test {
277
- #![!resolve_unexported]
278
312
extern crate test (name = "test", vers = "...");
279
313
fn main() {
280
314
test::test_main_static(::os::args().as_slice(), tests)
@@ -331,15 +365,9 @@ fn mk_test_module(cx: &TestCtxt) -> Gc<ast::Item> {
331
365
} ;
332
366
let item_ = ast:: ItemMod ( testmod) ;
333
367
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
-
340
368
let item = ast:: Item {
341
369
ident : token:: str_to_ident ( "__test" ) ,
342
- attrs : vec ! ( resolve_unexported_attr ) ,
370
+ attrs : Vec :: new ( ) ,
343
371
id : ast:: DUMMY_NODE_ID ,
344
372
node : item_,
345
373
vis : ast:: Public ,
@@ -367,18 +395,6 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
367
395
}
368
396
}
369
397
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
-
382
398
fn mk_tests ( cx : & TestCtxt ) -> Gc < ast:: Item > {
383
399
// The vector of test_descs for this crate
384
400
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> {
430
446
span : span
431
447
} ;
432
448
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) ;
434
455
435
456
let fn_expr = box ( GC ) ast:: Expr {
436
457
id : ast:: DUMMY_NODE_ID ,
0 commit comments