@@ -659,7 +659,8 @@ pub struct Attributes {
659
659
pub other_attrs : Vec < ast:: Attribute > ,
660
660
pub cfg : Option < Rc < Cfg > > ,
661
661
pub span : Option < syntax_pos:: Span > ,
662
- pub links : Vec < ( String , DefId ) > ,
662
+ /// map from Rust paths to resolved defs and potential URL fragments
663
+ pub links : Vec < ( String , DefId , Option < String > ) > ,
663
664
}
664
665
665
666
impl Attributes {
@@ -820,8 +821,12 @@ impl Attributes {
820
821
/// Cache must be populated before call
821
822
pub fn links ( & self ) -> Vec < ( String , String ) > {
822
823
use html:: format:: href;
823
- self . links . iter ( ) . filter_map ( |& ( ref s, did) | {
824
- if let Some ( ( href, ..) ) = href ( did) {
824
+ self . links . iter ( ) . filter_map ( |& ( ref s, did, ref fragment) | {
825
+ if let Some ( ( mut href, ..) ) = href ( did) {
826
+ if let Some ( ref fragment) = * fragment {
827
+ href. push_str ( "#" ) ;
828
+ href. push_str ( fragment) ;
829
+ }
825
830
Some ( ( s. clone ( ) , href) )
826
831
} else {
827
832
None
@@ -893,16 +898,67 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
893
898
}
894
899
895
900
/// Resolve a given string as a path, along with whether or not it is
896
- /// in the value namespace
897
- fn resolve ( cx : & DocContext , path_str : & str , is_val : bool ) -> Result < Def , ( ) > {
901
+ /// in the value namespace. Also returns an optional URL fragment in the case
902
+ /// of variants and methods
903
+ fn resolve ( cx : & DocContext , path_str : & str , is_val : bool ) -> Result < ( Def , Option < String > ) , ( ) > {
898
904
// In case we're in a module, try to resolve the relative
899
905
// path
900
906
if let Some ( id) = cx. mod_ids . borrow ( ) . last ( ) {
901
- cx. resolver . borrow_mut ( )
902
- . with_scope ( * id, |resolver| {
903
- resolver. resolve_str_path_error ( DUMMY_SP ,
904
- & path_str, is_val)
905
- } ) . map ( |path| path. def )
907
+ let result = cx. resolver . borrow_mut ( )
908
+ . with_scope ( * id,
909
+ |resolver| {
910
+ resolver. resolve_str_path_error ( DUMMY_SP ,
911
+ & path_str, is_val)
912
+ } ) ;
913
+
914
+ if result. is_ok ( ) {
915
+ return result. map ( |path| ( path. def , None ) ) ;
916
+ }
917
+
918
+ // Try looking for methods and other associated items
919
+ let mut split = path_str. rsplitn ( 2 , "::" ) ;
920
+ let mut item_name = if let Some ( first) = split. next ( ) {
921
+ first
922
+ } else {
923
+ return Err ( ( ) )
924
+ } ;
925
+
926
+ let mut path = if let Some ( second) = split. next ( ) {
927
+ second
928
+ } else {
929
+ return Err ( ( ) )
930
+ } ;
931
+
932
+ let ty = cx. resolver . borrow_mut ( )
933
+ . with_scope ( * id,
934
+ |resolver| {
935
+ resolver. resolve_str_path_error ( DUMMY_SP ,
936
+ & path, false )
937
+ } ) ?;
938
+
939
+
940
+ match ty. def {
941
+ Def :: Struct ( did) | Def :: Union ( did) | Def :: Enum ( did) | Def :: TyAlias ( did) => {
942
+ let item = cx. tcx . inherent_impls ( did) . iter ( )
943
+ . flat_map ( |imp| cx. tcx . associated_items ( * imp) )
944
+ . find ( |item| item. name == item_name) ;
945
+ if let Some ( item) = item {
946
+ if item. kind == ty:: AssociatedKind :: Method && is_val {
947
+ Ok ( ( ty. def , Some ( format ! ( "method.{}" , item_name) ) ) )
948
+ } else {
949
+ Err ( ( ) )
950
+ }
951
+ } else {
952
+ Err ( ( ) )
953
+ }
954
+ }
955
+ Def :: Trait ( _) => {
956
+ // XXXManishearth todo
957
+ Err ( ( ) )
958
+ }
959
+ _ => Err ( ( ) )
960
+ }
961
+
906
962
} else {
907
963
Err ( ( ) )
908
964
}
@@ -953,7 +1009,7 @@ impl Clean<Attributes> for [ast::Attribute] {
953
1009
if UnstableFeatures :: from_environment ( ) . is_nightly_build ( ) {
954
1010
let dox = attrs. collapsed_doc_value ( ) . unwrap_or_else ( String :: new) ;
955
1011
for link in markdown_links ( & dox, cx. render_type ) {
956
- let def = {
1012
+ let ( def, fragment ) = {
957
1013
let mut kind = PathKind :: Unknown ;
958
1014
let path_str = if let Some ( prefix) =
959
1015
[ "struct@" , "enum@" , "type@" ,
@@ -963,7 +1019,8 @@ impl Clean<Attributes> for [ast::Attribute] {
963
1019
link. trim_left_matches ( prefix)
964
1020
} else if let Some ( prefix) =
965
1021
[ "const@" , "static@" ,
966
- "value@" , "function@" , "mod@" , "fn@" , "module@" ]
1022
+ "value@" , "function@" , "mod@" ,
1023
+ "fn@" , "module@" , "method@" ]
967
1024
. iter ( ) . find ( |p| link. starts_with ( * * p) ) {
968
1025
kind = PathKind :: Value ;
969
1026
link. trim_left_matches ( prefix)
@@ -1013,31 +1070,31 @@ impl Clean<Attributes> for [ast::Attribute] {
1013
1070
if let Some ( macro_def) = macro_resolve ( cx, path_str) {
1014
1071
if let Ok ( type_def) = resolve ( cx, path_str, false ) {
1015
1072
let ( type_kind, article, type_disambig)
1016
- = type_ns_kind ( type_def, path_str) ;
1073
+ = type_ns_kind ( type_def. 0 , path_str) ;
1017
1074
ambiguity_error ( cx, & attrs, path_str,
1018
1075
article, type_kind, & type_disambig,
1019
1076
"a" , "macro" , & format ! ( "macro@{}" , path_str) ) ;
1020
1077
continue ;
1021
1078
} else if let Ok ( value_def) = resolve ( cx, path_str, true ) {
1022
1079
let ( value_kind, value_disambig)
1023
- = value_ns_kind ( value_def, path_str)
1080
+ = value_ns_kind ( value_def. 0 , path_str)
1024
1081
. expect ( "struct and mod cases should have been \
1025
1082
caught in previous branch") ;
1026
1083
ambiguity_error ( cx, & attrs, path_str,
1027
1084
"a" , value_kind, & value_disambig,
1028
1085
"a" , "macro" , & format ! ( "macro@{}" , path_str) ) ;
1029
1086
}
1030
- macro_def
1087
+ ( macro_def, None )
1031
1088
} else if let Ok ( type_def) = resolve ( cx, path_str, false ) {
1032
1089
// It is imperative we search for not-a-value first
1033
1090
// Otherwise we will find struct ctors for when we are looking
1034
1091
// for structs, and the link won't work.
1035
1092
// if there is something in both namespaces
1036
1093
if let Ok ( value_def) = resolve ( cx, path_str, true ) {
1037
- let kind = value_ns_kind ( value_def, path_str) ;
1094
+ let kind = value_ns_kind ( value_def. 0 , path_str) ;
1038
1095
if let Some ( ( value_kind, value_disambig) ) = kind {
1039
1096
let ( type_kind, article, type_disambig)
1040
- = type_ns_kind ( type_def, path_str) ;
1097
+ = type_ns_kind ( type_def. 0 , path_str) ;
1041
1098
ambiguity_error ( cx, & attrs, path_str,
1042
1099
article, type_kind, & type_disambig,
1043
1100
"a" , value_kind, & value_disambig) ;
@@ -1054,7 +1111,7 @@ impl Clean<Attributes> for [ast::Attribute] {
1054
1111
}
1055
1112
PathKind :: Macro => {
1056
1113
if let Some ( def) = macro_resolve ( cx, path_str) {
1057
- def
1114
+ ( def, None )
1058
1115
} else {
1059
1116
continue
1060
1117
}
@@ -1064,7 +1121,7 @@ impl Clean<Attributes> for [ast::Attribute] {
1064
1121
1065
1122
1066
1123
let id = register_def ( cx, def) ;
1067
- attrs. links . push ( ( link, id) ) ;
1124
+ attrs. links . push ( ( link, id, fragment ) ) ;
1068
1125
}
1069
1126
1070
1127
cx. sess ( ) . abort_if_errors ( ) ;
0 commit comments