@@ -48,12 +48,12 @@ pub struct Range {
48
48
}
49
49
50
50
#[ napi]
51
- pub struct SGNode {
52
- inner : SharedReference < SGRoot , Node < ' static , FrontEndLanguage > > ,
51
+ pub struct SgNode {
52
+ inner : SharedReference < SgRoot , Node < ' static , FrontEndLanguage > > ,
53
53
}
54
54
55
55
#[ napi]
56
- impl SGNode {
56
+ impl SgNode {
57
57
#[ napi]
58
58
pub fn range ( & self ) -> Range {
59
59
let start_pos = self . inner . start_pos ( ) ;
@@ -64,49 +64,177 @@ impl SGNode {
64
64
}
65
65
}
66
66
67
+ #[ napi]
68
+ pub fn is_leaf ( & self ) -> bool {
69
+ self . inner . is_leaf ( )
70
+ }
71
+ #[ napi]
72
+ pub fn kind ( & self ) -> String {
73
+ self . inner . kind ( ) . to_string ( )
74
+ }
75
+ #[ napi]
76
+ pub fn text ( & self ) -> String {
77
+ self . inner . text ( ) . to_string ( )
78
+ }
79
+ }
80
+
81
+ #[ napi]
82
+ impl SgNode {
83
+ #[ napi]
84
+ pub fn matches ( & self , m : String ) -> bool {
85
+ self . inner . matches ( & * m)
86
+ }
87
+
88
+ #[ napi]
89
+ pub fn inside ( & self , m : String ) -> bool {
90
+ self . inner . inside ( & * m)
91
+ }
92
+
93
+ #[ napi]
94
+ pub fn has ( & self , m : String ) -> bool {
95
+ self . inner . has ( & * m)
96
+ }
97
+
98
+ #[ napi]
99
+ pub fn precedes ( & self , m : String ) -> bool {
100
+ self . inner . precedes ( & * m)
101
+ }
102
+
103
+ #[ napi]
104
+ pub fn follows ( & self , m : String ) -> bool {
105
+ self . inner . follows ( & * m)
106
+ }
107
+ }
108
+
109
+ /// tree traversal API
110
+ #[ napi]
111
+ impl SgNode {
112
+ #[ napi]
113
+ pub fn children ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Vec < SgNode > > {
114
+ let children = reference. inner . children ( ) ;
115
+ Self :: from_iter_to_vec ( & reference, env, children)
116
+ }
117
+
67
118
#[ napi]
68
119
pub fn find_by_string (
69
120
& self ,
70
- reference : Reference < SGNode > ,
121
+ reference : Reference < SgNode > ,
71
122
env : Env ,
72
123
pattern : String ,
73
- ) -> Result < Option < SGNode > > {
124
+ ) -> Result < Option < SgNode > > {
74
125
let pattern = Pattern :: new ( & pattern, reference. inner . lang ( ) . clone ( ) ) ;
75
- let node = if let Some ( node) = self . inner . find ( pattern) {
76
- node. get_node ( ) . clone ( )
126
+ let node = reference. inner . find ( pattern) . map ( |n| n. get_node ( ) . clone ( ) ) ;
127
+ Self :: transpose_option ( reference, env, node)
128
+ }
129
+
130
+ fn transpose_option (
131
+ reference : Reference < SgNode > ,
132
+ env : Env ,
133
+ node : Option < Node < ' static , FrontEndLanguage > > ,
134
+ ) -> Result < Option < SgNode > > {
135
+ if let Some ( node) = node {
136
+ let root_ref = reference. inner . clone_owner ( env) ?;
137
+ let inner = root_ref. share_with ( env, move |_| Ok ( node) ) ?;
138
+ Ok ( Some ( SgNode { inner } ) )
77
139
} else {
78
- return Ok ( None ) ;
79
- } ;
80
- let root_ref = reference. inner . clone_owner ( env) ?;
81
- let inner = root_ref. share_with ( env, move |_| Ok ( node) ) ?;
82
- Ok ( Some ( SGNode { inner } ) )
140
+ Ok ( None )
141
+ }
83
142
}
84
143
85
144
#[ napi]
86
145
pub fn find_all (
87
146
& self ,
88
- reference : Reference < SGNode > ,
147
+ reference : Reference < SgNode > ,
89
148
env : Env ,
90
149
pattern : String ,
91
- ) -> Result < Vec < SGNode > > {
150
+ ) -> Result < Vec < SgNode > > {
92
151
let mut ret = vec ! [ ] ;
93
152
for node_match in self . inner . find_all ( & * pattern) {
94
153
let node = node_match. get_node ( ) . clone ( ) ;
95
154
let root_ref = reference. inner . clone_owner ( env) ?;
96
- let sg_node = SGNode {
155
+ let sg_node = SgNode {
156
+ inner : root_ref. share_with ( env, move |_| Ok ( node) ) ?,
157
+ } ;
158
+ ret. push ( sg_node) ;
159
+ }
160
+ Ok ( ret)
161
+ }
162
+
163
+ fn from_iter_to_vec (
164
+ reference : & Reference < SgNode > ,
165
+ env : Env ,
166
+ iter : impl Iterator < Item = Node < ' static , FrontEndLanguage > > ,
167
+ ) -> Result < Vec < SgNode > > {
168
+ let mut ret = vec ! [ ] ;
169
+ for node in iter {
170
+ let root_ref = reference. inner . clone_owner ( env) ?;
171
+ let sg_node = SgNode {
97
172
inner : root_ref. share_with ( env, move |_| Ok ( node) ) ?,
98
173
} ;
99
174
ret. push ( sg_node) ;
100
175
}
101
176
Ok ( ret)
102
177
}
178
+
179
+ #[ napi]
180
+ pub fn field (
181
+ & self ,
182
+ reference : Reference < SgNode > ,
183
+ env : Env ,
184
+ name : String ,
185
+ ) -> Result < Option < SgNode > > {
186
+ let node = reference. inner . field ( & name) ;
187
+ Self :: transpose_option ( reference, env, node)
188
+ }
189
+
190
+ #[ napi]
191
+ pub fn parent ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Option < SgNode > > {
192
+ let node = reference. inner . parent ( ) ;
193
+ Self :: transpose_option ( reference, env, node)
194
+ }
195
+
196
+ #[ napi]
197
+ pub fn child ( & self , reference : Reference < SgNode > , env : Env , nth : u32 ) -> Result < Option < SgNode > > {
198
+ let inner = reference. inner . child ( nth as usize ) ;
199
+ Self :: transpose_option ( reference, env, inner)
200
+ }
201
+
202
+ #[ napi]
203
+ pub fn ancestors ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Vec < SgNode > > {
204
+ let ancestors = reference. inner . ancestors ( ) ;
205
+ Self :: from_iter_to_vec ( & reference, env, ancestors)
206
+ }
207
+
208
+ #[ napi]
209
+ pub fn next ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Option < SgNode > > {
210
+ let inner = reference. inner . next ( ) ;
211
+ Self :: transpose_option ( reference, env, inner)
212
+ }
213
+
214
+ #[ napi]
215
+ pub fn next_all ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Vec < SgNode > > {
216
+ let inner = reference. inner . next_all ( ) ;
217
+ Self :: from_iter_to_vec ( & reference, env, inner)
218
+ }
219
+
220
+ #[ napi]
221
+ pub fn prev ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Option < SgNode > > {
222
+ let inner = reference. inner . prev ( ) ;
223
+ Self :: transpose_option ( reference, env, inner)
224
+ }
225
+
226
+ #[ napi]
227
+ pub fn prev_all ( & self , reference : Reference < SgNode > , env : Env ) -> Result < Vec < SgNode > > {
228
+ let inner = reference. inner . prev_all ( ) ;
229
+ Self :: from_iter_to_vec ( & reference, env, inner)
230
+ }
103
231
}
104
232
105
233
#[ napi( js_name = "AstGrep" ) ]
106
- pub struct SGRoot ( AstGrep < FrontEndLanguage > ) ;
234
+ pub struct SgRoot ( AstGrep < FrontEndLanguage > ) ;
107
235
108
236
#[ napi]
109
- impl SGRoot {
237
+ impl SgRoot {
110
238
fn from_lang ( src : String , fe_lang : FrontEndLanguage ) -> Self {
111
239
Self ( AstGrep :: new ( src, fe_lang) )
112
240
}
@@ -132,8 +260,8 @@ impl SGRoot {
132
260
}
133
261
134
262
#[ napi]
135
- pub fn root ( & self , root_ref : Reference < SGRoot > , env : Env ) -> Result < SGNode > {
263
+ pub fn root ( & self , root_ref : Reference < SgRoot > , env : Env ) -> Result < SgNode > {
136
264
let inner = root_ref. share_with ( env, |root| Ok ( root. 0 . root ( ) ) ) ?;
137
- Ok ( SGNode { inner } )
265
+ Ok ( SgNode { inner } )
138
266
}
139
267
}
0 commit comments