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
use crate::meta_var::MetaVarEnv;
use crate::replacer::Replacer;
use crate::ts_parser::Edit;
use crate::Language;
use crate::Node;
use std::borrow::Borrow;
use std::ops::Deref;
#[derive(Clone)]
pub struct NodeMatch<'tree, L: Language>(Node<'tree, L>, MetaVarEnv<'tree, L>);
impl<'tree, L: Language> NodeMatch<'tree, L> {
pub fn new(node: Node<'tree, L>, env: MetaVarEnv<'tree, L>) -> Self {
Self(node, env)
}
pub fn get_node(&self) -> &Node<'tree, L> {
&self.0
}
pub fn get_env(&self) -> &MetaVarEnv<'tree, L> {
&self.1
}
pub fn replace_by<R: Replacer<L>>(&self, replacer: R) -> Edit {
let lang = self.lang().clone();
let env = self.get_env();
let range = self.range();
let position = range.start;
let deleted_length = range.len();
let inserted_text = replacer.generate_replacement(env, lang);
Edit {
position,
deleted_length,
inserted_text,
}
}
}
impl<'tree, L: Language> From<Node<'tree, L>> for NodeMatch<'tree, L> {
fn from(node: Node<'tree, L>) -> Self {
Self(node, MetaVarEnv::new())
}
}
impl<'tree, L: Language> From<NodeMatch<'tree, L>> for Node<'tree, L> {
fn from(node_match: NodeMatch<'tree, L>) -> Self {
node_match.0
}
}
impl<'tree, L: Language> Deref for NodeMatch<'tree, L> {
type Target = Node<'tree, L>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'tree, L: Language> Borrow<Node<'tree, L>> for NodeMatch<'tree, L> {
fn borrow(&self) -> &Node<'tree, L> {
&self.0
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::language::Tsx;
fn use_node<L: Language>(n: &Node<L>) -> String {
n.text().to_string()
}
fn borrow_node<'a, L, B>(b: B) -> String
where
L: Language + 'static,
B: Borrow<Node<'a, L>>,
{
b.borrow().text().to_string()
}
#[test]
fn test_node_match_as_node() {
let root = Tsx.ast_grep("var a = 1");
let node = root.root();
let src = node.text().to_string();
let nm = NodeMatch::from(node);
let ret = use_node(&*nm);
assert_eq!(ret, src);
assert_eq!(use_node(&*nm), borrow_node(nm));
}
#[test]
fn test_node_env() {
let root = Tsx.ast_grep("var a = 1");
let find = root.root().find("var $A = 1").expect("should find");
let env = find.get_env();
let node = env.get_match("A").expect("should find");
assert_eq!(node.text(), "a");
}
#[test]
fn test_replace_by() {
let root = Tsx.ast_grep("var a = 1");
let find = root.root().find("var $A = 1").expect("should find");
let fixed = find.replace_by("var b = $A");
assert_eq!(fixed.position, 0);
assert_eq!(fixed.deleted_length, 9);
assert_eq!(fixed.inserted_text, "var b = a");
}
}