tree_stump 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []