@@ -68,7 +68,7 @@ impl<'a> From<ResolutionFailure<'a>> for ErrorKind<'a> {
68
68
}
69
69
70
70
#[ derive( Copy , Clone , Debug , Hash ) ]
71
- enum Res {
71
+ crate enum Res {
72
72
Def ( DefKind , DefId ) ,
73
73
Primitive ( PrimitiveType ) ,
74
74
}
@@ -134,7 +134,7 @@ impl TryFrom<ResolveRes> for Res {
134
134
135
135
/// A link failed to resolve.
136
136
#[ derive( Debug ) ]
137
- enum ResolutionFailure < ' a > {
137
+ crate enum ResolutionFailure < ' a > {
138
138
/// This resolved, but with the wrong namespace.
139
139
WrongNamespace {
140
140
/// What the link resolved to.
@@ -172,7 +172,7 @@ enum ResolutionFailure<'a> {
172
172
}
173
173
174
174
#[ derive( Debug ) ]
175
- enum MalformedGenerics {
175
+ crate enum MalformedGenerics {
176
176
/// This link has unbalanced angle brackets.
177
177
///
178
178
/// For example, `Vec<T` should trigger this, as should `Vec<T>>`.
@@ -224,7 +224,7 @@ impl ResolutionFailure<'a> {
224
224
}
225
225
}
226
226
227
- enum AnchorFailure {
227
+ crate enum AnchorFailure {
228
228
/// User error: `[std#x#y]` is not valid
229
229
MultipleAnchors ,
230
230
/// The anchor provided by the user conflicts with Rustdoc's generated anchor.
@@ -892,6 +892,117 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
892
892
}
893
893
}
894
894
895
+ crate enum PreprocessingError < ' a > {
896
+ Anchor ( AnchorFailure ) ,
897
+ Disambiguator ( Range < usize > , String ) ,
898
+ Resolution ( ResolutionFailure < ' a > , String , Option < Disambiguator > ) ,
899
+ }
900
+
901
+ impl From < AnchorFailure > for PreprocessingError < ' _ > {
902
+ fn from ( err : AnchorFailure ) -> Self {
903
+ Self :: Anchor ( err)
904
+ }
905
+ }
906
+
907
+ crate struct PreprocessingInfo {
908
+ crate path_str : String ,
909
+ disambiguator : Option < Disambiguator > ,
910
+ extra_fragment : Option < String > ,
911
+ link_text : String ,
912
+ }
913
+
914
+ /// Returns:
915
+ /// - `None` if the link should be ignored.
916
+ /// - `Some(Err)` if the link should emit an error
917
+ /// - `Some(Ok)` if the link is valid
918
+ ///
919
+ /// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored.
920
+ crate fn preprocess_link < ' a > (
921
+ ori_link : & ' a MarkdownLink ,
922
+ ) -> Option < Result < PreprocessingInfo , PreprocessingError < ' a > > > {
923
+ // [] is mostly likely not supposed to be a link
924
+ if ori_link. link . is_empty ( ) {
925
+ return None ;
926
+ }
927
+
928
+ // Bail early for real links.
929
+ if ori_link. link . contains ( '/' ) {
930
+ return None ;
931
+ }
932
+
933
+ let stripped = ori_link. link . replace ( "`" , "" ) ;
934
+ let mut parts = stripped. split ( '#' ) ;
935
+
936
+ let link = parts. next ( ) . unwrap ( ) ;
937
+ if link. trim ( ) . is_empty ( ) {
938
+ // This is an anchor to an element of the current page, nothing to do in here!
939
+ return None ;
940
+ }
941
+ let extra_fragment = parts. next ( ) ;
942
+ if parts. next ( ) . is_some ( ) {
943
+ // A valid link can't have multiple #'s
944
+ return Some ( Err ( AnchorFailure :: MultipleAnchors . into ( ) ) ) ;
945
+ }
946
+
947
+ // Parse and strip the disambiguator from the link, if present.
948
+ let ( path_str, disambiguator) = match Disambiguator :: from_str ( & link) {
949
+ Ok ( Some ( ( d, path) ) ) => ( path. trim ( ) , Some ( d) ) ,
950
+ Ok ( None ) => ( link. trim ( ) , None ) ,
951
+ Err ( ( err_msg, relative_range) ) => {
952
+ // Only report error if we would not have ignored this link. See issue #83859.
953
+ if !should_ignore_link_with_disambiguators ( link) {
954
+ let no_backticks_range = range_between_backticks ( & ori_link) ;
955
+ let disambiguator_range = ( no_backticks_range. start + relative_range. start )
956
+ ..( no_backticks_range. start + relative_range. end ) ;
957
+ return Some ( Err ( PreprocessingError :: Disambiguator ( disambiguator_range, err_msg) ) ) ;
958
+ } else {
959
+ return None ;
960
+ }
961
+ }
962
+ } ;
963
+
964
+ if should_ignore_link ( path_str) {
965
+ return None ;
966
+ }
967
+
968
+ // We stripped `()` and `!` when parsing the disambiguator.
969
+ // Add them back to be displayed, but not prefix disambiguators.
970
+ let link_text =
971
+ disambiguator. map ( |d| d. display_for ( path_str) ) . unwrap_or_else ( || path_str. to_owned ( ) ) ;
972
+
973
+ // Strip generics from the path.
974
+ let path_str = if path_str. contains ( [ '<' , '>' ] . as_slice ( ) ) {
975
+ match strip_generics_from_path ( & path_str) {
976
+ Ok ( path) => path,
977
+ Err ( err_kind) => {
978
+ debug ! ( "link has malformed generics: {}" , path_str) ;
979
+ return Some ( Err ( PreprocessingError :: Resolution (
980
+ err_kind,
981
+ path_str. to_owned ( ) ,
982
+ disambiguator,
983
+ ) ) ) ;
984
+ }
985
+ }
986
+ } else {
987
+ path_str. to_owned ( )
988
+ } ;
989
+
990
+ // Sanity check to make sure we don't have any angle brackets after stripping generics.
991
+ assert ! ( !path_str. contains( [ '<' , '>' ] . as_slice( ) ) ) ;
992
+
993
+ // The link is not an intra-doc link if it still contains spaces after stripping generics.
994
+ if path_str. contains ( ' ' ) {
995
+ return None ;
996
+ }
997
+
998
+ Some ( Ok ( PreprocessingInfo {
999
+ path_str,
1000
+ disambiguator,
1001
+ extra_fragment : extra_fragment. map ( String :: from) ,
1002
+ link_text,
1003
+ } ) )
1004
+ }
1005
+
895
1006
impl LinkCollector < ' _ , ' _ > {
896
1007
/// This is the entry point for resolving an intra-doc link.
897
1008
///
@@ -907,64 +1018,36 @@ impl LinkCollector<'_, '_> {
907
1018
) -> Option < ItemLink > {
908
1019
trace ! ( "considering link '{}'" , ori_link. link) ;
909
1020
910
- // Bail early for real links.
911
- if ori_link. link . contains ( '/' ) {
912
- return None ;
913
- }
914
-
915
- // [] is mostly likely not supposed to be a link
916
- if ori_link. link . is_empty ( ) {
917
- return None ;
918
- }
919
-
920
1021
let diag_info = DiagnosticInfo {
921
1022
item,
922
1023
dox,
923
1024
ori_link : & ori_link. link ,
924
1025
link_range : ori_link. range . clone ( ) ,
925
1026
} ;
926
1027
927
- let link = ori_link. link . replace ( "`" , "" ) ;
928
- let no_backticks_range = range_between_backticks ( & ori_link) ;
929
- let parts = link. split ( '#' ) . collect :: < Vec < _ > > ( ) ;
930
- let ( link, extra_fragment) = if parts. len ( ) > 2 {
931
- // A valid link can't have multiple #'s
932
- anchor_failure ( self . cx , diag_info, AnchorFailure :: MultipleAnchors ) ;
933
- return None ;
934
- } else if parts. len ( ) == 2 {
935
- if parts[ 0 ] . trim ( ) . is_empty ( ) {
936
- // This is an anchor to an element of the current page, nothing to do in here!
937
- return None ;
938
- }
939
- ( parts[ 0 ] , Some ( parts[ 1 ] . to_owned ( ) ) )
940
- } else {
941
- ( parts[ 0 ] , None )
942
- } ;
943
-
944
- // Parse and strip the disambiguator from the link, if present.
945
- let ( mut path_str, disambiguator) = match Disambiguator :: from_str ( & link) {
946
- Ok ( Some ( ( d, path) ) ) => ( path. trim ( ) , Some ( d) ) ,
947
- Ok ( None ) => ( link. trim ( ) , None ) ,
948
- Err ( ( err_msg, relative_range) ) => {
949
- if !should_ignore_link_with_disambiguators ( link) {
950
- // Only report error if we would not have ignored this link.
951
- // See issue #83859.
952
- let disambiguator_range = ( no_backticks_range. start + relative_range. start )
953
- ..( no_backticks_range. start + relative_range. end ) ;
954
- disambiguator_error ( self . cx , diag_info, disambiguator_range, & err_msg) ;
1028
+ let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
1029
+ match preprocess_link ( & ori_link) ? {
1030
+ Ok ( x) => x,
1031
+ Err ( err) => {
1032
+ match err {
1033
+ PreprocessingError :: Anchor ( err) => anchor_failure ( self . cx , diag_info, err) ,
1034
+ PreprocessingError :: Disambiguator ( range, msg) => {
1035
+ disambiguator_error ( self . cx , diag_info, range, & msg)
1036
+ }
1037
+ PreprocessingError :: Resolution ( err, path_str, disambiguator) => {
1038
+ resolution_failure (
1039
+ self ,
1040
+ diag_info,
1041
+ & path_str,
1042
+ disambiguator,
1043
+ smallvec ! [ err] ,
1044
+ ) ;
1045
+ }
1046
+ }
1047
+ return None ;
955
1048
}
956
- return None ;
957
- }
958
- } ;
959
-
960
- if should_ignore_link ( path_str) {
961
- return None ;
962
- }
963
-
964
- // We stripped `()` and `!` when parsing the disambiguator.
965
- // Add them back to be displayed, but not prefix disambiguators.
966
- let link_text =
967
- disambiguator. map ( |d| d. display_for ( path_str) ) . unwrap_or_else ( || path_str. to_owned ( ) ) ;
1049
+ } ;
1050
+ let mut path_str = & * path_str;
968
1051
969
1052
// In order to correctly resolve intra-doc links we need to
970
1053
// pick a base AST node to work from. If the documentation for
@@ -1029,39 +1112,12 @@ impl LinkCollector<'_, '_> {
1029
1112
module_id = DefId { krate, index : CRATE_DEF_INDEX } ;
1030
1113
}
1031
1114
1032
- // Strip generics from the path.
1033
- let stripped_path_string;
1034
- if path_str. contains ( [ '<' , '>' ] . as_slice ( ) ) {
1035
- stripped_path_string = match strip_generics_from_path ( path_str) {
1036
- Ok ( path) => path,
1037
- Err ( err_kind) => {
1038
- debug ! ( "link has malformed generics: {}" , path_str) ;
1039
- resolution_failure (
1040
- self ,
1041
- diag_info,
1042
- path_str,
1043
- disambiguator,
1044
- smallvec ! [ err_kind] ,
1045
- ) ;
1046
- return None ;
1047
- }
1048
- } ;
1049
- path_str = & stripped_path_string;
1050
- }
1051
- // Sanity check to make sure we don't have any angle brackets after stripping generics.
1052
- assert ! ( !path_str. contains( [ '<' , '>' ] . as_slice( ) ) ) ;
1053
-
1054
- // The link is not an intra-doc link if it still contains spaces after stripping generics.
1055
- if path_str. contains ( ' ' ) {
1056
- return None ;
1057
- }
1058
-
1059
1115
let ( mut res, mut fragment) = self . resolve_with_disambiguator_cached (
1060
1116
ResolutionInfo {
1061
1117
module_id,
1062
1118
dis : disambiguator,
1063
1119
path_str : path_str. to_owned ( ) ,
1064
- extra_fragment,
1120
+ extra_fragment : extra_fragment . map ( String :: from ) ,
1065
1121
} ,
1066
1122
diag_info. clone ( ) , // this struct should really be Copy, but Range is not :(
1067
1123
matches ! ( ori_link. kind, LinkType :: Reference | LinkType :: Shortcut ) ,
0 commit comments