@@ -108,13 +108,13 @@ pub(crate) fn external_docs(
108108 let node = token. parent ( ) ?;
109109 let definition = match_ast ! {
110110 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 ,
114114 }
115115 } ;
116116
117- get_doc_link ( db, definition? )
117+ get_doc_link ( db, definition)
118118}
119119
120120/// 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
214214// This should cease to be a problem if RFC2988 (Stable Rustdoc URLs) is implemented
215215// https://github.com/rust-lang/rfcs/pull/2988
216216fn 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,
218218 // then we can join the method, field, etc onto it if required.
219219 let target_def: ModuleDef = match definition {
220- Definition :: ModuleDef ( moddef ) => match moddef {
220+ Definition :: ModuleDef ( def ) => match def {
221221 ModuleDef :: Function ( f) => f
222222 . as_assoc_item ( db)
223223 . and_then ( |assoc| match assoc. container ( db) {
224224 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 ( ) )
227227 }
228228 } )
229- . unwrap_or_else ( || f . clone ( ) . into ( ) ) ,
230- moddef => moddef ,
229+ . unwrap_or_else ( || def ) ,
230+ def => def ,
231231 } ,
232232 Definition :: Field ( f) => f. parent_def ( db) . into ( ) ,
233233 // FIXME: Handle macros
@@ -236,17 +236,28 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
236236
237237 let ns = ItemInNs :: from ( target_def) ;
238238
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+ } ;
241244 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 += "/" ;
246257
247258 let filename = get_symbol_filename ( db, & target_def) ;
248259 let fragment = match definition {
249- Definition :: ModuleDef ( moddef ) => match moddef {
260+ Definition :: ModuleDef ( def ) => match def {
250261 ModuleDef :: Function ( f) => {
251262 get_symbol_fragment ( db, & FieldOrAssocItem :: AssocItem ( AssocItem :: Function ( f) ) )
252263 }
@@ -532,6 +543,19 @@ mod tests {
532543 expect. assert_eq ( & url)
533544 }
534545
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+
535559 #[ test]
536560 fn test_doc_url_struct ( ) {
537561 check (
0 commit comments