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 ;
@@ -526,6 +526,108 @@ impl Item {
526
526
self . as_type ( ) . map_or ( false , |ty| ty. is_type_ref ( ) )
527
527
}
528
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
+
529
631
/// Get the canonical name without taking into account the replaces
530
632
/// annotation.
531
633
///
@@ -539,102 +641,38 @@ impl Item {
539
641
/// type and the parent chain, since it should be consistent.
540
642
pub fn real_canonical_name ( & self ,
541
643
ctx : & BindgenContext ,
542
- count_namespaces : bool ,
644
+ within_namespace : bool ,
543
645
for_name_checking : bool )
544
646
-> String {
545
- let base_name = match * self . kind ( ) {
546
- ItemKind :: Type ( ref ty) => {
547
- match * ty. kind ( ) {
548
- // If we're a template specialization, our name is our
549
- // parent's.
550
- TypeKind :: Comp ( ref ci)
551
- if ci. is_template_specialization ( ) => {
552
- return ci. specialized_template ( ) . unwrap ( )
553
- . canonical_name ( ctx) ;
554
- } ,
555
- // Same as above
556
- TypeKind :: ResolvedTypeRef ( inner) |
557
- TypeKind :: TemplateRef ( inner, _) => {
558
- return inner. canonical_name ( ctx) ;
559
- }
560
- // If we're a named type, we don't need to mangle it, and we
561
- // should be able to assert we're not top level.
562
- TypeKind :: Named ( ref name, _) => {
563
- return name. to_owned ( ) ;
564
- }
565
- // We call codegen on the inner type, but we do not want
566
- // this alias's name to appear in the canonical name just
567
- // because it is in the inner type's parent chain, so we use
568
- // an empty base name.
569
- //
570
- // Note that this would be incorrect if this type could be
571
- // referenced from, let's say, a member variable, but in
572
- // that case the referenced type is the inner alias, so
573
- // we're good there. If we wouldn't, a more complex solution
574
- // would be needed.
575
- TypeKind :: TemplateAlias ( inner, _) => {
576
- if for_name_checking {
577
- return ctx. resolve_item ( inner)
578
- . real_canonical_name ( ctx,
579
- count_namespaces,
580
- false ) ;
581
- }
582
- Some ( "" )
583
- }
584
- // Else use the proper name, or fallback to a name with an
585
- // id.
586
- _ => {
587
- ty. name ( )
588
- }
589
- } . map ( ToOwned :: to_owned)
590
- }
591
- ItemKind :: Function ( ref fun) => {
592
- let mut base = fun. name ( ) . to_owned ( ) ;
593
-
594
- // We might need to deduplicate if we're a method.
595
- let parent = ctx. resolve_item ( self . parent_id ( ) ) ;
596
- if let ItemKind :: Type ( ref ty) = * parent. kind ( ) {
597
- if let TypeKind :: Comp ( ref ci) = * ty. kind ( ) {
598
- let mut count = 0 ;
599
- let mut found = false ;
600
- for method in ci. methods ( ) {
601
- if method. signature ( ) == self . id ( ) {
602
- found = true ;
603
- break ;
604
- }
605
- let fun = ctx. resolve_item ( method. signature ( ) )
606
- . expect_function ( ) ;
607
- if fun. name ( ) == base {
608
- count += 1 ;
609
- }
610
- }
611
-
612
- assert ! ( found, "Method not found?" ) ;
613
- if count != 0 {
614
- base. push_str ( & count. to_string ( ) ) ;
615
- }
616
- }
617
- }
618
- Some ( base)
619
- }
620
- ItemKind :: Var ( ref var) => Some ( var. name ( ) . to_owned ( ) ) ,
621
- ItemKind :: Module ( ref module) => {
622
- module. name ( ) . map ( ToOwned :: to_owned)
623
- }
624
- } ;
647
+ let target = ctx. resolve_item ( self . name_target ( ctx, for_name_checking) ) ;
648
+ let base_name = target. base_name ( ctx, for_name_checking) ;
625
649
626
- let parent = ctx. resolve_item ( self . parent_id ( ) ) ;
627
- 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
+ }
628
655
629
- if self . is_toplevel ( ctx) || ( parent_is_namespace && count_namespaces) {
630
- let base_name = self . make_exposed_name ( None , base_name, ctx) ;
656
+ if within_namespace {
631
657
return ctx. rust_mangle ( & base_name) . into_owned ( ) ;
632
658
}
633
659
634
- // TODO: allow modification of the mangling functions, maybe even per
635
- // item type?
636
- let parent_name = parent. canonical_name ( ctx) ;
637
- 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 ( )
638
676
}
639
677
640
678
fn exposed_id ( & self , ctx : & BindgenContext ) -> String {
@@ -655,45 +693,6 @@ impl Item {
655
693
format ! ( "id_{}" , self . id( ) . as_usize( ) )
656
694
}
657
695
658
- fn make_exposed_name ( & self ,
659
- parent_name : Option < String > ,
660
- base_name : Option < String > ,
661
- ctx : & BindgenContext )
662
- -> String {
663
- lazy_static ! {
664
- static ref RE_ENDS_WITH_BINDGEN_TY : Regex =
665
- Regex :: new( r"_bindgen_ty(_\d+)+$" ) . unwrap( ) ;
666
-
667
- static ref RE_ENDS_WITH_BINDGEN_MOD : Regex =
668
- Regex :: new( r"_bindgen_mod(_\d+)+$" ) . unwrap( ) ;
669
- }
670
-
671
- let ( re, kind) = match * self . kind ( ) {
672
- ItemKind :: Module ( ..) => ( & * RE_ENDS_WITH_BINDGEN_MOD , "mod" ) ,
673
- _ => ( & * RE_ENDS_WITH_BINDGEN_TY , "ty" ) ,
674
- } ;
675
-
676
- let parent_name =
677
- parent_name. and_then ( |n| if n. is_empty ( ) { None } else { Some ( n) } ) ;
678
- match ( parent_name, base_name) {
679
- ( Some ( parent) , Some ( base) ) => format ! ( "{}_{}" , parent, base) ,
680
- ( Some ( parent) , None ) => {
681
- if re. is_match ( parent. as_str ( ) ) {
682
- format ! ( "{}_{}" , parent, self . exposed_id( ctx) )
683
- } else {
684
- format ! ( "{}__bindgen_{}_{}" ,
685
- parent,
686
- kind,
687
- self . exposed_id( ctx) )
688
- }
689
- }
690
- ( None , Some ( base) ) => base,
691
- ( None , None ) => {
692
- format ! ( "_bindgen_{}_{}" , kind, self . exposed_id( ctx) )
693
- }
694
- }
695
- }
696
-
697
696
/// Get a mutable reference to this item's `Module`, or `None` if this is
698
697
/// not a `Module` item.
699
698
pub fn as_module_mut ( & mut self ) -> Option < & mut Module > {
0 commit comments