@@ -344,15 +344,16 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
344
344
345
345
fn expand_item_modifiers ( mut it : Gc < ast:: Item > , fld : & mut MacroExpander )
346
346
-> Gc < ast:: Item > {
347
- let ( modifiers, attrs) = it. attrs . partitioned ( |attr| {
347
+ // partition the attributes into ItemModifiers and others
348
+ let ( modifiers, other_attrs) = it. attrs . partitioned ( |attr| {
348
349
match fld. extsbox . find ( & intern ( attr. name ( ) . get ( ) ) ) {
349
350
Some ( & ItemModifier ( _) ) => true ,
350
351
_ => false
351
352
}
352
353
} ) ;
353
-
354
+ // update the attrs, leave everything else alone. Is this mutation really a good idea?
354
355
it = box ( GC ) ast:: Item {
355
- attrs : attrs ,
356
+ attrs : other_attrs ,
356
357
..( * it) . clone ( )
357
358
} ;
358
359
@@ -1047,13 +1048,14 @@ fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
1047
1048
#[ cfg( test) ]
1048
1049
mod test {
1049
1050
use super :: { pattern_bindings, expand_crate, contains_macro_escape} ;
1050
- use super :: { PatIdentFinder } ;
1051
+ use super :: { PatIdentFinder , IdentRenamer , PatIdentRenamer } ;
1051
1052
use ast;
1052
1053
use ast:: { Attribute_ , AttrOuter , MetaWord } ;
1053
1054
use attr;
1054
1055
use codemap;
1055
1056
use codemap:: Spanned ;
1056
1057
use ext:: mtwt;
1058
+ use fold:: Folder ;
1057
1059
use parse;
1058
1060
use parse:: token;
1059
1061
use util:: parser_testing:: { string_to_parser} ;
@@ -1091,7 +1093,24 @@ mod test {
1091
1093
path_finder. path_accumulator
1092
1094
}
1093
1095
1096
+ /// A Visitor that extracts the identifiers from a thingy.
1097
+ // as a side note, I'm starting to want to abstract over these....
1098
+ struct IdentFinder {
1099
+ ident_accumulator : Vec < ast:: Ident >
1100
+ }
1094
1101
1102
+ impl Visitor < ( ) > for IdentFinder {
1103
+ fn visit_ident ( & mut self , _: codemap:: Span , id : ast:: Ident , _: ( ) ) {
1104
+ self . ident_accumulator . push ( id) ;
1105
+ }
1106
+ }
1107
+
1108
+ /// Find the idents in a crate
1109
+ fn crate_idents ( the_crate : & ast:: Crate ) -> Vec < ast:: Ident > {
1110
+ let mut ident_finder = IdentFinder { ident_accumulator : Vec :: new ( ) } ;
1111
+ visit:: walk_crate ( & mut ident_finder, the_crate, ( ) ) ;
1112
+ ident_finder. ident_accumulator
1113
+ }
1095
1114
1096
1115
// these following tests are quite fragile, in that they don't test what
1097
1116
// *kind* of failure occurs.
@@ -1316,7 +1335,7 @@ mod test {
1316
1335
// but *shouldn't* bind because it was inserted by a different macro....
1317
1336
// can't write this test case until we have macro-generating macros.
1318
1337
1319
- // FIXME #9383 : lambda var hygiene
1338
+ // lambda var hygiene
1320
1339
// expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};}
1321
1340
#[ test]
1322
1341
fn issue_9383 ( ) {
@@ -1375,9 +1394,9 @@ mod test {
1375
1394
assert_eq ! ( varref_marks, binding_marks. clone( ) ) ;
1376
1395
}
1377
1396
} else {
1397
+ let varref_name = mtwt:: resolve ( varref. segments . get ( 0 ) . identifier ) ;
1378
1398
let fail = ( varref. segments . len ( ) == 1 )
1379
- && ( mtwt:: resolve ( varref. segments . get ( 0 ) . identifier )
1380
- == binding_name) ;
1399
+ && ( varref_name == binding_name) ;
1381
1400
// temp debugging:
1382
1401
if fail {
1383
1402
let varref_idents : Vec < ast:: Ident >
@@ -1388,15 +1407,18 @@ mod test {
1388
1407
println ! ( "text of test case: \" {}\" " , teststr) ;
1389
1408
println ! ( "" ) ;
1390
1409
println ! ( "uh oh, matches but shouldn't:" ) ;
1391
- println ! ( "varref: {}" , varref_idents) ;
1410
+ println ! ( "varref #{}: {}, resolves to {}" , idx, varref_idents,
1411
+ varref_name) ;
1392
1412
// good lord, you can't make a path with 0 segments, can you?
1393
1413
let string = token:: get_ident ( varref. segments
1394
1414
. get ( 0 )
1395
1415
. identifier ) ;
1396
1416
println ! ( "varref's first segment's uint: {}, and string: \" {}\" " ,
1397
1417
varref. segments. get( 0 ) . identifier. name,
1398
1418
string. get( ) ) ;
1399
- println ! ( "binding: {}" , * bindings. get( binding_idx) ) ;
1419
+ println ! ( "binding #{}: {}, resolves to {}" ,
1420
+ binding_idx, * bindings. get( binding_idx) ,
1421
+ binding_name) ;
1400
1422
mtwt:: with_sctable ( |x| mtwt:: display_sctable ( x) ) ;
1401
1423
}
1402
1424
assert ! ( !fail) ;
@@ -1459,13 +1481,43 @@ foo_module!()
1459
1481
// 'None' is listed as an identifier pattern because we don't yet know that
1460
1482
// it's the name of a 0-ary variant, and that 'i' appears twice in succession.
1461
1483
#[ test]
1462
- fn crate_idents ( ) {
1484
+ fn crate_bindings_test ( ) {
1463
1485
let the_crate = string_to_crate ( "fn main (a : int) -> int {|b| {
1464
1486
match 34 {None => 3, Some(i) | i => j, Foo{k:z,l:y} => \" banana\" }} }" . to_string ( ) ) ;
1465
1487
let idents = crate_bindings ( & the_crate) ;
1466
1488
assert_eq ! ( idents, strs_to_idents( vec!( "a" , "b" , "None" , "i" , "i" , "z" , "y" ) ) ) ;
1467
1489
}
1468
1490
1469
- //
1491
+ // test the IdentRenamer directly
1492
+ #[ test]
1493
+ fn ident_renamer_test ( ) {
1494
+ let the_crate = string_to_crate ( "fn f(x : int){let x = x; x}" . to_string ( ) ) ;
1495
+ let f_ident = token:: str_to_ident ( "f" ) ;
1496
+ let x_ident = token:: str_to_ident ( "x" ) ;
1497
+ let int_ident = token:: str_to_ident ( "int" ) ;
1498
+ let renames = vec ! ( ( x_ident, 16 ) ) ;
1499
+ let mut renamer = IdentRenamer { renames : & renames} ;
1500
+ let renamed_crate = renamer. fold_crate ( the_crate) ;
1501
+ let idents = crate_idents ( & renamed_crate) ;
1502
+ let resolved : Vec < ast:: Name > = idents. iter ( ) . map ( |id| mtwt:: resolve ( * id) ) . collect ( ) ;
1503
+ assert_eq ! ( resolved, vec!( f_ident. name, 16 , int_ident. name, 16 , 16 , 16 ) ) ;
1504
+ }
1505
+
1506
+ // test the PatIdentRenamer; only PatIdents get renamed
1507
+ #[ test]
1508
+ fn pat_ident_renamer_test ( ) {
1509
+ let the_crate = string_to_crate ( "fn f(x : int){let x = x; x}" . to_string ( ) ) ;
1510
+ let f_ident = token:: str_to_ident ( "f" ) ;
1511
+ let x_ident = token:: str_to_ident ( "x" ) ;
1512
+ let int_ident = token:: str_to_ident ( "int" ) ;
1513
+ let renames = vec ! ( ( x_ident, 16 ) ) ;
1514
+ let mut renamer = PatIdentRenamer { renames : & renames} ;
1515
+ let renamed_crate = renamer. fold_crate ( the_crate) ;
1516
+ let idents = crate_idents ( & renamed_crate) ;
1517
+ let resolved : Vec < ast:: Name > = idents. iter ( ) . map ( |id| mtwt:: resolve ( * id) ) . collect ( ) ;
1518
+ let x_name = x_ident. name ;
1519
+ assert_eq ! ( resolved, vec!( f_ident. name, 16 , int_ident. name, 16 , x_name, x_name) ) ;
1520
+ }
1521
+
1470
1522
1471
1523
}
0 commit comments