Skip to content

Commit 8ed86fc

Browse files
committed
Fix standard library doclinks not going to the correct page
1 parent 5051717 commit 8ed86fc

File tree

3 files changed

+103
-55
lines changed

3 files changed

+103
-55
lines changed

crates/base_db/src/input.rs

+9
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ pub struct CrateDisplayName {
120120
canonical_name: String,
121121
}
122122

123+
impl CrateDisplayName {
124+
pub fn canonical_name(&self) -> &str {
125+
&self.canonical_name
126+
}
127+
pub fn crate_name(&self) -> &CrateName {
128+
&self.crate_name
129+
}
130+
}
131+
123132
impl From<CrateName> for CrateDisplayName {
124133
fn from(crate_name: CrateName) -> CrateDisplayName {
125134
let canonical_name = crate_name.to_string();

crates/ide/src/doc_links.rs

+74-35
Original file line numberDiff line numberDiff line change
@@ -467,17 +467,24 @@ fn map_links<'e>(
467467
/// ```
468468
fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
469469
let display_name = krate.display_name(db)?;
470-
krate
471-
.get_html_root_url(db)
472-
.or_else(|| {
473-
// Fallback to docs.rs. This uses `display_name` and can never be
474-
// correct, but that's what fallbacks are about.
475-
//
476-
// FIXME: clicking on the link should just open the file in the editor,
477-
// instead of falling back to external urls.
478-
Some(format!("https://docs.rs/{krate}/*/", krate = display_name))
479-
})
480-
.and_then(|s| Url::parse(&s).ok()?.join(&format!("{}/", display_name)).ok())
470+
let base = match &**display_name.crate_name() {
471+
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
472+
// FIXME: Use the toolchains channel instead of nightly
473+
name @ ("core" | "std" | "alloc" | "proc_macro" | "test") => {
474+
format!("https://doc.rust-lang.org/nightly/{}", name)
475+
}
476+
_ => {
477+
krate.get_html_root_url(db).or_else(|| {
478+
// Fallback to docs.rs. This uses `display_name` and can never be
479+
// correct, but that's what fallbacks are about.
480+
//
481+
// FIXME: clicking on the link should just open the file in the editor,
482+
// instead of falling back to external urls.
483+
Some(format!("https://docs.rs/{krate}/*/", krate = display_name))
484+
})?
485+
}
486+
};
487+
Url::parse(&base).ok()?.join(&format!("{}/", display_name)).ok()
481488
}
482489

483490
/// Get the filename and extension generated for a symbol by rustdoc.
@@ -555,73 +562,90 @@ mod tests {
555562
fn external_docs_doc_url_crate() {
556563
check_external_docs(
557564
r#"
558-
//- /main.rs crate:main deps:test
559-
use test$0::Foo;
560-
//- /lib.rs crate:test
565+
//- /main.rs crate:main deps:foo
566+
use foo$0::Foo;
567+
//- /lib.rs crate:foo
561568
pub struct Foo;
562569
"#,
563-
expect![[r#"https://docs.rs/test/*/test/index.html"#]],
570+
expect![[r#"https://docs.rs/foo/*/foo/index.html"#]],
571+
);
572+
}
573+
574+
#[test]
575+
fn external_docs_doc_url_std_crate() {
576+
check_external_docs(
577+
r#"
578+
//- /main.rs crate:std
579+
use self$0;
580+
"#,
581+
expect![[r#"https://doc.rust-lang.org/nightly/std/index.html"#]],
564582
);
565583
}
566584

567585
#[test]
568586
fn external_docs_doc_url_struct() {
569587
check_external_docs(
570588
r#"
589+
//- /main.rs crate:foo
571590
pub struct Fo$0o;
572591
"#,
573-
expect![[r#"https://docs.rs/test/*/test/struct.Foo.html"#]],
592+
expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]],
574593
);
575594
}
576595

577596
#[test]
578597
fn external_docs_doc_url_struct_field() {
579598
check_external_docs(
580599
r#"
600+
//- /main.rs crate:foo
581601
pub struct Foo {
582602
field$0: ()
583603
}
584604
"#,
585-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#structfield.field"##]],
605+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#structfield.field"##]],
586606
);
587607
}
588608

589609
#[test]
590610
fn external_docs_doc_url_fn() {
591611
check_external_docs(
592612
r#"
613+
//- /main.rs crate:foo
593614
pub fn fo$0o() {}
594615
"#,
595-
expect![[r##"https://docs.rs/test/*/test/fn.foo.html"##]],
616+
expect![[r#"https://docs.rs/foo/*/foo/fn.foo.html"#]],
596617
);
597618
}
598619

599620
#[test]
600621
fn external_docs_doc_url_impl_assoc() {
601622
check_external_docs(
602623
r#"
624+
//- /main.rs crate:foo
603625
pub struct Foo;
604626
impl Foo {
605627
pub fn method$0() {}
606628
}
607629
"#,
608-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#method.method"##]],
630+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
609631
);
610632
check_external_docs(
611633
r#"
634+
//- /main.rs crate:foo
612635
pub struct Foo;
613636
impl Foo {
614637
const CONST$0: () = ();
615638
}
616639
"#,
617-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedconstant.CONST"##]],
640+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
618641
);
619642
}
620643

621644
#[test]
622645
fn external_docs_doc_url_impl_trait_assoc() {
623646
check_external_docs(
624647
r#"
648+
//- /main.rs crate:foo
625649
pub struct Foo;
626650
pub trait Trait {
627651
fn method() {}
@@ -630,10 +654,11 @@ impl Trait for Foo {
630654
pub fn method$0() {}
631655
}
632656
"#,
633-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#method.method"##]],
657+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
634658
);
635659
check_external_docs(
636660
r#"
661+
//- /main.rs crate:foo
637662
pub struct Foo;
638663
pub trait Trait {
639664
const CONST: () = ();
@@ -642,10 +667,11 @@ impl Trait for Foo {
642667
const CONST$0: () = ();
643668
}
644669
"#,
645-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedconstant.CONST"##]],
670+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
646671
);
647672
check_external_docs(
648673
r#"
674+
//- /main.rs crate:foo
649675
pub struct Foo;
650676
pub trait Trait {
651677
type Type;
@@ -654,64 +680,70 @@ impl Trait for Foo {
654680
type Type$0 = ();
655681
}
656682
"#,
657-
expect![[r##"https://docs.rs/test/*/test/struct.Foo.html#associatedtype.Type"##]],
683+
expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedtype.Type"##]],
658684
);
659685
}
660686

661687
#[test]
662688
fn external_docs_doc_url_trait_assoc() {
663689
check_external_docs(
664690
r#"
691+
//- /main.rs crate:foo
665692
pub trait Foo {
666693
fn method$0();
667694
}
668695
"#,
669-
expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#tymethod.method"##]],
696+
expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#tymethod.method"##]],
670697
);
671698
check_external_docs(
672699
r#"
700+
//- /main.rs crate:foo
673701
pub trait Foo {
674702
const CONST$0: ();
675703
}
676704
"#,
677-
expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#associatedconstant.CONST"##]],
705+
expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedconstant.CONST"##]],
678706
);
679707
check_external_docs(
680708
r#"
709+
//- /main.rs crate:foo
681710
pub trait Foo {
682711
type Type$0;
683712
}
684713
"#,
685-
expect![[r##"https://docs.rs/test/*/test/trait.Foo.html#associatedtype.Type"##]],
714+
expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedtype.Type"##]],
686715
);
687716
}
688717

689718
#[test]
690719
fn external_docs_trait() {
691720
check_external_docs(
692721
r#"
722+
//- /main.rs crate:foo
693723
trait Trait$0 {}
694724
"#,
695-
expect![[r#"https://docs.rs/test/*/test/trait.Trait.html"#]],
725+
expect![[r#"https://docs.rs/foo/*/foo/trait.Trait.html"#]],
696726
)
697727
}
698728

699729
#[test]
700730
fn external_docs_module() {
701731
check_external_docs(
702732
r#"
733+
//- /main.rs crate:foo
703734
pub mod foo {
704735
pub mod ba$0r {}
705736
}
706737
"#,
707-
expect![[r#"https://docs.rs/test/*/test/foo/bar/index.html"#]],
738+
expect![[r#"https://docs.rs/foo/*/foo/foo/bar/index.html"#]],
708739
)
709740
}
710741

711742
#[test]
712743
fn external_docs_reexport_order() {
713744
check_external_docs(
714745
r#"
746+
//- /main.rs crate:foo
715747
pub mod wrapper {
716748
pub use module::Item;
717749
@@ -724,7 +756,7 @@ fn foo() {
724756
let bar: wrapper::It$0em;
725757
}
726758
"#,
727-
expect![[r#"https://docs.rs/test/*/test/wrapper/module/struct.Item.html"#]],
759+
expect![[r#"https://docs.rs/foo/*/foo/wrapper/module/struct.Item.html"#]],
728760
)
729761
}
730762

@@ -753,6 +785,7 @@ trait Trait$0 {
753785
fn rewrite_html_root_url() {
754786
check_rewrite(
755787
r#"
788+
//- /main.rs crate:foo
756789
#![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)]
757790
758791
pub mod foo {
@@ -761,7 +794,7 @@ pub mod foo {
761794
/// [Foo](foo::Foo)
762795
pub struct B$0ar
763796
"#,
764-
expect![[r#"[Foo](https://example.com/test/foo/struct.Foo.html)"#]],
797+
expect![[r#"[Foo](https://example.com/foo/foo/struct.Foo.html)"#]],
765798
);
766799
}
767800

@@ -771,6 +804,7 @@ pub struct B$0ar
771804
// [Foo](https://docs.rs/test/*/test/struct.Foo.html)
772805
check_rewrite(
773806
r#"
807+
//- /main.rs crate:foo
774808
pub struct Foo {
775809
/// [Foo](struct.Foo.html)
776810
fie$0ld: ()
@@ -784,40 +818,45 @@ pub struct Foo {
784818
fn rewrite_struct() {
785819
check_rewrite(
786820
r#"
821+
//- /main.rs crate:foo
787822
/// [Foo]
788823
pub struct $0Foo;
789824
"#,
790-
expect![[r#"[Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]],
825+
expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
791826
);
792827
check_rewrite(
793828
r#"
829+
//- /main.rs crate:foo
794830
/// [`Foo`]
795831
pub struct $0Foo;
796832
"#,
797-
expect![[r#"[`Foo`](https://docs.rs/test/*/test/struct.Foo.html)"#]],
833+
expect![[r#"[`Foo`](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
798834
);
799835
check_rewrite(
800836
r#"
837+
//- /main.rs crate:foo
801838
/// [Foo](struct.Foo.html)
802839
pub struct $0Foo;
803840
"#,
804-
expect![[r#"[Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]],
841+
expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
805842
);
806843
check_rewrite(
807844
r#"
845+
//- /main.rs crate:foo
808846
/// [struct Foo](struct.Foo.html)
809847
pub struct $0Foo;
810848
"#,
811-
expect![[r#"[struct Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]],
849+
expect![[r#"[struct Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
812850
);
813851
check_rewrite(
814852
r#"
853+
//- /main.rs crate:foo
815854
/// [my Foo][foo]
816855
///
817856
/// [foo]: Foo
818857
pub struct $0Foo;
819858
"#,
820-
expect![[r#"[my Foo](https://docs.rs/test/*/test/struct.Foo.html)"#]],
859+
expect![[r#"[my Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
821860
);
822861
}
823862

0 commit comments

Comments
 (0)