1use std::collections::HashSet;
2
3use rowan::{NodeOrToken, SyntaxToken, TextSize};
4
5use crate::TokenTrait;
6
7pub fn completion<L: rowan::Language>(n: &rowan::SyntaxNode<L>, at: usize) -> HashSet<L::Kind>
8where
9 L::Kind: TokenTrait + 'static,
10{
11 let at = TextSize::new(at as u32);
12
13 let mut out = HashSet::new();
14 if let Some(end) = n
15 .descendants()
16 .filter(|x| x.text_range().end() == at)
17 .next()
18 {
19 out.extend(end.kind().ending_tokens().iter());
20 }
21
22 if let Some(end) = n
23 .descendants()
24 .filter(|x| x.text_range().start() == at)
25 .next()
26 {
27 out.extend(end.kind().starting_tokens().iter());
28 }
29
30 if let Some(end) = n.token_at_offset(at).left_biased() {
31 out.extend(end.kind().ending_tokens().iter());
32 }
33
34 out
35}
36
37pub fn print<L: rowan::Language>(n: &rowan::SyntaxNode<L>, indent: usize, errors: &mut &[String])
38where
39 L::Kind: TokenTrait + 'static,
40{
41 for _ in 0..indent {
42 eprint!(" ");
43 }
44 if n.kind() == L::Kind::ERROR {
45 eprintln!("{:?} {:?}", n, errors.first());
46 if errors.len() > 0 {
47 *errors = &errors[1..];
48 }
49 } else {
50 eprintln!("{:?}", n);
51 }
52 for node in n.children_with_tokens() {
53 match node {
54 NodeOrToken::Node(n) => print(&n, indent + 2, errors),
55 NodeOrToken::Token(t) => {
56 for _ in 0..indent {
57 eprint!(" ");
58 }
59 eprintln!(" {:?} (token)", t);
60 }
61 }
62 }
63}
64
65pub fn find_range<L: rowan::Language>(token: &rowan::SyntaxNode<L>) -> std::ops::Range<usize>
66where
67 L::Kind: TokenTrait + 'static,
68{
69 let mut start = token.text_range();
70
71 let is_empty = |token: &NodeOrToken<rowan::SyntaxNode<L>, SyntaxToken<L>>| {
72 let kind = token.kind();
73 kind.skips()
74 };
75
76 if let Some(mut start_find) = token.prev_sibling_or_token() {
77 while is_empty(&start_find) {
78 start = start_find.text_range();
79 if let Some(pr) = start_find.prev_sibling_or_token() {
80 start_find = pr;
81 } else {
82 break;
83 }
84 }
85 }
86 let mut end = token.text_range();
87
88 if let Some(mut end_find) = token.next_sibling_or_token() {
89 while is_empty(&end_find) {
90 end = end_find.text_range();
91 if let Some(pr) = end_find.next_sibling_or_token() {
92 end_find = pr;
93 } else {
94 break;
95 }
96 }
97 }
98
99 let e: usize = end.end().into();
100 start.start().into()..e + 1
101}