@@ -4,13 +4,15 @@ mod intra_doc_links;
4
4
5
5
use std:: convert:: { TryFrom , TryInto } ;
6
6
7
+ use either:: Either ;
7
8
use pulldown_cmark:: { BrokenLink , CowStr , Event , InlineStr , LinkType , Options , Parser , Tag } ;
8
9
use pulldown_cmark_to_cmark:: { cmark_with_options, Options as CmarkOptions } ;
9
10
use stdx:: format_to;
10
11
use url:: Url ;
11
12
12
13
use hir:: {
13
- db:: HirDatabase , Adt , AsAssocItem , AssocItem , AssocItemContainer , Crate , HasAttrs , ModuleDef ,
14
+ db:: HirDatabase , Adt , AsAssocItem , AssocItem , AssocItemContainer , Crate , HasAttrs , MacroDef ,
15
+ ModuleDef ,
14
16
} ;
15
17
use ide_db:: {
16
18
defs:: { Definition , NameClass , NameRefClass } ,
@@ -47,7 +49,7 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Defin
47
49
return rewritten;
48
50
}
49
51
if let Definition :: ModuleDef ( def) = definition {
50
- if let Some ( target) = rewrite_url_link ( db, def, target) {
52
+ if let Some ( target) = rewrite_url_link ( db, Either :: Left ( def) , target) {
51
53
return ( target, title. to_string ( ) ) ;
52
54
}
53
55
}
@@ -169,7 +171,7 @@ pub(crate) fn resolve_doc_path_for_def(
169
171
def : Definition ,
170
172
link : & str ,
171
173
ns : Option < hir:: Namespace > ,
172
- ) -> Option < hir :: ModuleDef > {
174
+ ) -> Option < Either < ModuleDef , MacroDef > > {
173
175
match def {
174
176
Definition :: ModuleDef ( def) => match def {
175
177
hir:: ModuleDef :: Module ( it) => it. resolve_doc_path ( db, link, ns) ,
@@ -243,9 +245,9 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
243
245
AssocItemContainer :: Impl ( i) => i. self_ty ( db) . as_adt ( ) ?. into ( ) ,
244
246
} ;
245
247
let frag = get_assoc_item_fragment ( db, assoc_item) ?;
246
- ( def, Some ( frag) )
248
+ ( Either :: Left ( def) , Some ( frag) )
247
249
} else {
248
- ( def, None )
250
+ ( Either :: Left ( def) , None )
249
251
}
250
252
}
251
253
Definition :: Field ( field) => {
@@ -254,10 +256,9 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
254
256
hir:: VariantDef :: Union ( it) => it. into ( ) ,
255
257
hir:: VariantDef :: Variant ( it) => it. into ( ) ,
256
258
} ;
257
- ( def, Some ( format ! ( "structfield.{}" , field. name( db) ) ) )
259
+ ( Either :: Left ( def) , Some ( format ! ( "structfield.{}" , field. name( db) ) ) )
258
260
}
259
- // FIXME macros
260
- Definition :: Macro ( _) => return None ,
261
+ Definition :: Macro ( makro) => ( Either :: Right ( makro) , None ) ,
261
262
// FIXME impls
262
263
Definition :: SelfType ( _) => return None ,
263
264
Definition :: Local ( _) | Definition :: GenericParam ( _) | Definition :: Label ( _) => return None ,
@@ -270,7 +271,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
270
271
url = url. join ( & path) . ok ( ) ?;
271
272
}
272
273
273
- url = url. join ( & get_symbol_filename ( db, & target) ?) . ok ( ) ?;
274
+ url = url. join ( & get_symbol_filename ( db, target) ?) . ok ( ) ?;
274
275
url. set_fragment ( frag. as_deref ( ) ) ;
275
276
276
277
Some ( url. into ( ) )
@@ -292,24 +293,29 @@ fn rewrite_intra_doc_link(
292
293
url = url. join ( & path) . ok ( ) ?;
293
294
}
294
295
295
- let ( resolved, frag) = if let Some ( assoc_item) = resolved. as_assoc_item ( db) {
296
- let resolved = match assoc_item. container ( db) {
297
- AssocItemContainer :: Trait ( t) => t. into ( ) ,
298
- AssocItemContainer :: Impl ( i) => i. self_ty ( db) . as_adt ( ) ?. into ( ) ,
296
+ let ( resolved, frag) =
297
+ if let Some ( assoc_item) = resolved. left ( ) . and_then ( |it| it. as_assoc_item ( db) ) {
298
+ let resolved = match assoc_item. container ( db) {
299
+ AssocItemContainer :: Trait ( t) => t. into ( ) ,
300
+ AssocItemContainer :: Impl ( i) => i. self_ty ( db) . as_adt ( ) ?. into ( ) ,
301
+ } ;
302
+ let frag = get_assoc_item_fragment ( db, assoc_item) ?;
303
+ ( Either :: Left ( resolved) , Some ( frag) )
304
+ } else {
305
+ ( resolved, None )
299
306
} ;
300
- let frag = get_assoc_item_fragment ( db, assoc_item) ?;
301
- ( resolved, Some ( frag) )
302
- } else {
303
- ( resolved, None )
304
- } ;
305
- url = url. join ( & get_symbol_filename ( db, & resolved) ?) . ok ( ) ?;
307
+ url = url. join ( & get_symbol_filename ( db, resolved) ?) . ok ( ) ?;
306
308
url. set_fragment ( frag. as_deref ( ) ) ;
307
309
308
310
Some ( ( url. into ( ) , strip_prefixes_suffixes ( title) . to_string ( ) ) )
309
311
}
310
312
311
313
/// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`).
312
- fn rewrite_url_link ( db : & RootDatabase , def : ModuleDef , target : & str ) -> Option < String > {
314
+ fn rewrite_url_link (
315
+ db : & RootDatabase ,
316
+ def : Either < ModuleDef , MacroDef > ,
317
+ target : & str ,
318
+ ) -> Option < String > {
313
319
if !( target. contains ( '#' ) || target. contains ( ".html" ) ) {
314
320
return None ;
315
321
}
@@ -321,25 +327,35 @@ fn rewrite_url_link(db: &RootDatabase, def: ModuleDef, target: &str) -> Option<S
321
327
url = url. join ( & path) . ok ( ) ?;
322
328
}
323
329
324
- url = url. join ( & get_symbol_filename ( db, & def) ?) . ok ( ) ?;
330
+ url = url. join ( & get_symbol_filename ( db, def) ?) . ok ( ) ?;
325
331
url. join ( target) . ok ( ) . map ( Into :: into)
326
332
}
327
333
328
- fn crate_of_def ( db : & RootDatabase , def : ModuleDef ) -> Option < Crate > {
334
+ fn crate_of_def ( db : & RootDatabase , def : Either < ModuleDef , MacroDef > ) -> Option < Crate > {
329
335
let krate = match def {
330
336
// Definition::module gives back the parent module, we don't want that as it fails for root modules
331
- ModuleDef :: Module ( module) => module. krate ( ) ,
332
- _ => def. module ( db) ?. krate ( ) ,
337
+ Either :: Left ( ModuleDef :: Module ( module) ) => module. krate ( ) ,
338
+ Either :: Left ( def) => def. module ( db) ?. krate ( ) ,
339
+ Either :: Right ( def) => def. module ( db) ?. krate ( ) ,
333
340
} ;
334
341
Some ( krate)
335
342
}
336
343
337
- fn mod_path_of_def ( db : & RootDatabase , def : ModuleDef ) -> Option < String > {
338
- def. canonical_module_path ( db) . map ( |it| {
339
- let mut path = String :: new ( ) ;
340
- it. flat_map ( |it| it. name ( db) ) . for_each ( |name| format_to ! ( path, "{}/" , name) ) ;
341
- path
342
- } )
344
+ fn mod_path_of_def ( db : & RootDatabase , def : Either < ModuleDef , MacroDef > ) -> Option < String > {
345
+ match def {
346
+ Either :: Left ( def) => def. canonical_module_path ( db) . map ( |it| {
347
+ let mut path = String :: new ( ) ;
348
+ it. flat_map ( |it| it. name ( db) ) . for_each ( |name| format_to ! ( path, "{}/" , name) ) ;
349
+ path
350
+ } ) ,
351
+ Either :: Right ( def) => {
352
+ def. module ( db) . map ( |it| it. path_to_root ( db) . into_iter ( ) . rev ( ) ) . map ( |it| {
353
+ let mut path = String :: new ( ) ;
354
+ it. flat_map ( |it| it. name ( db) ) . for_each ( |name| format_to ! ( path, "{}/" , name) ) ;
355
+ path
356
+ } )
357
+ }
358
+ }
343
359
}
344
360
345
361
/// Rewrites a markdown document, applying 'callback' to each link.
@@ -405,27 +421,34 @@ fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
405
421
/// https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
406
422
/// ^^^^^^^^^^^^^^^^^^^
407
423
/// ```
408
- fn get_symbol_filename ( db : & dyn HirDatabase , definition : & ModuleDef ) -> Option < String > {
409
- Some ( match definition {
410
- ModuleDef :: Adt ( adt) => match adt {
411
- Adt :: Struct ( s) => format ! ( "struct.{}.html" , s. name( db) ) ,
412
- Adt :: Enum ( e) => format ! ( "enum.{}.html" , e. name( db) ) ,
413
- Adt :: Union ( u) => format ! ( "union.{}.html" , u. name( db) ) ,
414
- } ,
415
- ModuleDef :: Module ( m) => match m. name ( db) {
416
- Some ( name) => format ! ( "{}/index.html" , name) ,
417
- None => String :: from ( "index.html" ) ,
424
+ fn get_symbol_filename (
425
+ db : & dyn HirDatabase ,
426
+ definition : Either < ModuleDef , MacroDef > ,
427
+ ) -> Option < String > {
428
+ let res = match definition {
429
+ Either :: Left ( definition) => match definition {
430
+ ModuleDef :: Adt ( adt) => match adt {
431
+ Adt :: Struct ( s) => format ! ( "struct.{}.html" , s. name( db) ) ,
432
+ Adt :: Enum ( e) => format ! ( "enum.{}.html" , e. name( db) ) ,
433
+ Adt :: Union ( u) => format ! ( "union.{}.html" , u. name( db) ) ,
434
+ } ,
435
+ ModuleDef :: Module ( m) => match m. name ( db) {
436
+ Some ( name) => format ! ( "{}/index.html" , name) ,
437
+ None => String :: from ( "index.html" ) ,
438
+ } ,
439
+ ModuleDef :: Trait ( t) => format ! ( "trait.{}.html" , t. name( db) ) ,
440
+ ModuleDef :: TypeAlias ( t) => format ! ( "type.{}.html" , t. name( db) ) ,
441
+ ModuleDef :: BuiltinType ( t) => format ! ( "primitive.{}.html" , t. name( ) ) ,
442
+ ModuleDef :: Function ( f) => format ! ( "fn.{}.html" , f. name( db) ) ,
443
+ ModuleDef :: Variant ( ev) => {
444
+ format ! ( "enum.{}.html#variant.{}" , ev. parent_enum( db) . name( db) , ev. name( db) )
445
+ }
446
+ ModuleDef :: Const ( c) => format ! ( "const.{}.html" , c. name( db) ?) ,
447
+ ModuleDef :: Static ( s) => format ! ( "static.{}.html" , s. name( db) ?) ,
418
448
} ,
419
- ModuleDef :: Trait ( t) => format ! ( "trait.{}.html" , t. name( db) ) ,
420
- ModuleDef :: TypeAlias ( t) => format ! ( "type.{}.html" , t. name( db) ) ,
421
- ModuleDef :: BuiltinType ( t) => format ! ( "primitive.{}.html" , t. name( ) ) ,
422
- ModuleDef :: Function ( f) => format ! ( "fn.{}.html" , f. name( db) ) ,
423
- ModuleDef :: Variant ( ev) => {
424
- format ! ( "enum.{}.html#variant.{}" , ev. parent_enum( db) . name( db) , ev. name( db) )
425
- }
426
- ModuleDef :: Const ( c) => format ! ( "const.{}.html" , c. name( db) ?) ,
427
- ModuleDef :: Static ( s) => format ! ( "static.{}.html" , s. name( db) ?) ,
428
- } )
449
+ Either :: Right ( mac) => format ! ( "macro.{}.html" , mac. name( db) ?) ,
450
+ } ;
451
+ Some ( res)
429
452
}
430
453
431
454
/// Get the fragment required to link to a specific field, method, associated type, or associated constant.
0 commit comments