1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use super::Matcher;
use crate::meta_var::MetaVarEnv;
use crate::node::KindId;
use crate::Language;
use crate::Node;
use std::marker::PhantomData;
use bit_set::BitSet;
const TS_BUILTIN_SYM_END: KindId = 0;
const TS_BUILTIN_SYM_ERROR: KindId = 65535;
#[derive(Clone)]
pub struct KindMatcher<L: Language> {
kind: KindId,
lang: PhantomData<L>,
}
impl<L: Language> KindMatcher<L> {
pub fn new(node_kind: &str, lang: L) -> Self {
Self {
kind: lang
.get_ts_language()
.id_for_node_kind(node_kind, true),
lang: PhantomData,
}
}
pub fn from_id(kind: KindId) -> Self {
Self {
kind,
lang: PhantomData,
}
}
pub fn is_invalid(&self) -> bool {
self.kind == TS_BUILTIN_SYM_END
}
pub fn is_error_matcher(&self) -> bool {
self.kind == TS_BUILTIN_SYM_ERROR
}
}
impl<L: Language> Matcher<L> for KindMatcher<L> {
fn match_node_with_env<'tree>(
&self,
node: Node<'tree, L>,
_env: &mut MetaVarEnv<'tree, L>,
) -> Option<Node<'tree, L>> {
if node.kind_id() == self.kind {
Some(node)
} else {
None
}
}
fn potential_kinds(&self) -> Option<BitSet> {
let mut set = BitSet::new();
set.insert(self.kind.into());
Some(set)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::language::Tsx;
use crate::Root;
fn pattern_node(s: &str) -> Root<Tsx> {
Root::new(s, Tsx)
}
#[test]
fn test_kind_match() {
let kind = "public_field_definition";
let cand = pattern_node("class A { a = 123 }");
let cand = cand.root();
let pattern = KindMatcher::new(kind, Tsx);
assert!(
pattern.find_node(cand.clone()).is_some(),
"goal: {}, candidate: {}",
kind,
cand.to_sexp(),
);
}
#[test]
fn test_kind_non_match() {
let kind = "field_definition";
let cand = pattern_node("const a = 123");
let cand = cand.root();
let pattern = KindMatcher::new(kind, Tsx);
assert!(
pattern.find_node(cand.clone()).is_none(),
"goal: {}, candidate: {}",
kind,
cand.to_sexp(),
);
}
#[test]
fn test_kind_potential_kinds() {
let kind = "field_definition";
let matcher = KindMatcher::new(kind, Tsx);
let potential_kinds = matcher
.potential_kinds()
.expect("should have potential kinds");
assert_eq!(potential_kinds.len(), 1);
}
}