diff options
-rw-r--r-- | crates/ide/src/doc_links.rs | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 0608c2ac6..b9d53bcd4 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -112,6 +112,7 @@ pub fn get_doc_link<T: Resolvable + Clone>(db: &dyn HirDatabase, definition: &T) | |||
112 | // version of import map which follows the same process as rustdoc. Otherwise there'll always be some | 112 | // version of import map which follows the same process as rustdoc. Otherwise there'll always be some |
113 | // edge cases where we select the wrong import path. | 113 | // edge cases where we select the wrong import path. |
114 | fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | 114 | fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { |
115 | eprintln!("enter"); | ||
115 | // Get the outermost definition for the moduledef. This is used to resolve the public path to the type, | 116 | // Get the outermost definition for the moduledef. This is used to resolve the public path to the type, |
116 | // then we can join the method, field, etc onto it if required. | 117 | // then we can join the method, field, etc onto it if required. |
117 | let target_def: ModuleDef = match definition { | 118 | let target_def: ModuleDef = match definition { |
@@ -131,8 +132,8 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | |||
131 | let module = definition.module(db)?; | 132 | let module = definition.module(db)?; |
132 | let krate = module.krate(); | 133 | let krate = module.krate(); |
133 | let import_map = db.import_map(krate.into()); | 134 | let import_map = db.import_map(krate.into()); |
134 | let base = once(krate.display_name(db).unwrap()) | 135 | let base = once(krate.display_name(db)?) |
135 | .chain(import_map.path_of(ns).unwrap().segments.iter().map(|name| format!("{}", name))) | 136 | .chain(import_map.path_of(ns)?.segments.iter().map(|name| format!("{}", name))) |
136 | .join("/"); | 137 | .join("/"); |
137 | 138 | ||
138 | let filename = get_symbol_filename(db, &target_def); | 139 | let filename = get_symbol_filename(db, &target_def); |
@@ -152,6 +153,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | |||
152 | Definition::Field(field) => get_symbol_fragment(db, &FieldOrAssocItem::Field(field)), | 153 | Definition::Field(field) => get_symbol_fragment(db, &FieldOrAssocItem::Field(field)), |
153 | _ => None, | 154 | _ => None, |
154 | }; | 155 | }; |
156 | eprintln!("end-ish"); | ||
155 | 157 | ||
156 | get_doc_url(db, &krate) | 158 | get_doc_url(db, &krate) |
157 | .and_then(|url| url.join(&base).ok()) | 159 | .and_then(|url| url.join(&base).ok()) |
@@ -430,3 +432,93 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
430 | } | 432 | } |
431 | } | 433 | } |
432 | } | 434 | } |
435 | |||
436 | #[cfg(test)] | ||
437 | mod tests { | ||
438 | use expect_test::{expect, Expect}; | ||
439 | |||
440 | use crate::mock_analysis::analysis_and_position; | ||
441 | |||
442 | fn check(ra_fixture: &str, expect: Expect) { | ||
443 | let (analysis, position) = analysis_and_position(ra_fixture); | ||
444 | let url = analysis.external_docs(position).unwrap().unwrap(); | ||
445 | |||
446 | expect.assert_eq(&url) | ||
447 | } | ||
448 | |||
449 | #[test] | ||
450 | fn test_doc_url_struct() { | ||
451 | check( | ||
452 | r#" | ||
453 | pub struct Fo<|>o; | ||
454 | "#, | ||
455 | expect![[r#"https://docs.rs/test/*/test/struct.Foo.html"#]], | ||
456 | ); | ||
457 | } | ||
458 | |||
459 | // TODO: Fix this test. Fails on `import_map.path_of(ns)` | ||
460 | #[test] | ||
461 | fn test_doc_url_fn() { | ||
462 | check( | ||
463 | r#" | ||
464 | pub fn fo<|>o() {} | ||
465 | "#, | ||
466 | expect![[r#""#]], | ||
467 | ); | ||
468 | } | ||
469 | |||
470 | #[test] | ||
471 | fn test_doc_url_inherent_method() { | ||
472 | check( | ||
473 | r#" | ||
474 | pub struct Foo; | ||
475 | |||
476 | impl Foo { | ||
477 | pub fn met<|>hod() {} | ||
478 | } | ||
479 | |||
480 | "#, | ||
481 | expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#method.method"##]], | ||
482 | ); | ||
483 | } | ||
484 | |||
485 | #[test] | ||
486 | fn test_doc_url_trait_provided_method() { | ||
487 | check( | ||
488 | r#" | ||
489 | pub trait Bar { | ||
490 | fn met<|>hod() {} | ||
491 | } | ||
492 | |||
493 | "#, | ||
494 | expect![[r##"https://docs.rs/test/*/test/trait.Bar.html#method.method"##]], | ||
495 | ); | ||
496 | } | ||
497 | |||
498 | #[test] | ||
499 | fn test_doc_url_trait_required_method() { | ||
500 | check( | ||
501 | r#" | ||
502 | pub trait Foo { | ||
503 | fn met<|>hod(); | ||
504 | } | ||
505 | |||
506 | "#, | ||
507 | expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#tymethod.method"##]], | ||
508 | ); | ||
509 | } | ||
510 | |||
511 | |||
512 | #[test] | ||
513 | fn test_doc_url_field() { | ||
514 | check( | ||
515 | r#" | ||
516 | pub struct Foo { | ||
517 | pub fie<|>ld: () | ||
518 | } | ||
519 | |||
520 | "#, | ||
521 | expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#structfield.field"##]], | ||
522 | ); | ||
523 | } | ||
524 | } | ||