aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/hover.rs')
-rw-r--r--crates/ra_ide/src/hover.rs102
1 files changed, 48 insertions, 54 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 1531aca2e..f6854a18d 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -1,8 +1,4 @@
1use std::collections::{HashMap, HashSet}; 1use std::iter::once;
2use std::{
3 iter::{once, FromIterator},
4 sync::Mutex,
5};
6 2
7use hir::{ 3use hir::{
8 db::DefDatabase, Adt, AsAssocItem, AsName, AssocItemContainer, AttrDef, Crate, Documentation, 4 db::DefDatabase, Adt, AsAssocItem, AsName, AssocItemContainer, AttrDef, Crate, Documentation,
@@ -10,7 +6,6 @@ use hir::{
10 ModuleSource, Semantics, 6 ModuleSource, Semantics,
11}; 7};
12use itertools::Itertools; 8use itertools::Itertools;
13use once_cell::sync::Lazy;
14use pulldown_cmark::{CowStr, Event, Options, Parser, Tag}; 9use pulldown_cmark::{CowStr, Event, Options, Parser, Tag};
15use pulldown_cmark_to_cmark::cmark; 10use pulldown_cmark_to_cmark::cmark;
16use ra_db::SourceDatabase; 11use ra_db::SourceDatabase;
@@ -402,10 +397,9 @@ fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) ->
402 try_resolve_path(db, definition, &target).map(|target| (target, title.to_string())) 397 try_resolve_path(db, definition, &target).map(|target| (target, title.to_string()))
403 }); 398 });
404 399
405 if let Some((target, title)) = resolved { 400 match resolved {
406 (target, title) 401 Some((target, title)) => (target, title),
407 } else { 402 None => (target.to_string(), title.to_string()),
408 (target.to_string(), title.to_string())
409 } 403 }
410 } 404 }
411 }); 405 });
@@ -421,65 +415,61 @@ enum Namespace {
421 Macros, 415 Macros,
422} 416}
423 417
424static NS_MAP: Lazy< 418static TYPES: ([&str; 7], [&str; 0]) =
425 HashMap<Namespace, (HashSet<&'static &'static str>, HashSet<&'static &'static str>)>, 419 (["type", "struct", "enum", "mod", "trait", "union", "module"], []);
426> = Lazy::new(|| { 420static VALUES: ([&str; 8], [&str; 1]) =
427 let mut map = HashMap::new(); 421 (["value", "function", "fn", "method", "const", "static", "mod", "module"], ["()"]);
428 map.insert(Namespace::Types, (HashSet::new(), HashSet::new())); 422static MACROS: ([&str; 1], [&str; 1]) = (["macro"], ["!"]);
429 map.insert(
430 Namespace::Values,
431 (
432 HashSet::from_iter(
433 ["value", "function", "fn", "method", "const", "static", "mod", "module"].iter(),
434 ),
435 HashSet::from_iter(["()"].iter()),
436 ),
437 );
438 map.insert(
439 Namespace::Macros,
440 (HashSet::from_iter(["macro"].iter()), HashSet::from_iter(["!"].iter())),
441 );
442 map
443});
444 423
445impl Namespace { 424impl Namespace {
446 /// Extract the specified namespace from an intra-doc-link if one exists. 425 /// Extract the specified namespace from an intra-doc-link if one exists.
447 fn from_intra_spec(s: &str) -> Option<Self> { 426 fn from_intra_spec(s: &str) -> Option<Self> {
448 NS_MAP 427 [
449 .iter() 428 (Namespace::Types, (TYPES.0.iter(), TYPES.1.iter())),
450 .filter(|(_ns, (prefixes, suffixes))| { 429 (Namespace::Values, (VALUES.0.iter(), VALUES.1.iter())),
451 prefixes 430 (Namespace::Macros, (MACROS.0.iter(), MACROS.1.iter())),
452 .iter() 431 ]
453 .map(|prefix| { 432 .iter()
454 s.starts_with(*prefix) 433 .filter(|(_ns, (prefixes, suffixes))| {
434 prefixes
435 .clone()
436 .map(|prefix| {
437 s.starts_with(*prefix)
438 && s.chars()
439 .nth(prefix.len() + 1)
440 .map(|c| c == '@' || c == ' ')
441 .unwrap_or(false)
442 })
443 .any(|cond| cond)
444 || suffixes
445 .clone()
446 .map(|suffix| {
447 s.starts_with(*suffix)
455 && s.chars() 448 && s.chars()
456 .nth(prefix.len() + 1) 449 .nth(suffix.len() + 1)
457 .map(|c| c == '@' || c == ' ') 450 .map(|c| c == '@' || c == ' ')
458 .unwrap_or(false) 451 .unwrap_or(false)
459 }) 452 })
460 .any(|cond| cond) 453 .any(|cond| cond)
461 || suffixes 454 })
462 .iter() 455 .map(|(ns, (_, _))| *ns)
463 .map(|suffix| { 456 .next()
464 s.starts_with(*suffix)
465 && s.chars()
466 .nth(suffix.len() + 1)
467 .map(|c| c == '@' || c == ' ')
468 .unwrap_or(false)
469 })
470 .any(|cond| cond)
471 })
472 .map(|(ns, (_, _))| *ns)
473 .next()
474 } 457 }
475} 458}
476 459
477// Strip prefixes, suffixes, and inline code marks from the given string. 460// Strip prefixes, suffixes, and inline code marks from the given string.
478fn strip_prefixes_suffixes(mut s: &str) -> &str { 461fn strip_prefixes_suffixes(mut s: &str) -> &str {
479 s = s.trim_matches('`'); 462 s = s.trim_matches('`');
480 NS_MAP.iter().for_each(|(_, (prefixes, suffixes))| { 463
481 prefixes.iter().for_each(|prefix| s = s.trim_start_matches(*prefix)); 464 [
482 suffixes.iter().for_each(|suffix| s = s.trim_end_matches(*suffix)); 465 (TYPES.0.iter(), TYPES.1.iter()),
466 (VALUES.0.iter(), VALUES.1.iter()),
467 (MACROS.0.iter(), MACROS.1.iter()),
468 ]
469 .iter()
470 .for_each(|(prefixes, suffixes)| {
471 prefixes.clone().for_each(|prefix| s = s.trim_start_matches(*prefix));
472 suffixes.clone().for_each(|suffix| s = s.trim_end_matches(*suffix));
483 }); 473 });
484 s.trim_start_matches("@").trim() 474 s.trim_start_matches("@").trim()
485} 475}
@@ -493,6 +483,8 @@ fn try_resolve_intra(
493 link_text: &str, 483 link_text: &str,
494 link_target: &str, 484 link_target: &str,
495) -> Option<(String, String)> { 485) -> Option<(String, String)> {
486 eprintln!("resolving intra");
487
496 // Set link_target for implied shortlinks 488 // Set link_target for implied shortlinks
497 let link_target = 489 let link_target =
498 if link_target.is_empty() { link_text.trim_matches('`') } else { link_target }; 490 if link_target.is_empty() { link_text.trim_matches('`') } else { link_target };
@@ -551,6 +543,8 @@ fn try_resolve_intra(
551 543
552/// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). 544/// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`).
553fn try_resolve_path(db: &RootDatabase, definition: &Definition, link: &str) -> Option<String> { 545fn try_resolve_path(db: &RootDatabase, definition: &Definition, link: &str) -> Option<String> {
546 eprintln!("resolving path");
547
554 if !link.contains("#") && !link.contains(".html") { 548 if !link.contains("#") && !link.contains(".html") {
555 return None; 549 return None;
556 } 550 }