ruby_tree_sitter 0.20.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +152 -0
  4. data/ext/tree_sitter/encoding.c +29 -0
  5. data/ext/tree_sitter/extconf.rb +172 -0
  6. data/ext/tree_sitter/input.c +126 -0
  7. data/ext/tree_sitter/input_edit.c +42 -0
  8. data/ext/tree_sitter/language.c +134 -0
  9. data/ext/tree_sitter/logger.c +212 -0
  10. data/ext/tree_sitter/macros.h +163 -0
  11. data/ext/tree_sitter/node.c +310 -0
  12. data/ext/tree_sitter/parser.c +203 -0
  13. data/ext/tree_sitter/point.c +26 -0
  14. data/ext/tree_sitter/quantifier.c +43 -0
  15. data/ext/tree_sitter/query.c +157 -0
  16. data/ext/tree_sitter/query_capture.c +28 -0
  17. data/ext/tree_sitter/query_cursor.c +103 -0
  18. data/ext/tree_sitter/query_error.c +41 -0
  19. data/ext/tree_sitter/query_match.c +44 -0
  20. data/ext/tree_sitter/query_predicate_step.c +83 -0
  21. data/ext/tree_sitter/range.c +35 -0
  22. data/ext/tree_sitter/symbol_type.c +46 -0
  23. data/ext/tree_sitter/tree.c +145 -0
  24. data/ext/tree_sitter/tree_cursor.c +97 -0
  25. data/ext/tree_sitter/tree_sitter.c +32 -0
  26. data/ext/tree_sitter/tree_sitter.h +107 -0
  27. data/lib/tree_sitter/node.rb +164 -0
  28. data/lib/tree_sitter/version.rb +5 -0
  29. data/lib/tree_sitter.rb +13 -0
  30. data/test/README.md +15 -0
  31. data/test/test_helper.rb +9 -0
  32. data/test/tree_sitter/language_test.rb +68 -0
  33. data/test/tree_sitter/logger_test.rb +69 -0
  34. data/test/tree_sitter/node_test.rb +355 -0
  35. data/test/tree_sitter/parser_test.rb +140 -0
  36. data/test/tree_sitter/query_test.rb +153 -0
  37. data/test/tree_sitter/tree_cursor_test.rb +83 -0
  38. data/test/tree_sitter/tree_test.rb +51 -0
  39. data/tree_sitter.gemspec +32 -0
  40. metadata +189 -0
