use static data for namespace recognition

This commit is contained in:
Zac Pullar-Strecker 2020-08-01 12:32:49 +12:00
parent cbdb6bd939
commit 7bd48a63f6
3 changed files with 49 additions and 56 deletions

2
Cargo.lock generated
View file

@ -1083,7 +1083,6 @@ dependencies = [
"indexmap", "indexmap",
"itertools", "itertools",
"log", "log",
"once_cell",
"oorandom", "oorandom",
"pulldown-cmark", "pulldown-cmark",
"pulldown-cmark-to-cmark", "pulldown-cmark-to-cmark",
@ -1103,6 +1102,7 @@ dependencies = [
"rustc-hash", "rustc-hash",
"stdx", "stdx",
"test_utils", "test_utils",
"url",
] ]
[[package]] [[package]]

View file

@ -21,7 +21,6 @@ url = "*"
pulldown-cmark-to-cmark = "4.0.2" pulldown-cmark-to-cmark = "4.0.2"
pulldown-cmark = "0.7.0" pulldown-cmark = "0.7.0"
oorandom = "11.1.2" oorandom = "11.1.2"
once_cell = "1"
stdx = { path = "../stdx" } stdx = { path = "../stdx" }

View file

@ -1,8 +1,4 @@
use std::collections::{HashMap, HashSet}; use std::iter::once;
use std::{
iter::{once, FromIterator},
sync::Mutex,
};
use hir::{ use hir::{
db::DefDatabase, Adt, AsAssocItem, AsName, AssocItemContainer, AttrDef, Crate, Documentation, db::DefDatabase, Adt, AsAssocItem, AsName, AssocItemContainer, AttrDef, Crate, Documentation,
@ -10,7 +6,6 @@ use hir::{
ModuleSource, Semantics, ModuleSource, Semantics,
}; };
use itertools::Itertools; use itertools::Itertools;
use once_cell::sync::Lazy;
use pulldown_cmark::{CowStr, Event, Options, Parser, Tag}; use pulldown_cmark::{CowStr, Event, Options, Parser, Tag};
use pulldown_cmark_to_cmark::cmark; use pulldown_cmark_to_cmark::cmark;
use ra_db::SourceDatabase; use ra_db::SourceDatabase;
@ -402,10 +397,9 @@ fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) ->
try_resolve_path(db, definition, &target).map(|target| (target, title.to_string())) try_resolve_path(db, definition, &target).map(|target| (target, title.to_string()))
}); });
if let Some((target, title)) = resolved { match resolved {
(target, title) Some((target, title)) => (target, title),
} else { None => (target.to_string(), title.to_string()),
(target.to_string(), title.to_string())
} }
} }
}); });
@ -421,65 +415,61 @@ enum Namespace {
Macros, Macros,
} }
static NS_MAP: Lazy< static TYPES: ([&str; 7], [&str; 0]) =
HashMap<Namespace, (HashSet<&'static &'static str>, HashSet<&'static &'static str>)>, (["type", "struct", "enum", "mod", "trait", "union", "module"], []);
> = Lazy::new(|| { static VALUES: ([&str; 8], [&str; 1]) =
let mut map = HashMap::new(); (["value", "function", "fn", "method", "const", "static", "mod", "module"], ["()"]);
map.insert(Namespace::Types, (HashSet::new(), HashSet::new())); static MACROS: ([&str; 1], [&str; 1]) = (["macro"], ["!"]);
map.insert(
Namespace::Values,
(
HashSet::from_iter(
["value", "function", "fn", "method", "const", "static", "mod", "module"].iter(),
),
HashSet::from_iter(["()"].iter()),
),
);
map.insert(
Namespace::Macros,
(HashSet::from_iter(["macro"].iter()), HashSet::from_iter(["!"].iter())),
);
map
});
impl Namespace { impl Namespace {
/// Extract the specified namespace from an intra-doc-link if one exists. /// Extract the specified namespace from an intra-doc-link if one exists.
fn from_intra_spec(s: &str) -> Option<Self> { fn from_intra_spec(s: &str) -> Option<Self> {
NS_MAP [
.iter() (Namespace::Types, (TYPES.0.iter(), TYPES.1.iter())),
.filter(|(_ns, (prefixes, suffixes))| { (Namespace::Values, (VALUES.0.iter(), VALUES.1.iter())),
prefixes (Namespace::Macros, (MACROS.0.iter(), MACROS.1.iter())),
.iter() ]
.map(|prefix| { .iter()
s.starts_with(*prefix) .filter(|(_ns, (prefixes, suffixes))| {
prefixes
.clone()
.map(|prefix| {
s.starts_with(*prefix)
&& s.chars()
.nth(prefix.len() + 1)
.map(|c| c == '@' || c == ' ')
.unwrap_or(false)
})
.any(|cond| cond)
|| suffixes
.clone()
.map(|suffix| {
s.starts_with(*suffix)
&& s.chars() && s.chars()
.nth(prefix.len() + 1) .nth(suffix.len() + 1)
.map(|c| c == '@' || c == ' ') .map(|c| c == '@' || c == ' ')
.unwrap_or(false) .unwrap_or(false)
}) })
.any(|cond| cond) .any(|cond| cond)
|| suffixes })
.iter() .map(|(ns, (_, _))| *ns)
.map(|suffix| { .next()
s.starts_with(*suffix)
&& s.chars()
.nth(suffix.len() + 1)
.map(|c| c == '@' || c == ' ')
.unwrap_or(false)
})
.any(|cond| cond)
})
.map(|(ns, (_, _))| *ns)
.next()
} }
} }
// Strip prefixes, suffixes, and inline code marks from the given string. // Strip prefixes, suffixes, and inline code marks from the given string.
fn strip_prefixes_suffixes(mut s: &str) -> &str { fn strip_prefixes_suffixes(mut s: &str) -> &str {
s = s.trim_matches('`'); s = s.trim_matches('`');
NS_MAP.iter().for_each(|(_, (prefixes, suffixes))| {
prefixes.iter().for_each(|prefix| s = s.trim_start_matches(*prefix)); [
suffixes.iter().for_each(|suffix| s = s.trim_end_matches(*suffix)); (TYPES.0.iter(), TYPES.1.iter()),
(VALUES.0.iter(), VALUES.1.iter()),
(MACROS.0.iter(), MACROS.1.iter()),
]
.iter()
.for_each(|(prefixes, suffixes)| {
prefixes.clone().for_each(|prefix| s = s.trim_start_matches(*prefix));
suffixes.clone().for_each(|suffix| s = s.trim_end_matches(*suffix));
}); });
s.trim_start_matches("@").trim() s.trim_start_matches("@").trim()
} }
@ -493,6 +483,8 @@ fn try_resolve_intra(
link_text: &str, link_text: &str,
link_target: &str, link_target: &str,
) -> Option<(String, String)> { ) -> Option<(String, String)> {
eprintln!("resolving intra");
// Set link_target for implied shortlinks // Set link_target for implied shortlinks
let link_target = let link_target =
if link_target.is_empty() { link_text.trim_matches('`') } else { link_target }; if link_target.is_empty() { link_text.trim_matches('`') } else { link_target };
@ -551,6 +543,8 @@ fn try_resolve_intra(
/// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`).
fn try_resolve_path(db: &RootDatabase, definition: &Definition, link: &str) -> Option<String> { fn try_resolve_path(db: &RootDatabase, definition: &Definition, link: &str) -> Option<String> {
eprintln!("resolving path");
if !link.contains("#") && !link.contains(".html") { if !link.contains("#") && !link.contains(".html") {
return None; return None;
} }