/// ```
fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
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.
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"#]],
);
}
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"#]],
);
}
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"##]],
);
}
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"#]],
);
}
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"##]],
);
}
fn external_docs_doc_url_impl_trait_assoc() {
check_external_docs(
r#"
+//- /main.rs crate:foo
pub struct Foo;
pub trait Trait {
fn method() {}
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: () = ();
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;
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"##]],
);
}
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"##]],
);
}
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"#]],
)
}
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"#]],
)
}
fn external_docs_reexport_order() {
check_external_docs(
r#"
+//- /main.rs crate:foo
pub mod wrapper {
pub use module::Item;
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"#]],
)
}
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 {
/// [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)"#]],
);
}
// [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: ()
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)"#]],
);
}