@@ -0,0 +1,212 @@
1
+ #include "tree_sitter.h"
2
+
3
+ extern VALUE mTreeSitter;
4
+
5
+ VALUE cLogger;
6
+
7
+ // This type is layed out in the DATA_* style.
8
+ // data: the TSLogger object
9
+ // payload: what will be used in TSLogger.log()
10
+ // therefore: data.payload = payload
11
+ // format: optional formatting string. Passed to "printf" if it exists
12
+ typedef struct {
13
+ TSLogger data;
14
+ VALUE payload;
15
+ VALUE format;
16
+ } logger_t;
17
+
18
+ static const char *logger_log_type_str(TSLogType log_type) {
19
+ switch (log_type) {
20
+ case TSLogTypeParse:
21
+ return "Parse:";
22
+ case TSLogTypeLex:
23
+ return "Lex :";
24
+ default:
25
+ return "?????:";
26
+ }
27
+ }
28
+
29
+ static void logger_log_printf(void *ptr, TSLogType log_type,
30
+ const char *message) {
31
+ logger_t *logger = (logger_t *)ptr;
32
+ VALUE type = safe_str(logger_log_type_str(log_type));
33
+ VALUE msg = safe_str(message);
34
+ rb_funcall(logger->payload, rb_intern("printf"), 3, logger->format, type,
35
+ msg);
36
+ }
37
+
38
+ static void logger_log_puts(void *ptr, TSLogType log_type,
39
+ const char *message) {
40
+ logger_t *logger = (logger_t *)ptr;
41
+ const char *format =
42
+ NIL_P(logger->format) ? "%s %s" : StringValueCStr(logger->format);
43
+ VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
44
+ rb_funcall(logger->payload, rb_intern("puts"), 1, str);
45
+ }
46
+
47
+ static void logger_log_write(void *ptr, TSLogType log_type,
48
+ const char *message) {
49
+ logger_t *logger = (logger_t *)ptr;
50
+ const char *format =
51
+ NIL_P(logger->format) ? "%s %s\n" : StringValueCStr(logger->format);
52
+ VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
53
+ rb_funcall(logger->payload, rb_intern("write"), 1, str);
54
+ }
55
+
56
+ static void logger_payload_set(logger_t *logger, VALUE value) {
57
+ logger->payload = value;
58
+ logger->data.payload = (void *)logger;
59
+
60
+ if (!NIL_P(logger->format) && !NIL_P(logger->payload)) {
61
+ if (rb_respond_to(logger->payload, rb_intern("printf"))) {
62
+ logger->data.log = logger_log_printf;
63
+ } else if (rb_respond_to(logger->payload, rb_intern("puts"))) {
64
+ logger->data.log = &logger_log_puts;
65
+ } else {
66
+ logger->data.log = &logger_log_write;
67
+ }
68
+ } else if (!NIL_P(logger->payload)) {
69
+ logger->data.log = &logger_log_write;
70
+ }
71
+ }
72
+
73
+ static void logger_free(void *ptr) { xfree(ptr); }
74
+
75
+ static size_t logger_memsize(const void *ptr) {
76
+ logger_t *type = (logger_t *)ptr;
77
+ return sizeof(type);
78
+ }
79
+
80
+ static void logger_mark(void *ptr) {
81
+ logger_t *logger = (logger_t *)ptr;
82
+ rb_gc_mark_movable(logger->payload);
83
+ // we don't want format to move because its reference will be
84
+ // consumed by the parser.
85
+ //
86
+ // No funny things please.
87
+ rb_gc_mark(logger->format);
88
+ }
89
+
90
+ static void logger_compact(void *ptr) {
91
+ logger_t *logger = (logger_t *)ptr;
92
+ logger->payload = rb_gc_location(logger->payload);
93
+ }
94
+
95
+ const rb_data_type_t logger_data_type = {
96
+ .wrap_struct_name = "logger",
97
+ .function =
98
+ {
99
+ .dmark = logger_mark,
100
+ .dfree = logger_free,
101
+ .dsize = logger_memsize,
102
+ .dcompact = logger_compact,
103
+ },
104
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
105
+ };
106
+
107
+ DATA_UNWRAP(logger)
108
+
109
+ static VALUE logger_allocate(VALUE klass) {
110
+ logger_t *logger;
111
+ return TypedData_Make_Struct(klass, logger_t, &logger_data_type, logger);
112
+ }
113
+
114
+ VALUE new_logger(const TSLogger *ptr) {
115
+ if (ptr != NULL) {
116
+ VALUE res = logger_allocate(cLogger);
117
+ logger_t *logger = unwrap(res);
118
+
119
+ logger->data.payload = logger;
120
+
121
+ VALUE payload = Qnil;
122
+ VALUE format = Qnil;
123
+ if (ptr->payload != NULL) {
124
+ logger_t *old_logger = (logger_t *)ptr->payload;
125
+ payload = old_logger->payload;
126
+ format = old_logger->format;
127
+ }
128
+ logger_payload_set(logger, payload);
129
+ logger->format = format;
130
+
131
+ return res;
132
+ } else {
133
+ return Qnil;
134
+ }
135
+ }
136
+
137
+ VALUE new_logger_by_val(TSLogger val) { return new_logger(&val); }
138
+
139
+ TSLogger value_to_logger(VALUE self) { return SELF; }
140
+
141
+ static void logger_initialize_stderr(logger_t *logger) {
142
+ VALUE stderr = rb_gv_get("$stderr");
143
+ if (!NIL_P(stderr)) {
144
+ logger_payload_set(logger, stderr);
145
+ } else {
146
+ logger_payload_set(logger, Qnil);
147
+ }
148
+ }
149
+
150
+ // For now, we only take:
151
+ // argv[0] = stream
152
+ // argv[1] = format : String
153
+ //
154
+ // We need to add support for argv[1] : lambda/block
155
+ //
156
+ // case argv[1]
157
+ // in lambda => lambda
158
+ // in String => puts || printf || write
159
+ // else => write
160
+ // end
161
+ //
162
+ static VALUE logger_initialize(int argc, VALUE *argv, VALUE self) {
163
+ logger_t *logger = unwrap(self);
164
+
165
+ VALUE payload;
166
+ VALUE format;
167
+ rb_scan_args(argc, argv, "02", &payload, &format);
168
+
169
+ logger->format = format;
170
+
171
+ if (argc == 0) {
172
+ logger_initialize_stderr(logger);
173
+ } else {
174
+ logger_payload_set(logger, payload);
175
+ }
176
+
177
+ return self;
178
+ }
179
+
180
+ static VALUE logger_inspect(VALUE self) {
181
+ logger_t *logger = unwrap(self);
182
+ return rb_sprintf("{payload=%+" PRIsVALUE ", format=%+" PRIsVALUE "}",
183
+ logger->payload, logger->format);
184
+ }
185
+
186
+ DATA_FAST_FORWARD_FNV(logger, write, payload)
187
+ DATA_FAST_FORWARD_FNV(logger, puts, payload)
188
+ DATA_FAST_FORWARD_FNV(logger, printf, payload)
189
+
190
+ DEFINE_ACCESSOR(logger, format)
191
+ DEFINE_GETTER(logger, payload)
192
+
193
+ static VALUE logger_set_payload(VALUE self, VALUE payload) {
194
+ logger_payload_set(unwrap(self), payload);
195
+ return Qnil;
196
+ }
197
+
198
+ void init_logger(void) {
199
+ cLogger = rb_define_class_under(mTreeSitter, "Logger", rb_cObject);
200
+
201
+ rb_define_alloc_func(cLogger, logger_allocate);
202
+
203
+ /* Class methods */
204
+ rb_define_method(cLogger, "initialize", logger_initialize, -1);
205
+ DECLARE_ACCESSOR(cLogger, logger, format)
206
+ DECLARE_ACCESSOR(cLogger, logger, payload)
207
+ rb_define_method(cLogger, "write", logger_write, -1);
208
+ rb_define_method(cLogger, "puts", logger_puts, -1);
209
+ rb_define_method(cLogger, "printf", logger_printf, -1);
210
+ rb_define_method(cLogger, "inspect", logger_inspect, 0);
211
+ rb_define_method(cLogger, "to_s", logger_inspect, 0);
212
+ }
@@ -0,0 +1,163 @@
1
+ #ifndef _RB_TREE_SITTER_MACROS_H
2
+ #define _RB_TREE_SITTER_MACROS_H
3
+
4
+ #define DECLARE_GETTER(klass, type, field) \
5
+ rb_define_method(klass, #field, type##_get_##field, 0);
6
+
7
+ #define DECLARE_SETTER(klass, type, field) \
8
+ rb_define_method(klass, #field "=", type##_set_##field, 1);
9
+
10
+ #define DECLARE_ACCESSOR(klass, type, field) \
11
+ DECLARE_GETTER(klass, type, field) \
12
+ DECLARE_SETTER(klass, type, field)
13
+
14
+ // Plain DEFINE_GETTER/DEFINE_SETTER/etc are for TypedData structs, reaching
15
+ // their top-level fields, and are of type VALUE
16
+ //
17
+ // DATA_* are for TypeData structs, raching their data field
18
+ // which can be of an arbitraty tuype.
19
+
20
+ #define DEFINE_GETTER(type, field) \
21
+ static VALUE type##_get_##field(VALUE self) { return (unwrap(self))->field; }
22
+
23
+ #define DEFINE_SETTER(type, field) \
24
+ static VALUE type##_set_##field(VALUE self, VALUE val) { \
25
+ unwrap(self)->field = val; \
26
+ return Qnil; \
27
+ }
28
+
29
+ #define DEFINE_ACCESSOR(type, field) \
30
+ DEFINE_GETTER(type, field) \
31
+ DEFINE_SETTER(type, field)
32
+
33
+ #define DATA_WRAP(base, type) \
34
+ DATA_TYPE(TS##base, type) \
35
+ DATA_FREE(type) \
36
+ DATA_MEMSIZE(type) \
37
+ DATA_DECLARE_DATA_TYPE(type) \
38
+ DATA_ALLOCATE(type) \
39
+ DATA_UNWRAP(type) \
40
+ DATA_NEW(c##base, TS##base, type) \
41
+ DATA_FROM_VALUE(TS##base, type)
42
+
43
+ #define DATA_PTR_WRAP(base, type) \
44
+ DATA_TYPE(TS##base *, type) \
45
+ DATA_FREE_PTR(type) \
46
+ DATA_MEMSIZE(type) \
47
+ DATA_DECLARE_DATA_TYPE(type) \
48
+ DATA_ALLOCATE(type) \
49
+ DATA_UNWRAP(type) \
50
+ DATA_PTR_NEW(c##base, TS##base, type) \
51
+ DATA_FROM_VALUE(TS##base *, type)
52
+
53
+ #define DATA_TYPE(klass, type) \
54
+ typedef struct { \
55
+ klass data; \
56
+ } type##_t;
57
+
58
+ #define DATA_FREE(type) \
59
+ static void type##_free(void *ptr) { xfree(ptr); }
60
+
61
+ #define DATA_FREE_PTR(type) \
62
+ static void type##_free(void *ptr) { \
63
+ type##_t *type = (type##_t *)ptr; \
64
+ if (type->data != NULL) { \
65
+ ts_##type##_delete(type->data); \
66
+ } \
67
+ xfree(ptr); \
68
+ }
69
+
70
+ #define DATA_MEMSIZE(type) \
71
+ static size_t type##_memsize(const void *ptr) { \
72
+ type##_t *type = (type##_t *)ptr; \
73
+ return sizeof(type); \
74
+ }
75
+
76
+ #define DATA_DECLARE_DATA_TYPE(type) \
77
+ const rb_data_type_t type##_data_type = { \
78
+ .wrap_struct_name = #type "", \
79
+ .function = \
80
+ { \
81
+ .dmark = NULL, \
82
+ .dfree = type##_free, \
83
+ .dsize = type##_memsize, \
84
+ .dcompact = NULL, \
85
+ }, \
86
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY, \
87
+ };
88
+
89
+ #define DATA_ALLOCATE(type) \
90
+ static VALUE type##_allocate(VALUE klass) { \
91
+ type##_t *type; \
92
+ return TypedData_Make_Struct(klass, type##_t, &type##_data_type, type); \
93
+ }
94
+
95
+ #define DATA_UNWRAP(type) \
96
+ static type##_t *unwrap(VALUE self) { \
97
+ type##_t *type; \
98
+ TypedData_Get_Struct(self, type##_t, &type##_data_type, type); \
99
+ return type; \
100
+ }
101
+
102
+ #define SELF unwrap(self)->data
103
+
104
+ #define DATA_NEW(klass, struct, type) \
105
+ VALUE new_##type(const struct *ptr) { \
106
+ if (ptr == NULL) { \
107
+ return Qnil; \
108
+ } \
109
+ VALUE res = type##_allocate(klass); \
110
+ type##_t *type = unwrap(res); \
111
+ type->data = *ptr; \
112
+ return res; \
113
+ } \
114
+ VALUE new_##type##_by_val(struct ptr) { \
115
+ VALUE res = type##_allocate(klass); \
116
+ type##_t *type = unwrap(res); \
117
+ type->data = ptr; \
118
+ return res; \
119
+ }
120
+
121
+ #define DATA_FROM_VALUE(struct, type) \
122
+ struct value_to_##type(VALUE self) { \
123
+ return (unwrap(self))->data; \
124
+ }
125
+
126
+ #define DATA_PTR_NEW(klass, struct, type) \
127
+ VALUE new_##type(struct *ptr) { \
128
+ if (ptr == NULL) { \
129
+ return Qnil; \
130
+ } \
131
+ VALUE res = type##_allocate(klass); \
132
+ type##_t *type = unwrap(res); \
133
+ type->data = ptr; \
134
+ return res; \
135
+ }
136
+
137
+ #define DATA_DEFINE_GETTER(type, field, cast) \
138
+ static VALUE type##_get_##field(VALUE self) { \
139
+ return cast((unwrap(self))->data.field); \
140
+ }
141
+
142
+ #define DATA_DEFINE_SETTER(type, field, cast) \
143
+ static VALUE type##_set_##field(VALUE self, VALUE val) { \
144
+ type##_t *type = unwrap(self); \
145
+ type->data.field = cast(val); \
146
+ return Qnil; \
147
+ }
148
+
149
+ #define DATA_DEFINE_ACCESSOR(type, field, cast_get, cast_set) \
150
+ DATA_DEFINE_GETTER(type, field, cast_get) \
151
+ DATA_DEFINE_SETTER(type, field, cast_set)
152
+
153
+ #define DATA_FAST_FORWARD_FNV(type, fn, field) \
154
+ static VALUE type##_##fn(int argc, VALUE *argv, VALUE self) { \
155
+ type##_t *type = unwrap(self); \
156
+ if (!NIL_P(type->field)) { \
157
+ return rb_funcallv(type->field, rb_intern(#fn ""), argc, argv); \
158
+ } else { \
159
+ return Qnil; \
160
+ } \
161
+ }
162
+
163
+ #endif
@@ -0,0 +1,310 @@
1
+ #include "tree_sitter.h"
2
+ #include "tree_sitter/api.h"
3
+
4
+ extern VALUE mTreeSitter;
5
+
6
+ VALUE cNode;
7
+
8
+ DATA_TYPE(TSNode, node)
9
+
10
+ static void node_free(void *ptr) {
11
+ node_t *type = (node_t *)ptr;
12
+ tree_rc_free(type->data.tree);
13
+ xfree(ptr);
14
+ }
15
+
16
+ DATA_MEMSIZE(node)
17
+ DATA_DECLARE_DATA_TYPE(node)
18
+ DATA_ALLOCATE(node)
19
+ DATA_UNWRAP(node)
20
+
21
+ VALUE new_node(const TSNode *ptr) {
22
+ if (ptr == NULL) {
23
+ return Qnil;
24
+ }
25
+ VALUE res = node_allocate(cNode);
26
+ node_t *type = unwrap(res);
27
+ type->data = *ptr;
28
+ tree_rc_new(type->data.tree);
29
+ return res;
30
+ }
31
+ VALUE new_node_by_val(TSNode ptr) {
32
+ VALUE res = node_allocate(cNode);
33
+ node_t *type = unwrap(res);
34
+ type->data = ptr;
35
+ tree_rc_new(type->data.tree);
36
+ return res;
37
+ }
38
+
39
+ DATA_FROM_VALUE(TSNode, node)
40
+
41
+ static VALUE node_type(VALUE self) { return safe_symbol(ts_node_type(SELF)); }
42
+
43
+ static VALUE node_symbol(VALUE self) { return UINT2NUM(ts_node_symbol(SELF)); }
44
+
45
+ static VALUE node_start_byte(VALUE self) {
46
+ return UINT2NUM(ts_node_start_byte(SELF));
47
+ }
48
+
49
+ static VALUE node_start_point(VALUE self) {
50
+ return new_point_by_val(ts_node_start_point(SELF));
51
+ }
52
+
53
+ static VALUE node_end_byte(VALUE self) {
54
+ return UINT2NUM(ts_node_end_byte(SELF));
55
+ }
56
+
57
+ static VALUE node_end_point(VALUE self) {
58
+ return new_point_by_val(ts_node_end_point(SELF));
59
+ }
60
+
61
+ static VALUE node_string(VALUE self) {
62
+ char *str = ts_node_string(SELF);
63
+ VALUE res = safe_str(str);
64
+ if (str) {
65
+ free(str);
66
+ }
67
+ return res;
68
+ }
69
+
70
+ static VALUE node_is_null(VALUE self) {
71
+ return ts_node_is_null(SELF) ? Qtrue : Qfalse;
72
+ }
73
+
74
+ static VALUE node_is_named(VALUE self) {
75
+ return ts_node_is_named(SELF) ? Qtrue : Qfalse;
76
+ }
77
+
78
+ static VALUE node_is_missing(VALUE self) {
79
+ return ts_node_is_missing(SELF) ? Qtrue : Qfalse;
80
+ }
81
+
82
+ static VALUE node_is_extra(VALUE self) {
83
+ return ts_node_is_extra(SELF) ? Qtrue : Qfalse;
84
+ }
85
+
86
+ static VALUE node_has_changes(VALUE self) {
87
+ return ts_node_has_changes(SELF) ? Qtrue : Qfalse;
88
+ }
89
+
90
+ static VALUE node_has_error(VALUE self) {
91
+ return ts_node_has_error(SELF) ? Qtrue : Qfalse;
92
+ }
93
+
94
+ static VALUE node_parent(VALUE self) {
95
+ return new_node_by_val(ts_node_parent(SELF));
96
+ }
97
+
98
+ static VALUE node_child(VALUE self, VALUE idx) {
99
+ TSNode node = SELF;
100
+ uint32_t index = NUM2UINT(idx);
101
+ uint32_t range = ts_node_child_count(node);
102
+
103
+ if (index < range) {
104
+ return new_node_by_val(ts_node_child(node, index));
105
+ } else {
106
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
107
+ range);
108
+ }
109
+ }
110
+
111
+ static VALUE node_field_name_for_child(VALUE self, VALUE idx) {
112
+ TSNode node = SELF;
113
+ uint32_t index = NUM2UINT(idx);
114
+ uint32_t range = ts_node_child_count(node);
115
+
116
+ if (index < range) {
117
+ return safe_str(ts_node_field_name_for_child(node, index));
118
+ } else {
119
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
120
+ range);
121
+ }
122
+ }
123
+
124
+ static VALUE node_child_count(VALUE self) {
125
+ TSNode node = SELF;
126
+ const char *type = ts_node_type(node);
127
+ if (strcmp(type, "end") == 0) {
128
+ return UINT2NUM(0);
129
+ } else {
130
+ return UINT2NUM(ts_node_child_count(SELF));
131
+ }
132
+ }
133
+
134
+ static VALUE node_named_child(VALUE self, VALUE idx) {
135
+ TSNode node = SELF;
136
+ uint32_t index = NUM2UINT(idx);
137
+ uint32_t range = ts_node_named_child_count(node);
138
+
139
+ if (index < range) {
140
+ return new_node_by_val(ts_node_named_child(node, index));
141
+ } else {
142
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
143
+ range);
144
+ }
145
+ }
146
+
147
+ static VALUE node_named_child_count(VALUE self) {
148
+ return UINT2NUM(ts_node_named_child_count(SELF));
149
+ }
150
+
151
+ static VALUE node_child_by_field_name(VALUE self, VALUE field_name) {
152
+ const char *name = StringValuePtr(field_name);
153
+ uint32_t length = (uint32_t)RSTRING_LEN(field_name);
154
+ return new_node_by_val(ts_node_child_by_field_name(SELF, name, length));
155
+ }
156
+
157
+ static VALUE node_child_by_field_id(VALUE self, VALUE field_id) {
158
+ return new_node_by_val(ts_node_child_by_field_id(SELF, NUM2UINT(field_id)));
159
+ }
160
+
161
+ static VALUE node_next_sibling(VALUE self) {
162
+ return new_node_by_val(ts_node_next_sibling(SELF));
163
+ }
164
+
165
+ static VALUE node_prev_sibling(VALUE self) {
166
+ return new_node_by_val(ts_node_prev_sibling(SELF));
167
+ }
168
+
169
+ static VALUE node_next_named_sibling(VALUE self) {
170
+ return new_node_by_val(ts_node_next_named_sibling(SELF));
171
+ }
172
+
173
+ static VALUE node_prev_named_sibling(VALUE self) {
174
+ return new_node_by_val(ts_node_prev_named_sibling(SELF));
175
+ }
176
+
177
+ static VALUE node_first_child_for_byte(VALUE self, VALUE byte) {
178
+ return new_node_by_val(ts_node_first_child_for_byte(SELF, NUM2UINT(byte)));
179
+ }
180
+
181
+ static VALUE node_first_named_child_for_byte(VALUE self, VALUE byte) {
182
+ return new_node_by_val(
183
+ ts_node_first_named_child_for_byte(SELF, NUM2UINT(byte)));
184
+ }
185
+
186
+ static VALUE node_descendant_for_byte_range(VALUE self, VALUE from, VALUE to) {
187
+ uint32_t from_b = NUM2UINT(from);
188
+ uint32_t to_b = NUM2UINT(to);
189
+
190
+ if (from_b > to_b) {
191
+ rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
192
+ } else {
193
+ return new_node_by_val(
194
+ ts_node_descendant_for_byte_range(SELF, from_b, to_b));
195
+ }
196
+ }
197
+
198
+ static VALUE node_descendant_for_point_range(VALUE self, VALUE from, VALUE to) {
199
+ TSNode node = SELF;
200
+ TSPoint start = ts_node_start_point(node);
201
+ TSPoint end = ts_node_end_point(node);
202
+ TSPoint f = value_to_point(from);
203
+ TSPoint t = value_to_point(to);
204
+
205
+ if ((f.row < start.row) || (t.row > end.row) ||
206
+ (f.row == start.row && (f.column < start.column)) ||
207
+ (t.row == end.row && (t.column > end.column))) {
208
+ rb_raise(rb_eIndexError,
209
+ "Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
210
+ "] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
211
+ from, to, new_point(&start), new_point(&end));
212
+ } else {
213
+ return new_node_by_val(ts_node_descendant_for_point_range(node, f, t));
214
+ }
215
+ }
216
+
217
+ static VALUE node_named_descendant_for_byte_range(VALUE self, VALUE from,
218
+ VALUE to) {
219
+ uint32_t from_b = NUM2UINT(from);
220
+ uint32_t to_b = NUM2UINT(to);
221
+
222
+ if (from_b > to_b) {
223
+ rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
224
+ } else {
225
+ return new_node_by_val(
226
+ ts_node_named_descendant_for_byte_range(SELF, from_b, to_b));
227
+ }
228
+ }
229
+
230
+ static VALUE node_named_descendant_for_point_range(VALUE self, VALUE from,
231
+ VALUE to) {
232
+ TSNode node = SELF;
233
+ TSPoint start = ts_node_start_point(node);
234
+ TSPoint end = ts_node_end_point(node);
235
+ TSPoint f = value_to_point(from);
236
+ TSPoint t = value_to_point(to);
237
+
238
+ if ((f.row < start.row) || (t.row > end.row) ||
239
+ (f.row == start.row && (f.column < start.column)) ||
240
+ (t.row == end.row && (t.column > end.column))) {
241
+ rb_raise(rb_eIndexError,
242
+ "Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
243
+ "] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
244
+ from, to, new_point(&start), new_point(&end));
245
+ } else {
246
+ return new_node_by_val(
247
+ ts_node_named_descendant_for_point_range(node, f, t));
248
+ }
249
+ }
250
+
251
+ static VALUE node_edit(VALUE self, VALUE input_edit) {
252
+ TSNode node = SELF;
253
+ TSInputEdit edit = value_to_input_edit(input_edit);
254
+ ts_node_edit(&node, &edit);
255
+
256
+ return Qnil;
257
+ }
258
+
259
+ static VALUE node_eq(VALUE self, VALUE other) {
260
+ return ts_node_eq(SELF, unwrap(other)->data) ? Qtrue : Qfalse;
261
+ }
262
+
263
+ void init_node(void) {
264
+ cNode = rb_define_class_under(mTreeSitter, "Node", rb_cObject);
265
+
266
+ rb_undef_alloc_func(cNode);
267
+
268
+ /* Class methods */
269
+ rb_define_method(cNode, "type", node_type, 0);
270
+ rb_define_method(cNode, "symbol", node_symbol, 0);
271
+ rb_define_method(cNode, "start_byte", node_start_byte, 0);
272
+ rb_define_method(cNode, "start_point", node_start_point, 0);
273
+ rb_define_method(cNode, "end_byte", node_end_byte, 0);
274
+ rb_define_method(cNode, "end_point", node_end_point, 0);
275
+ rb_define_method(cNode, "null?", node_is_null, 0);
276
+ rb_define_method(cNode, "named?", node_is_named, 0);
277
+ rb_define_method(cNode, "missing?", node_is_missing, 0);
278
+ rb_define_method(cNode, "extra?", node_is_extra, 0);
279
+ rb_define_method(cNode, "changed?", node_has_changes, 0);
280
+ rb_define_method(cNode, "error?", node_has_error, 0);
281
+ rb_define_method(cNode, "parent", node_parent, 0);
282
+ rb_define_method(cNode, "child", node_child, 1);
283
+ rb_define_method(cNode, "field_name_for_child", node_field_name_for_child, 1);
284
+ rb_define_method(cNode, "child_count", node_child_count, 0);
285
+ rb_define_method(cNode, "named_child", node_named_child, 1);
286
+ rb_define_method(cNode, "named_child_count", node_named_child_count, 0);
287
+ rb_define_method(cNode, "child_by_field_name", node_child_by_field_name, 1);
288
+ rb_define_method(cNode, "child_by_field_id", node_child_by_field_id, 1);
289
+ rb_define_method(cNode, "next_sibling", node_next_sibling, 0);
290
+ rb_define_method(cNode, "prev_sibling", node_prev_sibling, 0);
291
+ rb_define_method(cNode, "next_named_sibling", node_next_named_sibling, 0);
292
+ rb_define_method(cNode, "prev_named_sibling", node_prev_named_sibling, 0);
293
+ rb_define_method(cNode, "first_child_for_byte", node_first_child_for_byte, 1);
294
+ rb_define_method(cNode, "first_named_child_for_byte",
295
+ node_first_named_child_for_byte, 1);
296
+ rb_define_method(cNode, "descendant_for_byte_range",
297
+ node_descendant_for_byte_range, 2);
298
+ rb_define_method(cNode, "descendant_for_point_range",
299
+ node_descendant_for_point_range, 2);
300
+ rb_define_method(cNode, "named_descendant_for_byte_range",
301
+ node_named_descendant_for_byte_range, 2);
302
+ rb_define_method(cNode, "named_descendant_for_point_range",
303
+ node_named_descendant_for_point_range, 2);
304
+ rb_define_method(cNode, "eq?", node_eq, 1);
305
+ rb_define_method(cNode, "edit", node_edit, 1);
306
+ rb_define_method(cNode, "to_s", node_string, 0);
307
+ rb_define_method(cNode, "to_str", node_string, 0);
308
+ rb_define_method(cNode, "inspect", node_string, 0);
309
+ rb_define_method(cNode, "==", node_eq, 1);
310
+ }