tree_stump 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,531 @@
1
+ use magnus::block::Yield;
2
+ use magnus::value::ReprValue;
3
+ use magnus::{typed_data, Error, RFile, Ruby, Value};
4
+
5
+ use std::cell::RefCell;
6
+ use std::hash::Hash;
7
+ use std::num::NonZero;
8
+ use std::ops::Range;
9
+ use std::sync::Arc;
10
+
11
+ use crate::data;
12
+ use crate::data::Point;
13
+ use crate::language::LanguageRef;
14
+ use crate::util::build_error;
15
+
16
+ #[magnus::wrap(class = "TreeStump::Tree", free_immediately)]
17
+ pub struct Tree {
18
+ raw_tree: Arc<tree_sitter::Tree>,
19
+ }
20
+
21
+ impl Tree {
22
+ pub fn from(raw_tree: Arc<tree_sitter::Tree>) -> Self {
23
+ Self { raw_tree }
24
+ }
25
+
26
+ pub fn root_node(&self) -> Node<'_> {
27
+ Node {
28
+ raw_tree: Arc::clone(&self.raw_tree),
29
+ raw_node: self.raw_tree.root_node(),
30
+ }
31
+ }
32
+
33
+ pub fn language(&self) -> LanguageRef<'_> {
34
+ let raw_lang_ref = self.raw_tree.language();
35
+ LanguageRef {
36
+ raw_language_ref: raw_lang_ref,
37
+ }
38
+ }
39
+
40
+ pub fn walk(&self) -> TreeCursor<'_> {
41
+ TreeCursor {
42
+ raw_tree: Arc::clone(&self.raw_tree),
43
+ raw_cursor: RefCell::new(self.raw_tree.walk()),
44
+ }
45
+ }
46
+
47
+ pub fn print_dot_graph(&self, io: RFile) {
48
+ self.raw_tree.print_dot_graph(&io);
49
+ }
50
+
51
+ pub fn inspect(&self) -> String {
52
+ format!("{:?}", self.raw_tree)
53
+ }
54
+ }
55
+
56
+ #[magnus::wrap(class = "TreeStump::TreeCursor", free_immediately, unsafe_generics)]
57
+ pub struct TreeCursor<'cursor> {
58
+ raw_tree: Arc<tree_sitter::Tree>,
59
+ raw_cursor: RefCell<tree_sitter::TreeCursor<'cursor>>,
60
+ }
61
+
62
+ impl<'cursor> TreeCursor<'cursor> {
63
+ pub fn node(&self) -> Node {
64
+ Node {
65
+ raw_tree: Arc::clone(&self.raw_tree),
66
+ raw_node: self.raw_cursor.borrow().node(),
67
+ }
68
+ }
69
+
70
+ pub fn field_id(&self) -> Option<u16> {
71
+ self.raw_cursor.borrow().field_id().map(|id| id.get())
72
+ }
73
+
74
+ pub fn goto_first_child(&self) -> bool {
75
+ self.raw_cursor.borrow_mut().goto_first_child()
76
+ }
77
+
78
+ pub fn goto_last_child(&self) -> bool {
79
+ self.raw_cursor.borrow_mut().goto_last_child()
80
+ }
81
+
82
+ pub fn goto_parent(&self) -> bool {
83
+ self.raw_cursor.borrow_mut().goto_parent()
84
+ }
85
+
86
+ pub fn goto_next_sibling(&self) -> bool {
87
+ self.raw_cursor.borrow_mut().goto_next_sibling()
88
+ }
89
+
90
+ pub fn goto_descendant(&self, descendant_index: usize) {
91
+ self.raw_cursor
92
+ .borrow_mut()
93
+ .goto_descendant(descendant_index)
94
+ }
95
+
96
+ pub fn goto_previous_sibling(&self) -> bool {
97
+ self.raw_cursor.borrow_mut().goto_previous_sibling()
98
+ }
99
+
100
+ pub fn goto_first_child_for_byte(&self, index: usize) -> Option<usize> {
101
+ self.raw_cursor
102
+ .borrow_mut()
103
+ .goto_first_child_for_byte(index)
104
+ }
105
+
106
+ pub fn reset(&self, node: &Node<'cursor>) -> bool {
107
+ self.raw_cursor.borrow_mut().reset(node.raw_node);
108
+ true
109
+ }
110
+
111
+ pub fn reset_to(&self, cursor: &Self) {
112
+ self.raw_cursor
113
+ .borrow_mut()
114
+ .reset_to(&cursor.raw_cursor.borrow())
115
+ }
116
+ }
117
+
118
+ #[magnus::wrap(class = "TreeStump::Node", free_immediately, unsafe_generics)]
119
+ #[derive(Debug, Clone)]
120
+ pub struct Node<'tree> {
121
+ pub raw_tree: Arc<tree_sitter::Tree>,
122
+ pub raw_node: tree_sitter::Node<'tree>,
123
+ }
124
+
125
+ impl PartialEq for Node<'_> {
126
+ fn eq(&self, other: &Self) -> bool {
127
+ self.raw_node == other.raw_node
128
+ }
129
+ }
130
+
131
+ impl Eq for Node<'_> {}
132
+
133
+ impl Hash for Node<'_> {
134
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
135
+ self.raw_node.hash(state)
136
+ }
137
+ }
138
+
139
+ impl<'tree> Node<'tree> {
140
+ pub fn new(raw_tree: Arc<tree_sitter::Tree>, raw_node: tree_sitter::Node<'tree>) -> Self {
141
+ Self { raw_tree, raw_node }
142
+ }
143
+
144
+ pub fn get_raw_node(&self) -> tree_sitter::Node<'tree> {
145
+ self.raw_node
146
+ }
147
+
148
+ pub fn id(&self) -> usize {
149
+ self.raw_node.id()
150
+ }
151
+
152
+ pub fn kind(&self) -> &'static str {
153
+ self.raw_node.kind()
154
+ }
155
+
156
+ pub fn kind_id(&self) -> u16 {
157
+ self.raw_node.kind_id()
158
+ }
159
+
160
+ pub fn grammar_id(&self) -> u16 {
161
+ self.raw_node.grammar_id()
162
+ }
163
+
164
+ pub fn grammar_name(&self) -> &'static str {
165
+ self.raw_node.grammar_name()
166
+ }
167
+
168
+ pub fn language(&self) -> LanguageRef<'_> {
169
+ let raw_lang_ref = self.raw_node.language();
170
+ LanguageRef {
171
+ raw_language_ref: raw_lang_ref,
172
+ }
173
+ }
174
+
175
+ pub fn is_named(&self) -> bool {
176
+ self.raw_node.is_named()
177
+ }
178
+
179
+ pub fn is_extra(&self) -> bool {
180
+ self.raw_node.is_extra()
181
+ }
182
+
183
+ pub fn has_changes(&self) -> bool {
184
+ self.raw_node.has_changes()
185
+ }
186
+
187
+ pub fn has_error(&self) -> bool {
188
+ self.raw_node.has_error()
189
+ }
190
+
191
+ pub fn is_error(&self) -> bool {
192
+ self.raw_node.is_error()
193
+ }
194
+
195
+ pub fn parse_state(&self) -> u16 {
196
+ self.raw_node.parse_state()
197
+ }
198
+
199
+ pub fn next_parse_state(&self) -> u16 {
200
+ self.raw_node.parse_state()
201
+ }
202
+
203
+ pub fn start_byte(&self) -> usize {
204
+ self.raw_node.start_byte()
205
+ }
206
+
207
+ pub fn end_byte(&self) -> usize {
208
+ self.raw_node.end_byte()
209
+ }
210
+
211
+ pub fn byte_range(&self) -> Range<usize> {
212
+ self.raw_node.byte_range()
213
+ }
214
+
215
+ pub fn range(&self) -> data::Range {
216
+ self.raw_node.range().into()
217
+ }
218
+
219
+ pub fn start_position(&self) -> Point {
220
+ self.raw_node.start_position().into()
221
+ }
222
+
223
+ pub fn end_position(&self) -> Point {
224
+ self.raw_node.end_position().into()
225
+ }
226
+
227
+ pub fn child(&self, index: usize) -> Option<Self> {
228
+ self.raw_node.child(index).map(|node| Self {
229
+ raw_tree: Arc::clone(&self.raw_tree),
230
+ raw_node: node,
231
+ })
232
+ }
233
+
234
+ pub fn child_count(&self) -> usize {
235
+ self.raw_node.child_count()
236
+ }
237
+
238
+ pub fn named_child(&self, index: usize) -> Option<Self> {
239
+ self.raw_node.named_child(index).map(|node| Self {
240
+ raw_tree: Arc::clone(&self.raw_tree),
241
+ raw_node: node,
242
+ })
243
+ }
244
+
245
+ pub fn named_child_count(&self) -> usize {
246
+ self.raw_node.named_child_count()
247
+ }
248
+
249
+ pub fn child_by_field_name(&self, field_name: String) -> Option<Self> {
250
+ self.raw_node
251
+ .child_by_field_name(field_name)
252
+ .map(|node| Self {
253
+ raw_tree: Arc::clone(&self.raw_tree),
254
+ raw_node: node,
255
+ })
256
+ }
257
+
258
+ pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
259
+ self.raw_node.child_by_field_id(field_id).map(|node| Self {
260
+ raw_tree: Arc::clone(&self.raw_tree),
261
+ raw_node: node,
262
+ })
263
+ }
264
+
265
+ pub fn field_name_for_child(&self, child_index: u32) -> Option<&'static str> {
266
+ self.raw_node.field_name_for_child(child_index)
267
+ }
268
+
269
+ pub fn children<'cursor>(
270
+ ruby: &Ruby,
271
+ rb_self: typed_data::Obj<Self>,
272
+ ) -> Result<Yield<impl Iterator<Item = Value>>, Error> {
273
+ let mut cursor = rb_self.raw_node.walk();
274
+ let nodes = rb_self.raw_node.children(&mut cursor);
275
+ let array = ruby.ary_new_capa(nodes.len());
276
+ for n in nodes {
277
+ let node = Self {
278
+ raw_tree: Arc::clone(&rb_self.raw_tree),
279
+ raw_node: n,
280
+ };
281
+ array.push(node)?
282
+ }
283
+ array.freeze();
284
+
285
+ if ruby.block_given() {
286
+ Ok(Yield::Iter(array.into_iter()))
287
+ } else {
288
+ Ok(Yield::Enumerator(rb_self.enumeratorize("children", ())))
289
+ }
290
+ }
291
+
292
+ pub fn children_with_cursor<'cursor>(
293
+ ruby: &Ruby,
294
+ rb_self: typed_data::Obj<Self>,
295
+ cursor: typed_data::Obj<TreeCursor<'tree>>,
296
+ ) -> Result<Yield<impl Iterator<Item = Value>>, Error> {
297
+ let mut borrowed = cursor.raw_cursor.borrow_mut();
298
+ let nodes = rb_self.raw_node.children(&mut borrowed);
299
+ let array = ruby.ary_new_capa(nodes.len());
300
+ for n in nodes {
301
+ let node = Self {
302
+ raw_tree: Arc::clone(&rb_self.raw_tree),
303
+ raw_node: n,
304
+ };
305
+ array.push(node)?
306
+ }
307
+ array.freeze();
308
+
309
+ if ruby.block_given() {
310
+ Ok(Yield::Iter(array.into_iter()))
311
+ } else {
312
+ Ok(Yield::Enumerator(
313
+ rb_self.enumeratorize("children_with_cursor", ()),
314
+ ))
315
+ }
316
+ }
317
+
318
+ pub fn named_children_with_cursor<'cursor>(
319
+ ruby: &Ruby,
320
+ rb_self: typed_data::Obj<Self>,
321
+ cursor: typed_data::Obj<TreeCursor<'tree>>,
322
+ ) -> Result<Yield<impl Iterator<Item = Value>>, Error> {
323
+ let mut borrowed = cursor.raw_cursor.borrow_mut();
324
+ let nodes = rb_self.raw_node.named_children(&mut borrowed);
325
+ let array = ruby.ary_new_capa(nodes.len());
326
+ for n in nodes {
327
+ let node = Self {
328
+ raw_tree: Arc::clone(&rb_self.raw_tree),
329
+ raw_node: n,
330
+ };
331
+ array.push(node)?
332
+ }
333
+ array.freeze();
334
+
335
+ if ruby.block_given() {
336
+ Ok(Yield::Iter(array.into_iter()))
337
+ } else {
338
+ Ok(Yield::Enumerator(
339
+ rb_self.enumeratorize("named_children_with_cursor", [cursor]),
340
+ ))
341
+ }
342
+ }
343
+
344
+ pub fn children_by_field_name_with_cursor<'cursor>(
345
+ ruby: &Ruby,
346
+ rb_self: typed_data::Obj<Self>,
347
+ field_name: String,
348
+ cursor: typed_data::Obj<TreeCursor<'tree>>,
349
+ ) -> Result<Yield<impl Iterator<Item = Value>>, Error> {
350
+ let mut borrowed = cursor.raw_cursor.borrow_mut();
351
+ let nodes = rb_self
352
+ .raw_node
353
+ .children_by_field_name(&field_name, &mut borrowed);
354
+ let array = ruby.ary_new();
355
+ for n in nodes {
356
+ let node = Self {
357
+ raw_tree: Arc::clone(&rb_self.raw_tree),
358
+ raw_node: n,
359
+ };
360
+ array.push(node)?
361
+ }
362
+ array.freeze();
363
+
364
+ if ruby.block_given() {
365
+ Ok(Yield::Iter(array.into_iter()))
366
+ } else {
367
+ Ok(Yield::Enumerator(
368
+ rb_self.enumeratorize("named_children_with_cursor", [cursor]),
369
+ ))
370
+ }
371
+ }
372
+
373
+ pub fn children_by_field_id_with_cursor<'cursor>(
374
+ ruby: &Ruby,
375
+ rb_self: typed_data::Obj<Self>,
376
+ field_id: u16,
377
+ cursor: typed_data::Obj<TreeCursor<'tree>>,
378
+ ) -> Result<Yield<impl Iterator<Item = Value>>, Error> {
379
+ let mut borrowed = cursor.raw_cursor.borrow_mut();
380
+ let non_zero_field_id = match NonZero::new(field_id) {
381
+ Some(id) => Ok(id),
382
+ None => Err(build_error("field_id must be non-zero")),
383
+ }?;
384
+ let nodes = rb_self
385
+ .raw_node
386
+ .children_by_field_id(non_zero_field_id, &mut borrowed);
387
+ let array = ruby.ary_new();
388
+ for n in nodes {
389
+ let node = Self {
390
+ raw_tree: Arc::clone(&rb_self.raw_tree),
391
+ raw_node: n,
392
+ };
393
+ array.push(node)?
394
+ }
395
+ array.freeze();
396
+
397
+ if ruby.block_given() {
398
+ Ok(Yield::Iter(array.into_iter()))
399
+ } else {
400
+ Ok(Yield::Enumerator(
401
+ rb_self.enumeratorize("named_children_with_cursor", [cursor]),
402
+ ))
403
+ }
404
+ }
405
+
406
+ pub fn parent(&self) -> Option<Self> {
407
+ self.raw_node.parent().map(|node| Self {
408
+ raw_tree: Arc::clone(&self.raw_tree),
409
+ raw_node: node,
410
+ })
411
+ }
412
+
413
+ pub fn child_containing_descendant(
414
+ &self,
415
+ descendant: typed_data::Obj<Self>,
416
+ ) -> Result<Option<Self>, Error> {
417
+ Ok(self
418
+ .raw_node
419
+ .child_containing_descendant(descendant.raw_node)
420
+ .map(|node| Self {
421
+ raw_tree: Arc::clone(&self.raw_tree),
422
+ raw_node: node,
423
+ }))
424
+ }
425
+
426
+ pub fn next_sibling(&self) -> Option<Self> {
427
+ self.raw_node.next_sibling().map(|node| Self {
428
+ raw_tree: Arc::clone(&self.raw_tree),
429
+ raw_node: node,
430
+ })
431
+ }
432
+
433
+ pub fn prev_sibling(&self) -> Option<Self> {
434
+ self.raw_node.prev_sibling().map(|node| Self {
435
+ raw_tree: Arc::clone(&self.raw_tree),
436
+ raw_node: node,
437
+ })
438
+ }
439
+
440
+ pub fn next_named_sibling(&self) -> Option<Self> {
441
+ self.raw_node.next_named_sibling().map(|node| Self {
442
+ raw_tree: Arc::clone(&self.raw_tree),
443
+ raw_node: node,
444
+ })
445
+ }
446
+
447
+ pub fn prev_named_sibling(&self) -> Option<Self> {
448
+ self.raw_node.prev_named_sibling().map(|node| Self {
449
+ raw_tree: Arc::clone(&self.raw_tree),
450
+ raw_node: node,
451
+ })
452
+ }
453
+
454
+ pub fn descendant_count(&self) -> usize {
455
+ self.raw_node.descendant_count()
456
+ }
457
+
458
+ pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
459
+ self.raw_node
460
+ .descendant_for_byte_range(start, end)
461
+ .map(|node| Self {
462
+ raw_tree: Arc::clone(&self.raw_tree),
463
+ raw_node: node,
464
+ })
465
+ }
466
+
467
+ pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
468
+ self.raw_node
469
+ .named_descendant_for_byte_range(start, end)
470
+ .map(|node| Self {
471
+ raw_tree: Arc::clone(&self.raw_tree),
472
+ raw_node: node,
473
+ })
474
+ }
475
+
476
+ pub fn descendant_for_point_range(
477
+ &self,
478
+ start: (usize, usize),
479
+ end: (usize, usize),
480
+ ) -> Option<Self> {
481
+ let start = tree_sitter::Point::new(start.0, start.1);
482
+ let end = tree_sitter::Point::new(end.0, end.1);
483
+ self.raw_node
484
+ .descendant_for_point_range(start, end)
485
+ .map(|node| Self {
486
+ raw_tree: Arc::clone(&self.raw_tree),
487
+ raw_node: node,
488
+ })
489
+ }
490
+
491
+ pub fn named_descendant_for_point_range(
492
+ &self,
493
+ start: (usize, usize),
494
+ end: (usize, usize),
495
+ ) -> Option<Self> {
496
+ let start = tree_sitter::Point::new(start.0, start.1);
497
+ let end = tree_sitter::Point::new(end.0, end.1);
498
+ self.raw_node
499
+ .descendant_for_point_range(start, end)
500
+ .map(|node| Self {
501
+ raw_tree: Arc::clone(&self.raw_tree),
502
+ raw_node: node,
503
+ })
504
+ }
505
+
506
+ pub fn to_sexp(&self) -> String {
507
+ self.raw_node.to_sexp()
508
+ }
509
+
510
+ pub fn utf8_text(&self, source: String) -> String {
511
+ self.raw_node
512
+ .utf8_text(source.as_bytes())
513
+ .unwrap()
514
+ .to_string()
515
+ }
516
+
517
+ pub fn walk(&self) -> TreeCursor {
518
+ TreeCursor {
519
+ raw_tree: Arc::clone(&self.raw_tree),
520
+ raw_cursor: RefCell::new(self.raw_node.walk()),
521
+ }
522
+ }
523
+
524
+ pub fn inspect(&self) -> String {
525
+ format!("{:?}", self.raw_node)
526
+ }
527
+
528
+ pub fn to_s(&self) -> String {
529
+ format!("{}", self.raw_node)
530
+ }
531
+ }
@@ -0,0 +1,19 @@
1
+ use std::borrow::Cow;
2
+
3
+ use magnus::{
4
+ gc::register_mark_object,
5
+ value::{InnerValue, Lazy},
6
+ ExceptionClass, Ruby,
7
+ };
8
+
9
+ static ERROR_CLASS: Lazy<ExceptionClass> = Lazy::new(|ruby| {
10
+ let ex = ExceptionClass::from_value(ruby.eval("TreeStump::Error").unwrap()).unwrap();
11
+ register_mark_object(ex);
12
+ ex
13
+ });
14
+
15
+ pub fn build_error(message: impl Into<Cow<'static, str>>) -> magnus::Error {
16
+ let ruby = Ruby::get().expect("Not in Ruby thread");
17
+ let error_class = ERROR_CLASS.get_inner_with(&ruby);
18
+ magnus::Error::new(error_class, message)
19
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeStump
4
+ VERSION = "0.1.0"
5
+ end
data/lib/tree_stump.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tree_stump/version"
4
+
5
+ module TreeStump
6
+ class Error < StandardError;
7
+ def initialize(msg)
8
+ super(msg)
9
+ end
10
+ end
11
+
12
+ class QueryError < Error; end
13
+ end
14
+
15
+ require_relative "tree_stump/tree_stump"
@@ -0,0 +1,4 @@
1
+ module TreeStump
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tree_stump
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - joker1007
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Ruby bindings for Tree-sitter written in Rust
28
+ email:
29
+ - kakyoin.hierophant@gmail.com
30
+ executables: []
31
+ extensions:
32
+ - ext/tree_stump/Cargo.toml
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rspec"
36
+ - Cargo.lock
37
+ - Cargo.toml
38
+ - README.md
39
+ - Rakefile
40
+ - ext/tree_stump/Cargo.toml
41
+ - ext/tree_stump/extconf.rb
42
+ - ext/tree_stump/src/data.rs
43
+ - ext/tree_stump/src/language.rs
44
+ - ext/tree_stump/src/lib.rs
45
+ - ext/tree_stump/src/parser.rs
46
+ - ext/tree_stump/src/query.rs
47
+ - ext/tree_stump/src/tree.rs
48
+ - ext/tree_stump/src/util.rs
49
+ - lib/tree_stump.rb
50
+ - lib/tree_stump/version.rb
51
+ - sig/tree_house.rbs
52
+ homepage: https://github.com/joker1007/tree_stump
53
+ licenses: []
54
+ metadata:
55
+ homepage_uri: https://github.com/joker1007/tree_stump
56
+ source_code_uri: https://github.com/joker1007/tree_stump
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 3.1.0
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.3.11
71
+ requirements: []
72
+ rubygems_version: 3.5.11
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Ruby bindings for Tree-sitter written in Rust
76
+ test_files: []