@@ -57,7 +57,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
57
57
path_str : & str ,
58
58
ns : Namespace ,
59
59
current_item : & Option < String > ,
60
- parent_id : Option < hir:: HirId > )
60
+ parent_id : Option < hir:: HirId > ,
61
+ extra_fragment : & Option < String > )
61
62
-> Result < ( Res , Option < String > ) , ( ) >
62
63
{
63
64
let cx = self . cx ;
@@ -80,16 +81,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
80
81
let value = match res {
81
82
Res :: Def ( DefKind :: Method , _) | Res :: Def ( DefKind :: AssocConst , _) => true ,
82
83
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 ) ,
84
85
// 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
+ }
85
90
Res :: PrimTy ( ..) => return Ok ( ( res, Some ( path_str. to_owned ( ) ) ) ) ,
86
- _ => return Ok ( ( res, None ) )
91
+ _ => return Ok ( ( res, extra_fragment . clone ( ) ) )
87
92
} ;
88
93
89
94
if value != ( ns == ValueNS ) {
90
95
return Err ( ( ) )
91
96
}
92
97
} 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
+ //}
93
101
return Ok ( ( prim, Some ( path_str. to_owned ( ) ) ) )
94
102
} else {
95
103
// If resolution failed, it may still be a method
@@ -153,6 +161,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
153
161
ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
154
162
_ => return Err ( ( ) )
155
163
} ;
164
+ //if extra_fragment.is_some() {
165
+ // TODO: warn in here! (and don't return Ok)
166
+ //}
156
167
Ok ( ( ty_res, Some ( format ! ( "{}.{}" , out, item_name) ) ) )
157
168
} else {
158
169
match cx. tcx . type_of ( did) . kind {
@@ -165,6 +176,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
165
176
. iter ( )
166
177
. find ( |item| item. ident . name == item_name)
167
178
} {
179
+ //if extra_fragment.is_some() {
180
+ // TODO: warn in here! (and don't return Ok)
181
+ //}
168
182
Ok ( ( ty_res,
169
183
Some ( format ! ( "{}.{}" ,
170
184
if def. is_enum( ) {
@@ -199,6 +213,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
199
213
_ => return Err ( ( ) )
200
214
} ;
201
215
216
+ //if extra_fragment.is_some() {
217
+ // TODO: warn in here! (and don't return Ok)
218
+ //}
202
219
Ok ( ( ty_res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
203
220
} else {
204
221
Err ( ( ) )
@@ -289,6 +306,27 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
289
306
}
290
307
291
308
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
+ } ;
292
330
let ( res, fragment) = {
293
331
let mut kind = None ;
294
332
let path_str = if let Some ( prefix) =
@@ -341,7 +379,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
341
379
342
380
match kind {
343
381
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) {
345
384
res
346
385
} else {
347
386
resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -352,7 +391,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
352
391
}
353
392
}
354
393
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) {
356
396
res
357
397
} else {
358
398
resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -363,18 +403,27 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
363
403
None => {
364
404
// Try everything!
365
405
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 ( ) ) ) ,
367
408
type_ns : self
368
- . resolve ( path_str, TypeNS , & current_item, base_node)
409
+ . resolve ( path_str, TypeNS , & current_item, base_node, & extra_fragment )
369
410
. ok ( ) ,
370
411
value_ns : self
371
- . resolve ( path_str, ValueNS , & current_item, base_node)
412
+ . resolve ( path_str, ValueNS , & current_item, base_node, & extra_fragment )
372
413
. ok ( )
373
414
. and_then ( |( res, fragment) | {
374
415
// Constructors are picked up in the type namespace.
375
416
match res {
376
417
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
+ } ,
378
427
}
379
428
} ) ,
380
429
} ;
@@ -402,7 +451,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
402
451
}
403
452
Some ( MacroNS ) => {
404
453
if let Some ( res) = macro_resolve ( cx, path_str) {
405
- ( res, None )
454
+ ( res, extra_fragment )
406
455
} else {
407
456
resolution_failure ( cx, & item, path_str, & dox, link_range) ;
408
457
continue
@@ -637,7 +686,11 @@ fn ambiguity_error(
637
686
}
638
687
639
688
/// 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 > ) , ( ) > {
641
694
use rustc:: ty:: DefIdTree ;
642
695
643
696
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>)
647
700
} ;
648
701
let parent_def = Res :: Def ( DefKind :: Enum , parent) ;
649
702
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
+ }
650
706
Ok ( ( parent_def, Some ( format ! ( "{}.v" , variant. ident. name) ) ) )
651
707
}
652
708
0 commit comments