aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-06-27 02:32:46 +0100
committerZac Pullar-Strecker <[email protected]>2020-06-30 09:10:24 +0100
commit1833036daf6d2278df99f7b66aca24b2a66d8d2a (patch)
tree62cfbcf7d8539860f8118a5c35605a63a39d136d
parentf98e311617f66654b7799a966fc16b272438ed00 (diff)
Fix doc attr parsing, fixes links from std/core/alloc
-rw-r--r--crates/ra_ide/src/hover.rs32
1 files changed, 19 insertions, 13 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 185139250..8c972bb41 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -19,7 +19,7 @@ use ra_ide_db::{
19use ra_syntax::{ 19use ra_syntax::{
20 ast, ast::Path, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, TokenAtOffset, 20 ast, ast::Path, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, TokenAtOffset,
21}; 21};
22use ra_tt::{Ident, Leaf, Literal, Punct, TokenTree}; 22use ra_tt::{Ident, Leaf, Literal, TokenTree};
23use url::Url; 23use url::Url;
24 24
25use crate::{ 25use crate::{
@@ -410,6 +410,8 @@ fn map_links<'e>(
410 } 410 }
411 Event::Text(s) if in_link => { 411 Event::Text(s) if in_link => {
412 link_text = s.clone(); 412 link_text = s.clone();
413 // TODO: This can unintentionally strip words from path-based links.
414 // See std::box::Box -> std::box link as an example.
413 Event::Text(CowStr::Boxed(strip_prefixes_suffixes(&s).into())) 415 Event::Text(CowStr::Boxed(strip_prefixes_suffixes(&s).into()))
414 } 416 }
415 Event::Code(s) if in_link => { 417 Event::Code(s) if in_link => {
@@ -603,29 +605,33 @@ fn try_resolve_path(db: &RootDatabase, definition: &Definition, link: &str) -> O
603} 605}
604 606
605/// Try to get the root URL of the documentation of a crate. 607/// Try to get the root URL of the documentation of a crate.
606// FIXME: Special case standard, core, alloc libraries
607fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> { 608fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
608 // Look for #![doc(html_root_url = "...")] 609 // Look for #![doc(html_root_url = "...")]
609 let attrs = db.attrs(AttrDef::from(krate.root_module(db)?).into()); 610 let attrs = db.attrs(AttrDef::from(krate.root_module(db)?).into());
610 let doc_attr_q = attrs.by_key("doc"); 611 let doc_attr_q = attrs.by_key("doc");
612
613 // TODO: Tests for this parsing
611 let doc_url = if doc_attr_q.exists() { 614 let doc_url = if doc_attr_q.exists() {
612 doc_attr_q.tt_values().filter_map(|tt| match tt.token_trees.as_slice() { 615 doc_attr_q.tt_values().map(|tt| {
613 &[ 616 let name = tt.token_trees.iter()
614 TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident_text, ..})), 617 .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url"))
615 TokenTree::Leaf(Leaf::Punct(Punct{r#char: '=', ..})), 618 .skip(2)
616 TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..})) 619 .next();
617 ] if ident_text == "html_root_url" => Some(text.to_string()), 620
618 _ => { 621 match name {
619 None 622 Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text),
620 } 623 _ => None
621 }).next() 624 }
625 }).flat_map(|t| t).next().map(|s| s.to_string())
622 } else { 626 } else {
623 // Fallback to docs.rs 627 // Fallback to docs.rs
624 // FIXME: Specify an exact version here (from Cargo.lock) 628 // FIXME: Specify an exact version here (from Cargo.lock)
625 Some(format!("https://docs.rs/{}/*", krate.display_name(db)?)) 629 Some(format!("https://docs.rs/{}/*", krate.display_name(db)?))
626 }; 630 };
627 631
628 doc_url.map(|s| s.trim_matches('"').to_owned() + "/").and_then(|s| Url::parse(&s).ok()) 632 doc_url
633 .map(|s| s.trim_matches('"').trim_end_matches("/").to_owned() + "/")
634 .and_then(|s| Url::parse(&s).ok())
629} 635}
630 636
631/// Get the filename and extension generated for a symbol by rustdoc. 637/// Get the filename and extension generated for a symbol by rustdoc.