@@ -57,7 +57,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
5757 path_str : & str ,
5858 ns : Namespace ,
5959 current_item : & Option < String > ,
60- parent_id : Option < hir:: HirId > )
60+ parent_id : Option < hir:: HirId > ,
61+ extra_fragment : & Option < String > )
6162 -> Result < ( Res , Option < String > ) , ( ) >
6263 {
6364 let cx = self . cx ;
@@ -80,16 +81,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
8081 let value = match res {
8182 Res :: Def ( DefKind :: Method , _) | Res :: Def ( DefKind :: AssocConst , _) => true ,
8283 Res :: Def ( DefKind :: AssocTy , _) => false ,
83- Res :: Def ( DefKind :: Variant , _) => return handle_variant ( cx, res) ,
84+ Res :: Def ( DefKind :: Variant , _) => return handle_variant ( cx, res, extra_fragment ) ,
8485 // Not a trait item; just return what we found.
86+ Res :: PrimTy ( ..) if extra_fragment. is_some ( ) => {
87+ // TODO: warn in here! (and don't return Ok)
88+ return Ok ( ( res, Some ( path_str. to_owned ( ) ) ) )
89+ }
8590 Res :: PrimTy ( ..) => return Ok ( ( res, Some ( path_str. to_owned ( ) ) ) ) ,
86- _ => return Ok ( ( res, None ) )
91+ _ => return Ok ( ( res, extra_fragment . clone ( ) ) )
8792 } ;
8893
8994 if value != ( ns == ValueNS ) {
9095 return Err ( ( ) )
9196 }
9297 } else if let Some ( prim) = is_primitive ( path_str, ns) {
98+ //if extra_fragment.is_some() {
99+ // TODO: warn in here! (and don't return Ok)
100+ //}
93101 return Ok ( ( prim, Some ( path_str. to_owned ( ) ) ) )
94102 } else {
95103 // If resolution failed, it may still be a method
@@ -153,6 +161,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
153161 ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
154162 _ => return Err ( ( ) )
155163 } ;
164+ //if extra_fragment.is_some() {
165+ // TODO: warn in here! (and don't return Ok)
166+ //}
156167 Ok ( ( ty_res, Some ( format ! ( "{}.{}" , out, item_name) ) ) )
157168 } else {
158169 match cx. tcx . type_of ( did) . kind {
@@ -165,6 +176,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
165176 . iter ( )
166177 . find ( |item| item. ident . name == item_name)
167178 } {
179+ //if extra_fragment.is_some() {
180+ // TODO: warn in here! (and don't return Ok)
181+ //}
168182 Ok ( ( ty_res,
169183 Some ( format ! ( "{}.{}" ,
170184 if def. is_enum( ) {
@@ -199,6 +213,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
199213 _ => return Err ( ( ) )
200214 } ;
201215
216+ //if extra_fragment.is_some() {
217+ // TODO: warn in here! (and don't return Ok)
218+ //}
202219 Ok ( ( ty_res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
203220 } else {
204221 Err ( ( ) )
@@ -289,6 +306,27 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
289306 }
290307
291308 let link = ori_link. replace ( "`" , "" ) ;
309+ let parts = link. split ( '#' ) . collect :: < Vec < _ > > ( ) ;
310+ let ( link, extra_fragment) = if parts. len ( ) > 2 {
311+ let mut diag = cx. tcx . struct_span_lint_hir (
312+ lint:: builtin:: INTRA_DOC_LINK_RESOLUTION_FAILURE ,
313+ item_hir_id. unwrap ( ) ,
314+ span_of_attrs ( & item. attrs ) . unwrap_or ( item. source . span ( ) ) ,
315+ & format ! ( "`[{}]` cannot be resolved, ignoring it..." , ori_link) ,
316+ ) ;
317+ // TODO: use the correct span!
318+ diag. span_label ( DUMMY_SP , "only one `#` is allowed in a link" ) ;
319+ diag. emit ( ) ;
320+ continue ;
321+ } else if parts. len ( ) == 2 {
322+ if parts[ 0 ] . trim ( ) . is_empty ( ) {
323+ // This is an anchor to an element of the current page, nothing to do in here!
324+ continue ;
325+ }
326+ ( parts[ 0 ] . to_owned ( ) , Some ( parts[ 1 ] . to_owned ( ) ) )
327+ } else {
328+ ( parts[ 0 ] . to_owned ( ) , None )
329+ } ;
292330 let ( res, fragment) = {
293331 let mut kind = None ;
294332 let path_str = if let Some ( prefix) =
@@ -341,7 +379,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
341379
342380 match kind {
343381 Some ( ns @ ValueNS ) => {
344- if let Ok ( res) = self . resolve ( path_str, ns, & current_item, base_node) {
382+ if let Ok ( res) = self . resolve ( path_str, ns, & current_item, base_node,
383+ & extra_fragment) {
345384 res
346385 } else {
347386 resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -352,7 +391,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
352391 }
353392 }
354393 Some ( ns @ TypeNS ) => {
355- if let Ok ( res) = self . resolve ( path_str, ns, & current_item, base_node) {
394+ if let Ok ( res) = self . resolve ( path_str, ns, & current_item, base_node,
395+ & extra_fragment) {
356396 res
357397 } else {
358398 resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -363,18 +403,27 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
363403 None => {
364404 // Try everything!
365405 let candidates = PerNS {
366- macro_ns : macro_resolve ( cx, path_str) . map ( |res| ( res, None ) ) ,
406+ macro_ns : macro_resolve ( cx, path_str)
407+ . map ( |res| ( res, extra_fragment. clone ( ) ) ) ,
367408 type_ns : self
368- . resolve ( path_str, TypeNS , & current_item, base_node)
409+ . resolve ( path_str, TypeNS , & current_item, base_node, & extra_fragment )
369410 . ok ( ) ,
370411 value_ns : self
371- . resolve ( path_str, ValueNS , & current_item, base_node)
412+ . resolve ( path_str, ValueNS , & current_item, base_node, & extra_fragment )
372413 . ok ( )
373414 . and_then ( |( res, fragment) | {
374415 // Constructors are picked up in the type namespace.
375416 match res {
376417 Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) => None ,
377- _ => Some ( ( res, fragment) )
418+ _ => match ( fragment, extra_fragment) {
419+ ( Some ( fragment) , Some ( _) ) => {
420+ // Shouldn't happen but who knows?
421+ Some ( ( res, Some ( fragment) ) )
422+ }
423+ ( fragment, None ) | ( None , fragment) => {
424+ Some ( ( res, fragment) )
425+ }
426+ } ,
378427 }
379428 } ) ,
380429 } ;
@@ -402,7 +451,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
402451 }
403452 Some ( MacroNS ) => {
404453 if let Some ( res) = macro_resolve ( cx, path_str) {
405- ( res, None )
454+ ( res, extra_fragment )
406455 } else {
407456 resolution_failure ( cx, & item, path_str, & dox, link_range) ;
408457 continue
@@ -637,7 +686,11 @@ fn ambiguity_error(
637686}
638687
639688/// Given an enum variant's res, return the res of its enum and the associated fragment.
640- fn handle_variant ( cx : & DocContext < ' _ > , res : Res ) -> Result < ( Res , Option < String > ) , ( ) > {
689+ fn handle_variant (
690+ cx : & DocContext < ' _ > ,
691+ res : Res ,
692+ extra_fragment : & Option < String > ,
693+ ) -> Result < ( Res , Option < String > ) , ( ) > {
641694 use rustc:: ty:: DefIdTree ;
642695
643696 let parent = if let Some ( parent) = cx. tcx . parent ( res. def_id ( ) ) {
@@ -647,6 +700,9 @@ fn handle_variant(cx: &DocContext<'_>, res: Res) -> Result<(Res, Option<String>)
647700 } ;
648701 let parent_def = Res :: Def ( DefKind :: Enum , parent) ;
649702 let variant = cx. tcx . expect_variant_res ( res) ;
703+ if extra_fragment. is_some ( ) {
704+ // TODO warn in here! (and don't return ok)
705+ }
650706 Ok ( ( parent_def, Some ( format ! ( "{}.v" , variant. ident. name) ) ) )
651707}
652708
0 commit comments