ide/doc_links/
intra_doc_links.rs1const TYPES: (&[&str], &[&str]) =
4 (&["type", "struct", "enum", "mod", "trait", "union", "module", "prim", "primitive"], &[]);
5const VALUES: (&[&str], &[&str]) =
6 (&["value", "function", "fn", "method", "const", "static", "mod", "module"], &["()"]);
7const MACROS: (&[&str], &[&str]) = (&["macro", "derive"], &["!"]);
8
9pub(super) fn parse_intra_doc_link(s: &str) -> (&str, Option<hir::Namespace>) {
17 let s = s.trim_matches('`');
18
19 [
20 (hir::Namespace::Types, TYPES),
21 (hir::Namespace::Values, VALUES),
22 (hir::Namespace::Macros, MACROS),
23 ]
24 .into_iter()
25 .find_map(|(ns, (prefixes, suffixes))| {
26 if let Some(prefix) = prefixes.iter().find(|&&prefix| {
27 s.starts_with(prefix)
28 && s.chars().nth(prefix.len()).is_some_and(|c| c == '@' || c == ' ')
29 }) {
30 Some((&s[prefix.len() + 1..], ns))
31 } else {
32 suffixes.iter().find_map(|&suffix| s.strip_suffix(suffix).zip(Some(ns)))
33 }
34 })
35 .map_or((s, None), |(s, ns)| (s, Some(ns)))
36}
37
38pub(super) fn strip_prefixes_suffixes(s: &str) -> &str {
39 [TYPES, VALUES, MACROS]
40 .into_iter()
41 .find_map(|(prefixes, suffixes)| {
42 if let Some(prefix) = prefixes.iter().find(|&&prefix| {
43 s.starts_with(prefix)
44 && s.chars().nth(prefix.len()).is_some_and(|c| c == '@' || c == ' ')
45 }) {
46 Some(&s[prefix.len() + 1..])
47 } else {
48 suffixes.iter().find_map(|&suffix| s.strip_suffix(suffix))
49 }
50 })
51 .unwrap_or(s)
52}
53
54#[cfg(test)]
55mod tests {
56 use expect_test::{Expect, expect};
57
58 use super::*;
59
60 fn check(link: &str, expected: Expect) {
61 let (l, a) = parse_intra_doc_link(link);
62 let a = a.map_or_else(String::new, |a| format!(" ({a:?})"));
63 expected.assert_eq(&format!("{l}{a}"));
64 }
65
66 #[test]
67 fn test_name() {
68 check("foo", expect![[r#"foo"#]]);
69 check("struct Struct", expect![[r#"Struct (Types)"#]]);
70 check("makro!", expect![[r#"makro (Macros)"#]]);
71 check("fn@function", expect![[r#"function (Values)"#]]);
72 }
73}