@@ -108,13 +108,13 @@ pub(crate) fn external_docs(
108
108
let node = token. parent ( ) ?;
109
109
let definition = match_ast ! {
110
110
match node {
111
- ast:: NameRef ( name_ref) => NameRefClass :: classify( & sema, & name_ref) . map( |d| d. referenced( sema. db) ) ,
112
- ast:: Name ( name) => NameClass :: classify( & sema, & name) . map( |d| d. referenced_or_defined( sema. db) ) ,
113
- _ => None ,
111
+ ast:: NameRef ( name_ref) => NameRefClass :: classify( & sema, & name_ref) . map( |d| d. referenced( sema. db) ) ? ,
112
+ ast:: Name ( name) => NameClass :: classify( & sema, & name) . map( |d| d. referenced_or_defined( sema. db) ) ? ,
113
+ _ => return None ,
114
114
}
115
115
} ;
116
116
117
- get_doc_link ( db, definition? )
117
+ get_doc_link ( db, definition)
118
118
}
119
119
120
120
/// Extracts all links from a given markdown text.
@@ -214,20 +214,20 @@ fn broken_link_clone_cb<'a, 'b>(link: BrokenLink<'a>) -> Option<(CowStr<'b>, Cow
214
214
// This should cease to be a problem if RFC2988 (Stable Rustdoc URLs) is implemented
215
215
// https://github.com/rust-lang/rfcs/pull/2988
216
216
fn get_doc_link ( db : & RootDatabase , definition : Definition ) -> Option < String > {
217
- // Get the outermost definition for the moduledef . This is used to resolve the public path to the type,
217
+ // Get the outermost definition for the module def . This is used to resolve the public path to the type,
218
218
// then we can join the method, field, etc onto it if required.
219
219
let target_def: ModuleDef = match definition {
220
- Definition :: ModuleDef ( moddef ) => match moddef {
220
+ Definition :: ModuleDef ( def ) => match def {
221
221
ModuleDef :: Function ( f) => f
222
222
. as_assoc_item ( db)
223
223
. and_then ( |assoc| match assoc. container ( db) {
224
224
AssocItemContainer :: Trait ( t) => Some ( t. into ( ) ) ,
225
- AssocItemContainer :: Impl ( impld ) => {
226
- impld . self_ty ( db) . as_adt ( ) . map ( |adt| adt. into ( ) )
225
+ AssocItemContainer :: Impl ( impl_ ) => {
226
+ impl_ . self_ty ( db) . as_adt ( ) . map ( |adt| adt. into ( ) )
227
227
}
228
228
} )
229
- . unwrap_or_else ( || f . clone ( ) . into ( ) ) ,
230
- moddef => moddef ,
229
+ . unwrap_or_else ( || def ) ,
230
+ def => def ,
231
231
} ,
232
232
Definition :: Field ( f) => f. parent_def ( db) . into ( ) ,
233
233
// FIXME: Handle macros
@@ -236,17 +236,28 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
236
236
237
237
let ns = ItemInNs :: from ( target_def) ;
238
238
239
- let module = definition. module ( db) ?;
240
- let krate = module. krate ( ) ;
239
+ let krate = match definition {
240
+ // Definition::module gives back the parent module, we don't want that as it fails for root modules
241
+ Definition :: ModuleDef ( ModuleDef :: Module ( module) ) => module. krate ( ) ,
242
+ _ => definition. module ( db) ?. krate ( ) ,
243
+ } ;
241
244
let import_map = db. import_map ( krate. into ( ) ) ;
242
- let base = once ( krate. display_name ( db) ?. to_string ( ) )
243
- . chain ( import_map. path_of ( ns) ?. segments . iter ( ) . map ( |name| name. to_string ( ) ) )
244
- . join ( "/" )
245
- + "/" ;
245
+
246
+ let mut base = krate. display_name ( db) ?. to_string ( ) ;
247
+ let is_root_module = matches ! (
248
+ definition,
249
+ Definition :: ModuleDef ( ModuleDef :: Module ( module) ) if krate. root_module( db) == module
250
+ ) ;
251
+ if !is_root_module {
252
+ base = once ( base)
253
+ . chain ( import_map. path_of ( ns) ?. segments . iter ( ) . map ( |name| name. to_string ( ) ) )
254
+ . join ( "/" ) ;
255
+ }
256
+ base += "/" ;
246
257
247
258
let filename = get_symbol_filename ( db, & target_def) ;
248
259
let fragment = match definition {
249
- Definition :: ModuleDef ( moddef ) => match moddef {
260
+ Definition :: ModuleDef ( def ) => match def {
250
261
ModuleDef :: Function ( f) => {
251
262
get_symbol_fragment ( db, & FieldOrAssocItem :: AssocItem ( AssocItem :: Function ( f) ) )
252
263
}
@@ -532,6 +543,19 @@ mod tests {
532
543
expect. assert_eq ( & url)
533
544
}
534
545
546
+ #[ test]
547
+ fn test_doc_url_crate ( ) {
548
+ check (
549
+ r#"
550
+ //- /main.rs crate:main deps:test
551
+ use test$0::Foo;
552
+ //- /lib.rs crate:test
553
+ pub struct Foo;
554
+ "# ,
555
+ expect ! [ [ r#"https://docs.rs/test/*/test/index.html"# ] ] ,
556
+ ) ;
557
+ }
558
+
535
559
#[ test]
536
560
fn test_doc_url_struct ( ) {
537
561
check (
0 commit comments