Fix standard library doclinks not going to the correct page

This commit is contained in:
Lukas Wirth 2021-10-20 16:21:33 +02:00
parent 5051717856
commit 8ed86fc25d
3 changed files with 103 additions and 55 deletions

View file

@ -120,6 +120,15 @@ pub struct CrateDisplayName {
canonical_name: String, 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<CrateName> for CrateDisplayName { impl From<CrateName> for CrateDisplayName {
fn from(crate_name: CrateName) -> CrateDisplayName { fn from(crate_name: CrateName) -> CrateDisplayName {
let canonical_name = crate_name.to_string(); let canonical_name = crate_name.to_string();

View file

@ -467,17 +467,24 @@ fn map_links<'e>(
/// ``` /// ```
fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> { fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
let display_name = krate.display_name(db)?; let display_name = krate.display_name(db)?;
krate let base = match &**display_name.crate_name() {
.get_html_root_url(db) // std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
.or_else(|| { // 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 // Fallback to docs.rs. This uses `display_name` and can never be
// correct, but that's what fallbacks are about. // correct, but that's what fallbacks are about.
// //
// FIXME: clicking on the link should just open the file in the editor, // FIXME: clicking on the link should just open the file in the editor,
// instead of falling back to external urls. // instead of falling back to external urls.
Some(format!("https://docs.rs/{krate}/*/", krate = display_name)) Some(format!("https://docs.rs/{krate}/*/", krate = display_name))
}) })?
.and_then(|s| Url::parse(&s).ok()?.join(&format!("{}/", display_name)).ok()) }
};
Url::parse(&base).ok()?.join(&format!("{}/", display_name)).ok()
} }
/// Get the filename and extension generated for a symbol by rustdoc. /// Get the filename and extension generated for a symbol by rustdoc.
@ -555,12 +562,23 @@ mod tests {
fn external_docs_doc_url_crate() { fn external_docs_doc_url_crate() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:main deps:test //- /main.rs crate:main deps:foo
use test$0::Foo; use foo$0::Foo;
//- /lib.rs crate:test //- /lib.rs crate:foo
pub struct 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() { fn external_docs_doc_url_struct() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Fo$0o; 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() { fn external_docs_doc_url_struct_field() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo { pub struct Foo {
field$0: () 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() { fn external_docs_doc_url_fn() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub fn fo$0o() {} 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() { fn external_docs_doc_url_impl_assoc() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo; pub struct Foo;
impl Foo { impl Foo {
pub fn method$0() {} 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( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo; pub struct Foo;
impl Foo { impl Foo {
const CONST$0: () = (); 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() { fn external_docs_doc_url_impl_trait_assoc() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo; pub struct Foo;
pub trait Trait { pub trait Trait {
fn method() {} fn method() {}
@ -630,10 +654,11 @@ impl Trait for Foo {
pub fn method$0() {} 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( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo; pub struct Foo;
pub trait Trait { pub trait Trait {
const CONST: () = (); const CONST: () = ();
@ -642,10 +667,11 @@ impl Trait for Foo {
const CONST$0: () = (); 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( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub struct Foo; pub struct Foo;
pub trait Trait { pub trait Trait {
type Type; type Type;
@ -654,7 +680,7 @@ impl Trait for Foo {
type Type$0 = (); 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() { fn external_docs_doc_url_trait_assoc() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub trait Foo { pub trait Foo {
fn method$0(); 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( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub trait Foo { pub trait Foo {
const CONST$0: (); 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( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub trait Foo { pub trait Foo {
type Type$0; 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() { fn external_docs_trait() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
trait Trait$0 {} 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() { fn external_docs_module() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub mod foo { pub mod foo {
pub mod ba$0r {} 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() { fn external_docs_reexport_order() {
check_external_docs( check_external_docs(
r#" r#"
//- /main.rs crate:foo
pub mod wrapper { pub mod wrapper {
pub use module::Item; pub use module::Item;
@ -724,7 +756,7 @@ fn foo() {
let bar: wrapper::It$0em; 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() { fn rewrite_html_root_url() {
check_rewrite( check_rewrite(
r#" r#"
//- /main.rs crate:foo
#![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)] #![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)]
pub mod foo { pub mod foo {
@ -761,7 +794,7 @@ pub mod foo {
/// [Foo](foo::Foo) /// [Foo](foo::Foo)
pub struct B$0ar 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) // [Foo](https://docs.rs/test/*/test/struct.Foo.html)
check_rewrite( check_rewrite(
r#" r#"
//- /main.rs crate:foo
pub struct Foo { pub struct Foo {
/// [Foo](struct.Foo.html) /// [Foo](struct.Foo.html)
fie$0ld: () fie$0ld: ()
@ -784,40 +818,45 @@ pub struct Foo {
fn rewrite_struct() { fn rewrite_struct() {
check_rewrite( check_rewrite(
r#" r#"
//- /main.rs crate:foo
/// [Foo] /// [Foo]
pub struct $0Foo; 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( check_rewrite(
r#" r#"
//- /main.rs crate:foo
/// [`Foo`] /// [`Foo`]
pub struct $0Foo; 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( check_rewrite(
r#" r#"
//- /main.rs crate:foo
/// [Foo](struct.Foo.html) /// [Foo](struct.Foo.html)
pub struct $0Foo; 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( check_rewrite(
r#" r#"
//- /main.rs crate:foo
/// [struct Foo](struct.Foo.html) /// [struct Foo](struct.Foo.html)
pub struct $0Foo; 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( check_rewrite(
r#" r#"
//- /main.rs crate:foo
/// [my Foo][foo] /// [my Foo][foo]
/// ///
/// [foo]: Foo /// [foo]: Foo
pub struct $0Foo; 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)"#]],
); );
} }

View file

@ -4137,7 +4137,7 @@ foo_macro!(
--- ---
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)
"#]], "#]],
); );
} }
@ -4162,7 +4162,7 @@ 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)
"#]], "#]],
); );
} }