@@ -5,6 +5,8 @@ mod tests;
5
5
6
6
mod intra_doc_links;
7
7
8
+ use std:: ffi:: OsStr ;
9
+
8
10
use pulldown_cmark:: { BrokenLink , CowStr , Event , InlineStr , LinkType , Options , Parser , Tag } ;
9
11
use pulldown_cmark_to_cmark:: { cmark_resume_with_options, Options as CMarkOptions } ;
10
12
use stdx:: format_to;
@@ -127,7 +129,11 @@ pub(crate) fn remove_links(markdown: &str) -> String {
127
129
//
128
130
// | VS Code | **rust-analyzer: Open Docs**
129
131
// |===
130
- pub ( crate ) fn external_docs ( db : & RootDatabase , position : & FilePosition ) -> DocumentationLinks {
132
+ pub ( crate ) fn external_docs (
133
+ db : & RootDatabase ,
134
+ position : & FilePosition ,
135
+ target_dir : Option < & OsStr > ,
136
+ ) -> DocumentationLinks {
131
137
let sema = & Semantics :: new ( db) ;
132
138
let file = sema. parse ( position. file_id ) . syntax ( ) . clone ( ) ;
133
139
let token = pick_best_token ( file. token_at_offset ( position. offset ) , |kind| match kind {
@@ -158,7 +164,7 @@ pub(crate) fn external_docs(db: &RootDatabase, position: &FilePosition) -> Docum
158
164
}
159
165
} ;
160
166
161
- return get_doc_links ( db, definition) ;
167
+ return get_doc_links ( db, definition, target_dir ) ;
162
168
}
163
169
164
170
/// Extracts all links from a given markdown text returning the definition text range, link-text
@@ -316,10 +322,14 @@ fn broken_link_clone_cb(link: BrokenLink<'_>) -> Option<(CowStr<'_>, CowStr<'_>)
316
322
//
317
323
// This should cease to be a problem if RFC2988 (Stable Rustdoc URLs) is implemented
318
324
// https://github.com/rust-lang/rfcs/pull/2988
319
- fn get_doc_links ( db : & RootDatabase , def : Definition ) -> DocumentationLinks {
325
+ fn get_doc_links (
326
+ db : & RootDatabase ,
327
+ def : Definition ,
328
+ target_dir : Option < & OsStr > ,
329
+ ) -> DocumentationLinks {
320
330
let Some ( ( target, file, frag) ) = filename_and_frag_for_def ( db, def) else { return Default :: default ( ) ; } ;
321
331
322
- let ( mut web_url, mut local_url) = get_doc_base_urls ( db, target) ;
332
+ let ( mut web_url, mut local_url) = get_doc_base_urls ( db, target, target_dir ) ;
323
333
324
334
if let Some ( path) = mod_path_of_def ( db, target) {
325
335
web_url = join_url ( web_url, & path) ;
@@ -355,7 +365,7 @@ fn rewrite_intra_doc_link(
355
365
let ( link, ns) = parse_intra_doc_link ( target) ;
356
366
357
367
let resolved = resolve_doc_path_for_def ( db, def, link, ns) ?;
358
- let mut url = get_doc_base_urls ( db, resolved) . 0 ?;
368
+ let mut url = get_doc_base_urls ( db, resolved, None ) . 0 ?;
359
369
360
370
let ( _, file, frag) = filename_and_frag_for_def ( db, resolved) ?;
361
371
if let Some ( path) = mod_path_of_def ( db, resolved) {
@@ -374,7 +384,7 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
374
384
return None ;
375
385
}
376
386
377
- let mut url = get_doc_base_urls ( db, def) . 0 ?;
387
+ let mut url = get_doc_base_urls ( db, def, None ) . 0 ?;
378
388
let ( def, file, frag) = filename_and_frag_for_def ( db, def) ?;
379
389
380
390
if let Some ( path) = mod_path_of_def ( db, def) {
@@ -450,23 +460,23 @@ fn map_links<'e>(
450
460
/// https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
451
461
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^
452
462
/// ```
453
- fn get_doc_base_urls ( db : & RootDatabase , def : Definition ) -> ( Option < Url > , Option < Url > ) {
454
- // TODO: get this is from `CargoWorkspace`
455
- // TODO: get `CargoWorkspace` from `db`
456
- let target_path = "file:///project/root/target" ;
457
- let target_path = Url :: parse ( target_path ) . ok ( ) ;
458
- let local_doc_path = target_path . and_then ( |url| url . join ( "doc" ) . ok ( ) ) ;
459
- debug_assert ! ( local_doc_path . is_some ( ) , "failed to parse local doc path" ) ;
460
-
463
+ fn get_doc_base_urls (
464
+ db : & RootDatabase ,
465
+ def : Definition ,
466
+ target_dir : Option < & OsStr > ,
467
+ ) -> ( Option < Url > , Option < Url > ) {
468
+ let local_doc_path = target_dir
469
+ . and_then ( |it| Url :: from_directory_path ( it ) . ok ( ) )
470
+ . and_then ( |it| it . join ( "doc" ) . ok ( ) ) ;
461
471
// special case base url of `BuiltinType` to core
462
472
// https://github.com/rust-lang/rust-analyzer/issues/12250
463
473
if let Definition :: BuiltinType ( ..) = def {
464
474
let weblink = Url :: parse ( "https://doc.rust-lang.org/nightly/core/" ) . ok ( ) ;
465
475
return ( weblink, local_doc_path) ;
466
476
} ;
467
477
468
- let Some ( krate) = def. krate ( db) else { return Default :: default ( ) } ;
469
- let Some ( display_name) = krate. display_name ( db) else { return Default :: default ( ) } ;
478
+ let Some ( krate) = def. krate ( db) else { return ( None , local_doc_path ) } ;
479
+ let Some ( display_name) = krate. display_name ( db) else { return ( None , local_doc_path ) } ;
470
480
let crate_data = & db. crate_graph ( ) [ krate. into ( ) ] ;
471
481
let channel = crate_data. channel . map_or ( "nightly" , ReleaseChannel :: as_str) ;
472
482
let ( web_base, local_base) = match & crate_data. origin {
0 commit comments