diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | crates/ra_ide/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 49 |
3 files changed, 42 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock index bc36f0fab..112c4210d 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1276,12 +1276,14 @@ dependencies = [ | |||
1276 | "ra_fmt", | 1276 | "ra_fmt", |
1277 | "ra_hir", | 1277 | "ra_hir", |
1278 | "ra_hir_def", | 1278 | "ra_hir_def", |
1279 | "ra_hir_expand", | ||
1279 | "ra_ide_db", | 1280 | "ra_ide_db", |
1280 | "ra_prof", | 1281 | "ra_prof", |
1281 | "ra_project_model", | 1282 | "ra_project_model", |
1282 | "ra_ssr", | 1283 | "ra_ssr", |
1283 | "ra_syntax", | 1284 | "ra_syntax", |
1284 | "ra_text_edit", | 1285 | "ra_text_edit", |
1286 | "ra_tt", | ||
1285 | "rand", | 1287 | "rand", |
1286 | "rustc-hash", | 1288 | "rustc-hash", |
1287 | "stdx", | 1289 | "stdx", |
diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index fa925fc5a..219ad33e6 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml | |||
@@ -35,6 +35,7 @@ ra_ssr = { path = "../ra_ssr" } | |||
35 | ra_project_model = { path = "../ra_project_model" } | 35 | ra_project_model = { path = "../ra_project_model" } |
36 | ra_hir_def = { path = "../ra_hir_def" } | 36 | ra_hir_def = { path = "../ra_hir_def" } |
37 | ra_tt = { path = "../ra_tt" } | 37 | ra_tt = { path = "../ra_tt" } |
38 | ra_hir_expand = { path = "../ra_hir_expand" } | ||
38 | 39 | ||
39 | # ra_ide should depend only on the top-level `hir` package. if you need | 40 | # ra_ide should depend only on the top-level `hir` package. if you need |
40 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. | 41 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index f703af434..760d7fe14 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -16,6 +16,7 @@ use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffs | |||
16 | use ra_project_model::ProjectWorkspace; | 16 | use ra_project_model::ProjectWorkspace; |
17 | use ra_hir_def::{item_scope::ItemInNs, db::DefDatabase}; | 17 | use ra_hir_def::{item_scope::ItemInNs, db::DefDatabase}; |
18 | use ra_tt::{Literal, Ident, Punct, TokenTree, Leaf}; | 18 | use ra_tt::{Literal, Ident, Punct, TokenTree, Leaf}; |
19 | use ra_hir_expand::name::AsName; | ||
19 | 20 | ||
20 | use comrak::{parse_document,format_commonmark, ComrakOptions, Arena}; | 21 | use comrak::{parse_document,format_commonmark, ComrakOptions, Arena}; |
21 | use comrak::nodes::NodeValue; | 22 | use comrak::nodes::NodeValue; |
@@ -406,9 +407,9 @@ fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition, wor | |||
406 | match Url::parse(&String::from_utf8(link.url.clone()).unwrap()) { | 407 | match Url::parse(&String::from_utf8(link.url.clone()).unwrap()) { |
407 | // If this is a valid absolute URL don't touch it | 408 | // If this is a valid absolute URL don't touch it |
408 | Ok(_) => (), | 409 | Ok(_) => (), |
409 | // If contains .html file-based link to new page | 410 | // Otherwise there are two main possibilities |
410 | // If starts with #fragment file-based link to fragment on current page | 411 | // path-based links: `../../module/struct.MyStruct.html` |
411 | // If contains :: module-based link | 412 | // module-based links (AKA intra-doc links): `super::super::module::MyStruct` |
412 | Err(_) => { | 413 | Err(_) => { |
413 | let link_str = String::from_utf8(link.url.clone()).unwrap(); | 414 | let link_str = String::from_utf8(link.url.clone()).unwrap(); |
414 | let resolved = try_resolve_path(db, &mut doc_target_dirs.clone(), definition, &link_str, UrlMode::Url) | 415 | let resolved = try_resolve_path(db, &mut doc_target_dirs.clone(), definition, &link_str, UrlMode::Url) |
@@ -429,7 +430,9 @@ fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition, wor | |||
429 | Some(String::from_utf8(out).unwrap()) | 430 | Some(String::from_utf8(out).unwrap()) |
430 | } | 431 | } |
431 | 432 | ||
432 | /// Try to resolve path to local documentation via intra-doc-links (i.e. `super::gateway::Shard`) | 433 | /// Try to resolve path to local documentation via intra-doc-links (i.e. `super::gateway::Shard`). |
434 | /// | ||
435 | /// See [RFC1946](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md). | ||
433 | fn try_resolve_intra(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = PathBuf>, definition: &Definition, link: &str) -> Option<String> { | 436 | fn try_resolve_intra(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = PathBuf>, definition: &Definition, link: &str) -> Option<String> { |
434 | None | 437 | None |
435 | } | 438 | } |
@@ -439,7 +442,7 @@ enum UrlMode { | |||
439 | File | 442 | File |
440 | } | 443 | } |
441 | 444 | ||
442 | /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`) | 445 | /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). |
443 | fn try_resolve_path(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = PathBuf>, definition: &Definition, link: &str, mode: UrlMode) -> Option<String> { | 446 | fn try_resolve_path(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = PathBuf>, definition: &Definition, link: &str, mode: UrlMode) -> Option<String> { |
444 | let ns = if let Definition::ModuleDef(moddef) = definition { | 447 | let ns = if let Definition::ModuleDef(moddef) = definition { |
445 | ItemInNs::Types(moddef.clone().into()) | 448 | ItemInNs::Types(moddef.clone().into()) |
@@ -456,12 +459,12 @@ fn try_resolve_path(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = Pat | |||
456 | 459 | ||
457 | match mode { | 460 | match mode { |
458 | UrlMode::Url => { | 461 | UrlMode::Url => { |
459 | let root = get_doc_url(db, &krate); | ||
460 | let mut base = base.join("/"); | 462 | let mut base = base.join("/"); |
461 | if link.starts_with("#") { | 463 | get_doc_url(db, &krate) |
462 | base = base + "/" | 464 | .and_then(|url| url.join(&base).ok()) |
463 | }; | 465 | .and_then(|url| get_symbol_filename(db, definition).as_deref().map(|f| url.join(f).ok()).flatten()) |
464 | root.and_then(|url| url.join(&base).ok()).and_then(|url| url.join(link).ok()).map(|url| url.into_string()) | 466 | .and_then(|url| url.join(link).ok()) |
467 | .map(|url| url.into_string()) | ||
465 | }, | 468 | }, |
466 | UrlMode::File => { | 469 | UrlMode::File => { |
467 | let base = base.collect::<PathBuf>(); | 470 | let base = base.collect::<PathBuf>(); |
@@ -502,6 +505,32 @@ fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> { | |||
502 | doc_url.map(|s| s.trim_matches('"').to_owned() + "/").and_then(|s| Url::parse(&s).ok()) | 505 | doc_url.map(|s| s.trim_matches('"').to_owned() + "/").and_then(|s| Url::parse(&s).ok()) |
503 | } | 506 | } |
504 | 507 | ||
508 | /// Get the filename and extension generated for a symbol by rustdoc. | ||
509 | /// | ||
510 | /// Example: `struct.Shard.html` | ||
511 | fn get_symbol_filename(db: &RootDatabase, definition: &Definition) -> Option<String> { | ||
512 | Some(match definition { | ||
513 | Definition::ModuleDef(def) => match def { | ||
514 | ModuleDef::Adt(adt) => match adt { | ||
515 | Adt::Struct(s) => format!("struct.{}.html", s.name(db)), | ||
516 | Adt::Enum(e) => format!("enum.{}.html", e.name(db)), | ||
517 | Adt::Union(u) => format!("union.{}.html", u.name(db)) | ||
518 | }, | ||
519 | ModuleDef::Module(_) => "index.html".to_string(), | ||
520 | ModuleDef::Trait(t) => format!("trait.{}.html", t.name(db)), | ||
521 | ModuleDef::TypeAlias(t) => format!("type.{}.html", t.name(db)), | ||
522 | ModuleDef::BuiltinType(t) => format!("primitive.{}.html", t.as_name()), | ||
523 | ModuleDef::Function(f) => format!("fn.{}.html", f.name(db)), | ||
524 | ModuleDef::EnumVariant(ev) => format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db)), | ||
525 | ModuleDef::Const(c) => format!("const.{}.html", c.name(db)?), | ||
526 | // TODO: Check this is the right prefix | ||
527 | ModuleDef::Static(s) => format!("static.{}.html", s.name(db)?) | ||
528 | }, | ||
529 | Definition::Macro(m) => format!("macro.{}.html", m.name(db)?), | ||
530 | _ => None? | ||
531 | }) | ||
532 | } | ||
533 | |||
505 | fn iter_nodes<'a, F>(node: &'a comrak::nodes::AstNode<'a>, f: &F) | 534 | fn iter_nodes<'a, F>(node: &'a comrak::nodes::AstNode<'a>, f: &F) |
506 | where F : Fn(&'a comrak::nodes::AstNode<'a>) { | 535 | where F : Fn(&'a comrak::nodes::AstNode<'a>) { |
507 | f(node); | 536 | f(node); |