From 8ed86fc25d389632792f064f08183b3229328208 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 20 Oct 2021 16:21:33 +0200 Subject: [PATCH] Fix standard library doclinks not going to the correct page --- crates/base_db/src/input.rs | 9 +++ crates/ide/src/doc_links.rs | 109 +++++++++++++++++++++++----------- crates/ide/src/hover/tests.rs | 40 ++++++------- 3 files changed, 103 insertions(+), 55 deletions(-) diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 1dd7783b0e..63b2691154 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs @@ -120,6 +120,15 @@ pub struct CrateDisplayName { canonical_name: String, } +impl CrateDisplayName { + pub fn canonical_name(&self) -> &str { + &self.canonical_name + } + pub fn crate_name(&self) -> &CrateName { + &self.crate_name + } +} + impl From for CrateDisplayName { fn from(crate_name: CrateName) -> CrateDisplayName { let canonical_name = crate_name.to_string(); diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 41557ca1d9..3b7a2c8b5f 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -467,17 +467,24 @@ fn map_links<'e>( /// ``` fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option { let display_name = krate.display_name(db)?; - krate - .get_html_root_url(db) - .or_else(|| { - // Fallback to docs.rs. This uses `display_name` and can never be - // correct, but that's what fallbacks are about. - // - // FIXME: clicking on the link should just open the file in the editor, - // instead of falling back to external urls. - Some(format!("https://docs.rs/{krate}/*/", krate = display_name)) - }) - .and_then(|s| Url::parse(&s).ok()?.join(&format!("{}/", display_name)).ok()) + let base = match &**display_name.crate_name() { + // std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself. + // FIXME: Use the toolchains channel instead of nightly + name @ ("core" | "std" | "alloc" | "proc_macro" | "test") => { + format!("https://doc.rust-lang.org/nightly/{}", name) + } + _ => { + krate.get_html_root_url(db).or_else(|| { + // Fallback to docs.rs. This uses `display_name` and can never be + // correct, but that's what fallbacks are about. + // + // FIXME: clicking on the link should just open the file in the editor, + // instead of falling back to external urls. + Some(format!("https://docs.rs/{krate}/*/", krate = display_name)) + })? + } + }; + Url::parse(&base).ok()?.join(&format!("{}/", display_name)).ok() } /// Get the filename and extension generated for a symbol by rustdoc. @@ -555,12 +562,23 @@ mod tests { fn external_docs_doc_url_crate() { check_external_docs( r#" -//- /main.rs crate:main deps:test -use test$0::Foo; -//- /lib.rs crate:test +//- /main.rs crate:main deps:foo +use foo$0::Foo; +//- /lib.rs crate:foo pub struct Foo; "#, - expect![[r#"https://docs.rs/test/*/test/index.html"#]], + expect![[r#"https://docs.rs/foo/*/foo/index.html"#]], + ); + } + + #[test] + fn external_docs_doc_url_std_crate() { + check_external_docs( + r#" +//- /main.rs crate:std +use self$0; +"#, + expect![[r#"https://doc.rust-lang.org/nightly/std/index.html"#]], ); } @@ -568,9 +586,10 @@ pub struct Foo; fn external_docs_doc_url_struct() { check_external_docs( r#" +//- /main.rs crate:foo pub struct Fo$0o; "#, - expect![[r#"https://docs.rs/test/*/test/struct.Foo.html"#]], + expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]], ); } @@ -578,11 +597,12 @@ pub struct Fo$0o; fn external_docs_doc_url_struct_field() { check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo { field$0: () } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#structfield.field"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#structfield.field"##]], ); } @@ -590,9 +610,10 @@ pub struct Foo { fn external_docs_doc_url_fn() { check_external_docs( r#" +//- /main.rs crate:foo pub fn fo$0o() {} "#, - expect![[r##"https://docs.rs/test/*/test/fn.foo.html"##]], + expect![[r#"https://docs.rs/foo/*/foo/fn.foo.html"#]], ); } @@ -600,21 +621,23 @@ pub fn fo$0o() {} fn external_docs_doc_url_impl_assoc() { check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo; impl Foo { pub fn method$0() {} } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#method.method"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]], ); check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo; impl Foo { const CONST$0: () = (); } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedconstant.CONST"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]], ); } @@ -622,6 +645,7 @@ impl Foo { fn external_docs_doc_url_impl_trait_assoc() { check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo; pub trait Trait { fn method() {} @@ -630,10 +654,11 @@ impl Trait for Foo { pub fn method$0() {} } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#method.method"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]], ); check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo; pub trait Trait { const CONST: () = (); @@ -642,10 +667,11 @@ impl Trait for Foo { const CONST$0: () = (); } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedconstant.CONST"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]], ); check_external_docs( r#" +//- /main.rs crate:foo pub struct Foo; pub trait Trait { type Type; @@ -654,7 +680,7 @@ impl Trait for Foo { type Type$0 = (); } "#, - expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedtype.Type"##]], + expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedtype.Type"##]], ); } @@ -662,27 +688,30 @@ impl Trait for Foo { fn external_docs_doc_url_trait_assoc() { check_external_docs( r#" +//- /main.rs crate:foo pub trait Foo { fn method$0(); } "#, - expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#tymethod.method"##]], + expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#tymethod.method"##]], ); check_external_docs( r#" +//- /main.rs crate:foo pub trait Foo { const CONST$0: (); } "#, - expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#associatedconstant.CONST"##]], + expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedconstant.CONST"##]], ); check_external_docs( r#" +//- /main.rs crate:foo pub trait Foo { type Type$0; } "#, - expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#associatedtype.Type"##]], + expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedtype.Type"##]], ); } @@ -690,9 +719,10 @@ pub trait Foo { fn external_docs_trait() { check_external_docs( r#" +//- /main.rs crate:foo trait Trait$0 {} "#, - expect![[r#"https://docs.rs/test/*/test/trait.Trait.html"#]], + expect![[r#"https://docs.rs/foo/*/foo/trait.Trait.html"#]], ) } @@ -700,11 +730,12 @@ trait Trait$0 {} fn external_docs_module() { check_external_docs( r#" +//- /main.rs crate:foo pub mod foo { pub mod ba$0r {} } "#, - expect![[r#"https://docs.rs/test/*/test/foo/bar/index.html"#]], + expect![[r#"https://docs.rs/foo/*/foo/foo/bar/index.html"#]], ) } @@ -712,6 +743,7 @@ pub mod foo { fn external_docs_reexport_order() { check_external_docs( r#" +//- /main.rs crate:foo pub mod wrapper { pub use module::Item; @@ -724,7 +756,7 @@ fn foo() { let bar: wrapper::It$0em; } "#, - expect![[r#"https://docs.rs/test/*/test/wrapper/module/struct.Item.html"#]], + expect![[r#"https://docs.rs/foo/*/foo/wrapper/module/struct.Item.html"#]], ) } @@ -753,6 +785,7 @@ trait Trait$0 { fn rewrite_html_root_url() { check_rewrite( r#" +//- /main.rs crate:foo #![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)] pub mod foo { @@ -761,7 +794,7 @@ pub mod foo { /// [Foo](foo::Foo) pub struct B$0ar "#, - expect![[r#"[Foo](https://example.com/test/foo/struct.Foo.html)"#]], + expect![[r#"[Foo](https://example.com/foo/foo/struct.Foo.html)"#]], ); } @@ -771,6 +804,7 @@ pub struct B$0ar // [Foo](https://docs.rs/test/*/test/struct.Foo.html) check_rewrite( r#" +//- /main.rs crate:foo pub struct Foo { /// [Foo](struct.Foo.html) fie$0ld: () @@ -784,40 +818,45 @@ pub struct Foo { fn rewrite_struct() { check_rewrite( r#" +//- /main.rs crate:foo /// [Foo] pub struct $0Foo; "#, - expect![[r#"[Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]], + expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]], ); check_rewrite( r#" +//- /main.rs crate:foo /// [`Foo`] pub struct $0Foo; "#, - expect![[r#"[`Foo`](https://docs.rs/test/*/test/struct.Foo.html)"#]], + expect![[r#"[`Foo`](https://docs.rs/foo/*/foo/struct.Foo.html)"#]], ); check_rewrite( r#" +//- /main.rs crate:foo /// [Foo](struct.Foo.html) pub struct $0Foo; "#, - expect![[r#"[Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]], + expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]], ); check_rewrite( r#" +//- /main.rs crate:foo /// [struct Foo](struct.Foo.html) pub struct $0Foo; "#, - expect![[r#"[struct Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]], + expect![[r#"[struct Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]], ); check_rewrite( r#" +//- /main.rs crate:foo /// [my Foo][foo] /// /// [foo]: Foo pub struct $0Foo; "#, - expect![[r#"[my Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]], + expect![[r#"[my Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]], ); } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 463cd58e48..e684b77c4f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -4125,20 +4125,20 @@ foo_macro!( ); "#, expect![[r#" - *[`Foo`]* + *[`Foo`]* - ```rust - test - ``` + ```rust + test + ``` - ```rust - pub struct Foo - ``` + ```rust + pub struct Foo + ``` - --- + --- - Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html) - "#]], + Doc comment for [`Foo`](https://doc.rust-lang.org/nightly/test/struct.Foo.html) + "#]], ); } @@ -4150,19 +4150,19 @@ fn hover_intra_in_attr() { pub struct Foo; "#, expect![[r#" - *[`Foo`]* + *[`Foo`]* - ```rust - test - ``` + ```rust + test + ``` - ```rust - pub struct Foo - ``` + ```rust + pub struct Foo + ``` - --- + --- - Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html) - "#]], + Doc comment for [`Foo`](https://doc.rust-lang.org/nightly/test/struct.Foo.html) + "#]], ); }