2
2
3
3
use clang;
4
4
use parse:: { ClangItemParser , ClangSubItemParser , ParseError , ParseResult } ;
5
- use regex:: Regex ;
6
5
use std:: cell:: { Cell , RefCell } ;
6
+ use std:: fmt:: Write ;
7
7
use super :: annotations:: Annotations ;
8
8
use super :: context:: { BindgenContext , ItemId } ;
9
9
use super :: function:: Function ;
@@ -490,7 +490,8 @@ impl Item {
490
490
}
491
491
}
492
492
493
- fn is_module ( & self ) -> bool {
493
+ /// Is this item a module?
494
+ pub fn is_module ( & self ) -> bool {
494
495
match self . kind {
495
496
ItemKind :: Module ( ..) => true ,
496
497
_ => false ,
@@ -525,6 +526,108 @@ impl Item {
525
526
self . as_type ( ) . map_or ( false , |ty| ty. is_type_ref ( ) )
526
527
}
527
528
529
+ /// Get the target item id for name generation.
530
+ fn name_target ( & self , ctx : & BindgenContext , for_name_checking : bool ) -> ItemId {
531
+ let mut item = self ;
532
+ loop {
533
+ match * item. kind ( ) {
534
+ ItemKind :: Type ( ref ty) => {
535
+ match * ty. kind ( ) {
536
+ // If we're a template specialization, our name is our
537
+ // parent's name.
538
+ TypeKind :: Comp ( ref ci) if ci. is_template_specialization ( ) => {
539
+ item = ctx. resolve_item ( ci. specialized_template ( ) . unwrap ( ) ) ;
540
+ } ,
541
+ // Same as above.
542
+ TypeKind :: ResolvedTypeRef ( inner) |
543
+ TypeKind :: TemplateRef ( inner, _) => {
544
+ item = ctx. resolve_item ( inner) ;
545
+ }
546
+ // Template aliases use their inner alias type's name if we
547
+ // are checking names for whitelisting/replacement/etc.
548
+ TypeKind :: TemplateAlias ( inner, _) if for_name_checking => {
549
+ item = ctx. resolve_item ( inner) ;
550
+ assert_eq ! ( item. id( ) , item. name_target( ctx, for_name_checking) ) ;
551
+ return item. id ( ) ;
552
+ }
553
+ _ => return item. id ( ) ,
554
+ }
555
+ } ,
556
+ _ => return item. id ( ) ,
557
+ }
558
+ }
559
+ }
560
+
561
+ /// Get this function item's name, or `None` if this item is not a function.
562
+ fn func_name ( & self ) -> Option < & str > {
563
+ match * self . kind ( ) {
564
+ ItemKind :: Function ( ref func) => Some ( func. name ( ) ) ,
565
+ _ => None ,
566
+ }
567
+ }
568
+
569
+ /// Get the overload index for this method. If this is not a method, return
570
+ /// `None`.
571
+ fn method_overload_index ( & self , ctx : & BindgenContext ) -> Option < usize > {
572
+ self . func_name ( ) . and_then ( |func_name| {
573
+ let parent = ctx. resolve_item ( self . parent_id ( ) ) ;
574
+ if let ItemKind :: Type ( ref ty) = * parent. kind ( ) {
575
+ if let TypeKind :: Comp ( ref ci) = * ty. kind ( ) {
576
+ return ci. methods ( )
577
+ . iter ( )
578
+ . filter ( |method| {
579
+ let item = ctx. resolve_item ( method. signature ( ) ) ;
580
+ let func = item. expect_function ( ) ;
581
+ func. name ( ) == func_name
582
+ } )
583
+ . enumerate ( )
584
+ . find ( |& ( _, ref method) | method. signature ( ) == self . id ( ) )
585
+ . map ( |( idx, _) | idx) ;
586
+ }
587
+ }
588
+
589
+ None
590
+ } )
591
+ }
592
+
593
+ /// Get this item's base name (aka non-namespaced name).
594
+ ///
595
+ /// The `for_name_checking` boolean parameter informs us whether we are
596
+ /// asking for the name in order to do a whitelisting/replacement/etc check
597
+ /// or if we are instead using it for code generation.
598
+ fn base_name ( & self , ctx : & BindgenContext , for_name_checking : bool ) -> String {
599
+ match * self . kind ( ) {
600
+ ItemKind :: Var ( ref var) => var. name ( ) . to_owned ( ) ,
601
+ ItemKind :: Module ( ref module) => {
602
+ module. name ( )
603
+ . map ( ToOwned :: to_owned)
604
+ . unwrap_or_else ( || format ! ( "_bindgen_mod_{}" , self . exposed_id( ctx) ) )
605
+ } ,
606
+ ItemKind :: Type ( ref ty) => {
607
+ let name = match * ty. kind ( ) {
608
+ TypeKind :: ResolvedTypeRef ( ..) =>
609
+ panic ! ( "should have resolved this in name_target()" ) ,
610
+ TypeKind :: TemplateAlias ( ..) if !for_name_checking => Some ( "" ) ,
611
+ TypeKind :: TemplateAlias ( ..) => None ,
612
+ _ => ty. name ( ) ,
613
+ } ;
614
+ name. map ( ToOwned :: to_owned)
615
+ . unwrap_or_else ( || format ! ( "_bindgen_ty_{}" , self . exposed_id( ctx) ) )
616
+ }
617
+ ItemKind :: Function ( ref fun) => {
618
+ let mut name = fun. name ( ) . to_owned ( ) ;
619
+
620
+ if let Some ( idx) = self . method_overload_index ( ctx) {
621
+ if idx > 0 {
622
+ write ! ( & mut name, "{}" , idx) . unwrap ( ) ;
623
+ }
624
+ }
625
+
626
+ name
627
+ } ,
628
+ }
629
+ }
630
+
528
631
/// Get the canonical name without taking into account the replaces
529
632
/// annotation.
530
633
///
@@ -538,102 +641,38 @@ impl Item {
538
641
/// type and the parent chain, since it should be consistent.
539
642
pub fn real_canonical_name ( & self ,
540
643
ctx : & BindgenContext ,
541
- count_namespaces : bool ,
644
+ within_namespace : bool ,
542
645
for_name_checking : bool )
543
646
-> String {
544
- let base_name = match * self . kind ( ) {
545
- ItemKind :: Type ( ref ty) => {
546
- match * ty. kind ( ) {
547
- // If we're a template specialization, our name is our
548
- // parent's.
549
- TypeKind :: Comp ( ref ci)
550
- if ci. is_template_specialization ( ) => {
551
- return ci. specialized_template ( ) . unwrap ( )
552
- . canonical_name ( ctx) ;
553
- } ,
554
- // Same as above
555
- TypeKind :: ResolvedTypeRef ( inner) |
556
- TypeKind :: TemplateRef ( inner, _) => {
557
- return inner. canonical_name ( ctx) ;
558
- }
559
- // If we're a named type, we don't need to mangle it, and we
560
- // should be able to assert we're not top level.
561
- TypeKind :: Named ( ref name, _) => {
562
- return name. to_owned ( ) ;
563
- }
564
- // We call codegen on the inner type, but we do not want
565
- // this alias's name to appear in the canonical name just
566
- // because it is in the inner type's parent chain, so we use
567
- // an empty base name.
568
- //
569
- // Note that this would be incorrect if this type could be
570
- // referenced from, let's say, a member variable, but in
571
- // that case the referenced type is the inner alias, so
572
- // we're good there. If we wouldn't, a more complex solution
573
- // would be needed.
574
- TypeKind :: TemplateAlias ( inner, _) => {
575
- if for_name_checking {
576
- return ctx. resolve_item ( inner)
577
- . real_canonical_name ( ctx,
578
- count_namespaces,
579
- false ) ;
580
- }
581
- Some ( "" )
582
- }
583
- // Else use the proper name, or fallback to a name with an
584
- // id.
585
- _ => {
586
- ty. name ( )
587
- }
588
- } . map ( ToOwned :: to_owned)
589
- }
590
- ItemKind :: Function ( ref fun) => {
591
- let mut base = fun. name ( ) . to_owned ( ) ;
592
-
593
- // We might need to deduplicate if we're a method.
594
- let parent = ctx. resolve_item ( self . parent_id ( ) ) ;
595
- if let ItemKind :: Type ( ref ty) = * parent. kind ( ) {
596
- if let TypeKind :: Comp ( ref ci) = * ty. kind ( ) {
597
- let mut count = 0 ;
598
- let mut found = false ;
599
- for method in ci. methods ( ) {
600
- if method. signature ( ) == self . id ( ) {
601
- found = true ;
602
- break ;
603
- }
604
- let fun = ctx. resolve_item ( method. signature ( ) )
605
- . expect_function ( ) ;
606
- if fun. name ( ) == base {
607
- count += 1 ;
608
- }
609
- }
610
-
611
- assert ! ( found, "Method not found?" ) ;
612
- if count != 0 {
613
- base. push_str ( & count. to_string ( ) ) ;
614
- }
615
- }
616
- }
617
- Some ( base)
618
- }
619
- ItemKind :: Var ( ref var) => Some ( var. name ( ) . to_owned ( ) ) ,
620
- ItemKind :: Module ( ref module) => {
621
- module. name ( ) . map ( ToOwned :: to_owned)
622
- }
623
- } ;
647
+ let target = ctx. resolve_item ( self . name_target ( ctx, for_name_checking) ) ;
648
+ let base_name = target. base_name ( ctx, for_name_checking) ;
624
649
625
- let parent = ctx. resolve_item ( self . parent_id ( ) ) ;
626
- let parent_is_namespace = parent. is_module ( ) ;
650
+ // Named template type arguments are never namespaced, and never
651
+ // mangled.
652
+ if target. as_type ( ) . map_or ( false , |ty| ty. is_named ( ) ) {
653
+ return base_name;
654
+ }
627
655
628
- if self . is_toplevel ( ctx) || ( parent_is_namespace && count_namespaces) {
629
- let base_name = self . make_exposed_name ( None , base_name, ctx) ;
656
+ if within_namespace {
630
657
return ctx. rust_mangle ( & base_name) . into_owned ( ) ;
631
658
}
632
659
633
- // TODO: allow modification of the mangling functions, maybe even per
634
- // item type?
635
- let parent_name = parent. canonical_name ( ctx) ;
636
- self . make_exposed_name ( Some ( parent_name) , base_name, ctx)
660
+ // Concatenate this item's ancestors' names together.
661
+ let mut names: Vec < _ > = target. parent_id ( )
662
+ . ancestors ( ctx)
663
+ . filter ( |id| * id != ctx. root_module ( ) )
664
+ . map ( |id| {
665
+ let item = ctx. resolve_item ( id) ;
666
+ let target = ctx. resolve_item ( item. name_target ( ctx, false ) ) ;
667
+ target. base_name ( ctx, false )
668
+ } )
669
+ . filter ( |name| !name. is_empty ( ) )
670
+ . collect ( ) ;
671
+ names. reverse ( ) ;
672
+ names. push ( base_name) ;
673
+ let name = names. join ( "_" ) ;
674
+
675
+ ctx. rust_mangle ( & name) . into_owned ( )
637
676
}
638
677
639
678
fn exposed_id ( & self , ctx : & BindgenContext ) -> String {
@@ -654,45 +693,6 @@ impl Item {
654
693
format ! ( "id_{}" , self . id( ) . as_usize( ) )
655
694
}
656
695
657
- fn make_exposed_name ( & self ,
658
- parent_name : Option < String > ,
659
- base_name : Option < String > ,
660
- ctx : & BindgenContext )
661
- -> String {
662
- lazy_static ! {
663
- static ref RE_ENDS_WITH_BINDGEN_TY : Regex =
664
- Regex :: new( r"_bindgen_ty(_\d+)+$" ) . unwrap( ) ;
665
-
666
- static ref RE_ENDS_WITH_BINDGEN_MOD : Regex =
667
- Regex :: new( r"_bindgen_mod(_\d+)+$" ) . unwrap( ) ;
668
- }
669
-
670
- let ( re, kind) = match * self . kind ( ) {
671
- ItemKind :: Module ( ..) => ( & * RE_ENDS_WITH_BINDGEN_MOD , "mod" ) ,
672
- _ => ( & * RE_ENDS_WITH_BINDGEN_TY , "ty" ) ,
673
- } ;
674
-
675
- let parent_name =
676
- parent_name. and_then ( |n| if n. is_empty ( ) { None } else { Some ( n) } ) ;
677
- match ( parent_name, base_name) {
678
- ( Some ( parent) , Some ( base) ) => format ! ( "{}_{}" , parent, base) ,
679
- ( Some ( parent) , None ) => {
680
- if re. is_match ( parent. as_str ( ) ) {
681
- format ! ( "{}_{}" , parent, self . exposed_id( ctx) )
682
- } else {
683
- format ! ( "{}__bindgen_{}_{}" ,
684
- parent,
685
- kind,
686
- self . exposed_id( ctx) )
687
- }
688
- }
689
- ( None , Some ( base) ) => base,
690
- ( None , None ) => {
691
- format ! ( "_bindgen_{}_{}" , kind, self . exposed_id( ctx) )
692
- }
693
- }
694
- }
695
-
696
696
/// Get a mutable reference to this item's `Module`, or `None` if this is
697
697
/// not a `Module` item.
698
698
pub fn as_module_mut ( & mut self ) -> Option < & mut Module > {
0 commit comments