rubydex 0.1.0.beta1-x86_64-linux → 0.1.0.beta2-x86_64-linux
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.
- checksums.yaml +4 -4
- data/ext/rubydex/declaration.c +146 -0
- data/ext/rubydex/declaration.h +10 -0
- data/ext/rubydex/definition.c +234 -0
- data/ext/rubydex/definition.h +28 -0
- data/ext/rubydex/diagnostic.c +6 -0
- data/ext/rubydex/diagnostic.h +11 -0
- data/ext/rubydex/document.c +98 -0
- data/ext/rubydex/document.h +10 -0
- data/ext/rubydex/extconf.rb +36 -15
- data/ext/rubydex/graph.c +405 -0
- data/ext/rubydex/graph.h +10 -0
- data/ext/rubydex/handle.h +44 -0
- data/ext/rubydex/location.c +22 -0
- data/ext/rubydex/location.h +15 -0
- data/ext/rubydex/reference.c +104 -0
- data/ext/rubydex/reference.h +16 -0
- data/ext/rubydex/rubydex.c +22 -0
- data/ext/rubydex/utils.c +27 -0
- data/ext/rubydex/utils.h +13 -0
- data/lib/rubydex/3.2/rubydex.so +0 -0
- data/lib/rubydex/3.3/rubydex.so +0 -0
- data/lib/rubydex/3.4/rubydex.so +0 -0
- data/lib/rubydex/4.0/rubydex.so +0 -0
- data/lib/rubydex/librubydex_sys.so +0 -0
- data/lib/rubydex/version.rb +1 -1
- data/rust/Cargo.lock +1275 -0
- data/rust/Cargo.toml +23 -0
- data/rust/about.hbs +78 -0
- data/rust/about.toml +9 -0
- data/rust/rubydex/Cargo.toml +41 -0
- data/rust/rubydex/src/diagnostic.rs +108 -0
- data/rust/rubydex/src/errors.rs +28 -0
- data/rust/rubydex/src/indexing/local_graph.rs +172 -0
- data/rust/rubydex/src/indexing/ruby_indexer.rs +5397 -0
- data/rust/rubydex/src/indexing.rs +128 -0
- data/rust/rubydex/src/job_queue.rs +186 -0
- data/rust/rubydex/src/lib.rs +15 -0
- data/rust/rubydex/src/listing.rs +249 -0
- data/rust/rubydex/src/main.rs +116 -0
- data/rust/rubydex/src/model/comment.rs +24 -0
- data/rust/rubydex/src/model/declaration.rs +541 -0
- data/rust/rubydex/src/model/definitions.rs +1475 -0
- data/rust/rubydex/src/model/document.rs +111 -0
- data/rust/rubydex/src/model/encoding.rs +22 -0
- data/rust/rubydex/src/model/graph.rs +1387 -0
- data/rust/rubydex/src/model/id.rs +90 -0
- data/rust/rubydex/src/model/identity_maps.rs +54 -0
- data/rust/rubydex/src/model/ids.rs +32 -0
- data/rust/rubydex/src/model/name.rs +188 -0
- data/rust/rubydex/src/model/references.rs +129 -0
- data/rust/rubydex/src/model/string_ref.rs +44 -0
- data/rust/rubydex/src/model/visibility.rs +41 -0
- data/rust/rubydex/src/model.rs +13 -0
- data/rust/rubydex/src/offset.rs +70 -0
- data/rust/rubydex/src/position.rs +6 -0
- data/rust/rubydex/src/query.rs +103 -0
- data/rust/rubydex/src/resolution.rs +4421 -0
- data/rust/rubydex/src/stats/memory.rs +71 -0
- data/rust/rubydex/src/stats/timer.rs +126 -0
- data/rust/rubydex/src/stats.rs +9 -0
- data/rust/rubydex/src/test_utils/context.rs +226 -0
- data/rust/rubydex/src/test_utils/graph_test.rs +229 -0
- data/rust/rubydex/src/test_utils/local_graph_test.rs +166 -0
- data/rust/rubydex/src/test_utils.rs +52 -0
- data/rust/rubydex/src/visualization/dot.rs +176 -0
- data/rust/rubydex/src/visualization.rs +6 -0
- data/rust/rubydex/tests/cli.rs +167 -0
- data/rust/rubydex-sys/Cargo.toml +20 -0
- data/rust/rubydex-sys/build.rs +14 -0
- data/rust/rubydex-sys/cbindgen.toml +12 -0
- data/rust/rubydex-sys/src/declaration_api.rs +114 -0
- data/rust/rubydex-sys/src/definition_api.rs +350 -0
- data/rust/rubydex-sys/src/diagnostic_api.rs +99 -0
- data/rust/rubydex-sys/src/document_api.rs +54 -0
- data/rust/rubydex-sys/src/graph_api.rs +493 -0
- data/rust/rubydex-sys/src/lib.rs +9 -0
- data/rust/rubydex-sys/src/location_api.rs +79 -0
- data/rust/rubydex-sys/src/name_api.rs +81 -0
- data/rust/rubydex-sys/src/reference_api.rs +191 -0
- data/rust/rubydex-sys/src/utils.rs +50 -0
- data/rust/rustfmt.toml +2 -0
- metadata +77 -2
data/ext/rubydex/graph.c
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#include "graph.h"
|
|
2
|
+
#include "declaration.h"
|
|
3
|
+
#include "diagnostic.h"
|
|
4
|
+
#include "document.h"
|
|
5
|
+
#include "location.h"
|
|
6
|
+
#include "reference.h"
|
|
7
|
+
#include "ruby/internal/globals.h"
|
|
8
|
+
#include "rustbindings.h"
|
|
9
|
+
#include "utils.h"
|
|
10
|
+
|
|
11
|
+
static VALUE cGraph;
|
|
12
|
+
static VALUE eIndexingError;
|
|
13
|
+
|
|
14
|
+
// Free function for the custom Graph allocator. We always have to call into Rust to free data allocated by it
|
|
15
|
+
static void graph_free(void *ptr) {
|
|
16
|
+
if (ptr) {
|
|
17
|
+
rdx_graph_free(ptr);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const rb_data_type_t graph_type = {"Graph", {0, graph_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY};
|
|
22
|
+
|
|
23
|
+
// Custom allocator for the Graph class. Calls into Rust to create a new `Arc<Mutex<Graph>>` that gets stored internally
|
|
24
|
+
// as a void pointer
|
|
25
|
+
static VALUE rdxr_graph_alloc(VALUE klass) {
|
|
26
|
+
void *graph = rdx_graph_new();
|
|
27
|
+
return TypedData_Wrap_Struct(klass, &graph_type, graph);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Graph#index_all: (Array[String] file_paths) -> nil
|
|
31
|
+
// Raises IndexingError if anything failed during indexing
|
|
32
|
+
static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) {
|
|
33
|
+
rdxi_check_array_of_strings(file_paths);
|
|
34
|
+
|
|
35
|
+
// Convert the given file paths into a char** array, so that we can pass to Rust
|
|
36
|
+
size_t length = RARRAY_LEN(file_paths);
|
|
37
|
+
char **converted_file_paths = rdxi_str_array_to_char(file_paths, length);
|
|
38
|
+
|
|
39
|
+
// Get the underying graph pointer and then invoke the Rust index all implementation
|
|
40
|
+
void *graph;
|
|
41
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
42
|
+
const char *error_messages = rdx_index_all(graph, (const char **)converted_file_paths, length);
|
|
43
|
+
|
|
44
|
+
// Free the converted file paths and allow the GC to collect them
|
|
45
|
+
for (size_t i = 0; i < length; i++) {
|
|
46
|
+
free(converted_file_paths[i]);
|
|
47
|
+
}
|
|
48
|
+
free(converted_file_paths);
|
|
49
|
+
|
|
50
|
+
// If indexing errors were returned, turn them into a Ruby string, call Rust to free the CString it allocated and
|
|
51
|
+
// return the Ruby string
|
|
52
|
+
if (error_messages != NULL) {
|
|
53
|
+
VALUE error_string = rb_utf8_str_new_cstr(error_messages);
|
|
54
|
+
free_c_string(error_messages);
|
|
55
|
+
rb_raise(eIndexingError, "%s", StringValueCStr(error_string));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Qnil;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Body function for rb_ensure in Graph#declarations
|
|
62
|
+
static VALUE graph_declarations_yield(VALUE args) {
|
|
63
|
+
VALUE self = rb_ary_entry(args, 0);
|
|
64
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
65
|
+
|
|
66
|
+
int64_t id = 0;
|
|
67
|
+
while (rdx_graph_declarations_iter_next(iter, &id)) {
|
|
68
|
+
VALUE argv[] = {self, LL2NUM(id)};
|
|
69
|
+
VALUE handle = rb_class_new_instance(2, argv, cDeclaration);
|
|
70
|
+
rb_yield(handle);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return Qnil;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Ensure function for rb_ensure in Graph#declarations to always free the iterator
|
|
77
|
+
static VALUE graph_declarations_ensure(VALUE args) {
|
|
78
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
79
|
+
rdx_graph_declarations_iter_free(iter);
|
|
80
|
+
|
|
81
|
+
return Qnil;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Size function for the declarations enumerator
|
|
85
|
+
static VALUE graph_declarations_size(VALUE self, VALUE _args, VALUE _eobj) {
|
|
86
|
+
void *graph;
|
|
87
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
88
|
+
|
|
89
|
+
DeclarationsIter *iter = rdx_graph_declarations_iter_new(graph);
|
|
90
|
+
size_t len = rdx_graph_declarations_iter_len(iter);
|
|
91
|
+
rdx_graph_declarations_iter_free(iter);
|
|
92
|
+
|
|
93
|
+
return SIZET2NUM(len);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Graph#declarations: () -> Enumerator[Declaration]
|
|
97
|
+
// Returns an enumerator that yields all declarations lazily
|
|
98
|
+
static VALUE rdxr_graph_declarations(VALUE self) {
|
|
99
|
+
if (!rb_block_given_p()) {
|
|
100
|
+
return rb_enumeratorize_with_size(self, rb_str_new2("declarations"), 0, NULL, graph_declarations_size);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void *graph;
|
|
104
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
105
|
+
|
|
106
|
+
void *iter = rdx_graph_declarations_iter_new(graph);
|
|
107
|
+
VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
|
|
108
|
+
rb_ensure(graph_declarations_yield, args, graph_declarations_ensure, args);
|
|
109
|
+
|
|
110
|
+
return self;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Graph#search: () -> Enumerator[Declaration]
|
|
114
|
+
// Returns an enumerator that yields all declarations lazily
|
|
115
|
+
static VALUE rdxr_graph_search(VALUE self, VALUE query) {
|
|
116
|
+
if (!rb_block_given_p()) {
|
|
117
|
+
return rb_enumeratorize(self, rb_str_new2("search"), 1, &query);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
void *graph;
|
|
121
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
122
|
+
|
|
123
|
+
const char *c_query = StringValueCStr(query);
|
|
124
|
+
|
|
125
|
+
void *iter = rdx_graph_declarations_search(graph, c_query);
|
|
126
|
+
|
|
127
|
+
if (iter == NULL) {
|
|
128
|
+
// The only case where the iterator will be NULL instead of a list is if the query cannot be converted to a Rust
|
|
129
|
+
// string
|
|
130
|
+
rb_raise(rb_eRuntimeError, "Converting query to Rust string failed");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
|
|
134
|
+
rb_ensure(graph_declarations_yield, args, graph_declarations_ensure, args);
|
|
135
|
+
|
|
136
|
+
return self;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Body function for rb_ensure in Graph#documents
|
|
140
|
+
static VALUE graph_documents_yield(VALUE args) {
|
|
141
|
+
VALUE self = rb_ary_entry(args, 0);
|
|
142
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
143
|
+
|
|
144
|
+
int64_t id = 0;
|
|
145
|
+
while (rdx_graph_documents_iter_next(iter, &id)) {
|
|
146
|
+
VALUE argv[] = {self, LL2NUM(id)};
|
|
147
|
+
VALUE handle = rb_class_new_instance(2, argv, cDocument);
|
|
148
|
+
rb_yield(handle);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return Qnil;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Ensure function for rb_ensure in Graph#documents to always free the iterator
|
|
155
|
+
static VALUE graph_documents_ensure(VALUE args) {
|
|
156
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
157
|
+
rdx_graph_documents_iter_free(iter);
|
|
158
|
+
|
|
159
|
+
return Qnil;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Size function for the documents enumerator
|
|
163
|
+
static VALUE graph_documents_size(VALUE self, VALUE _args, VALUE _eobj) {
|
|
164
|
+
void *graph;
|
|
165
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
166
|
+
|
|
167
|
+
DocumentsIter *iter = rdx_graph_documents_iter_new(graph);
|
|
168
|
+
size_t len = rdx_graph_documents_iter_len(iter);
|
|
169
|
+
rdx_graph_documents_iter_free(iter);
|
|
170
|
+
|
|
171
|
+
return SIZET2NUM(len);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Graph#documents: () -> Enumerator[Document]
|
|
175
|
+
// Returns an enumerator that yields all documents lazily
|
|
176
|
+
static VALUE rdxr_graph_documents(VALUE self) {
|
|
177
|
+
if (!rb_block_given_p()) {
|
|
178
|
+
return rb_enumeratorize_with_size(self, rb_str_new2("documents"), 0, NULL, graph_documents_size);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
void *graph;
|
|
182
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
183
|
+
|
|
184
|
+
void *iter = rdx_graph_documents_iter_new(graph);
|
|
185
|
+
VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
|
|
186
|
+
rb_ensure(graph_documents_yield, args, graph_documents_ensure, args);
|
|
187
|
+
|
|
188
|
+
return self;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Graph#[]: (String fully_qualified_name) -> Declaration
|
|
192
|
+
// Returns a declaration handle for the given ID
|
|
193
|
+
static VALUE rdxr_graph_aref(VALUE self, VALUE key) {
|
|
194
|
+
void *graph;
|
|
195
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
196
|
+
|
|
197
|
+
if (TYPE(key) != T_STRING) {
|
|
198
|
+
rb_raise(rb_eTypeError, "expected String");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const int64_t *id_ptr = rdx_graph_get_declaration(graph, StringValueCStr(key));
|
|
202
|
+
if (id_ptr == NULL) {
|
|
203
|
+
return Qnil;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
int64_t id = *id_ptr;
|
|
207
|
+
free_i64(id_ptr);
|
|
208
|
+
VALUE argv[] = {self, LL2NUM(id)};
|
|
209
|
+
|
|
210
|
+
return rb_class_new_instance(2, argv, cDeclaration);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Body function for rb_ensure for the reference enumerators
|
|
214
|
+
static VALUE graph_references_yield(VALUE args) {
|
|
215
|
+
VALUE self = rb_ary_entry(args, 0);
|
|
216
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
217
|
+
|
|
218
|
+
int64_t id = 0;
|
|
219
|
+
ReferenceKind kind;
|
|
220
|
+
while (rdx_references_iter_next(iter, &id, &kind)) {
|
|
221
|
+
VALUE ref_class = rdxi_reference_class_for_kind(kind);
|
|
222
|
+
VALUE argv[] = {self, LL2NUM(id)};
|
|
223
|
+
VALUE obj = rb_class_new_instance(2, argv, ref_class);
|
|
224
|
+
rb_yield(obj);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return Qnil;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Ensure function for rb_ensure for the reference enumerators to always free the iterator
|
|
231
|
+
static VALUE graph_references_ensure(VALUE args) {
|
|
232
|
+
void *iter = (void *)(uintptr_t)NUM2ULL(rb_ary_entry(args, 1));
|
|
233
|
+
rdx_references_iter_free(iter);
|
|
234
|
+
|
|
235
|
+
return Qnil;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Size function for the constant_references enumerator
|
|
239
|
+
static VALUE graph_constant_references_size(VALUE self, VALUE _args, VALUE _eobj) {
|
|
240
|
+
void *graph;
|
|
241
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
242
|
+
|
|
243
|
+
ReferencesIter *iter = rdx_graph_constant_references_iter_new(graph);
|
|
244
|
+
size_t len = rdx_references_iter_len(iter);
|
|
245
|
+
rdx_references_iter_free(iter);
|
|
246
|
+
|
|
247
|
+
return SIZET2NUM(len);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Graph#constant_references: () -> Enumerator[ConstantReference]
|
|
251
|
+
// Returns an enumerator that yields constant references lazily
|
|
252
|
+
static VALUE rdxr_graph_constant_references(VALUE self) {
|
|
253
|
+
if (!rb_block_given_p()) {
|
|
254
|
+
return rb_enumeratorize_with_size(self, rb_str_new2("constant_references"), 0, NULL,
|
|
255
|
+
graph_constant_references_size);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
void *graph;
|
|
259
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
260
|
+
|
|
261
|
+
void *iter = rdx_graph_constant_references_iter_new(graph);
|
|
262
|
+
VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
|
|
263
|
+
rb_ensure(graph_references_yield, args, graph_references_ensure, args);
|
|
264
|
+
|
|
265
|
+
return self;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Size function for the method_references enumerator
|
|
269
|
+
static VALUE graph_method_references_size(VALUE self, VALUE _args, VALUE _eobj) {
|
|
270
|
+
void *graph;
|
|
271
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
272
|
+
|
|
273
|
+
ReferencesIter *iter = rdx_graph_method_references_iter_new(graph);
|
|
274
|
+
size_t len = rdx_references_iter_len(iter);
|
|
275
|
+
rdx_references_iter_free(iter);
|
|
276
|
+
|
|
277
|
+
return SIZET2NUM(len);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Graph#method_references: () -> Enumerator[MethodReference]
|
|
281
|
+
// Returns an enumerator that yields method references lazily
|
|
282
|
+
static VALUE rdxr_graph_method_references(VALUE self) {
|
|
283
|
+
if (!rb_block_given_p()) {
|
|
284
|
+
return rb_enumeratorize_with_size(self, rb_str_new2("method_references"), 0, NULL,
|
|
285
|
+
graph_method_references_size);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
void *graph;
|
|
289
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
290
|
+
|
|
291
|
+
void *iter = rdx_graph_method_references_iter_new(graph);
|
|
292
|
+
VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
|
|
293
|
+
rb_ensure(graph_references_yield, args, graph_references_ensure, args);
|
|
294
|
+
|
|
295
|
+
return self;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Graph#resolve: () -> self
|
|
299
|
+
// Runs the resolver to compute declarations and ownership
|
|
300
|
+
static VALUE rdxr_graph_resolve(VALUE self) {
|
|
301
|
+
void *graph;
|
|
302
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
303
|
+
rdx_graph_resolve(graph);
|
|
304
|
+
return self;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Graph#set_encoding: (String) -> void
|
|
308
|
+
// Sets the encoding used for transforming byte offsets into LSP code unit line/column positions
|
|
309
|
+
static VALUE rdxr_graph_set_encoding(VALUE self, VALUE encoding) {
|
|
310
|
+
Check_Type(encoding, T_STRING);
|
|
311
|
+
|
|
312
|
+
void *graph;
|
|
313
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
314
|
+
|
|
315
|
+
char *encoding_string = StringValueCStr(encoding);
|
|
316
|
+
if (!rdx_graph_set_encoding(graph, encoding_string)) {
|
|
317
|
+
rb_raise(rb_eArgError, "invalid encoding `%s` (should be utf8, utf16 or utf32)", encoding_string);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return Qnil;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Graph#resolve_constant: (String, Array[String]) -> Declaration?
|
|
324
|
+
// Runs the resolver on a single constant reference to determine what it points to
|
|
325
|
+
static VALUE rdxr_graph_resolve_constant(VALUE self, VALUE const_name, VALUE nesting) {
|
|
326
|
+
Check_Type(const_name, T_STRING);
|
|
327
|
+
rdxi_check_array_of_strings(nesting);
|
|
328
|
+
|
|
329
|
+
// Convert the given file paths into a char** array, so that we can pass to Rust
|
|
330
|
+
size_t length = RARRAY_LEN(nesting);
|
|
331
|
+
char **converted_file_paths = rdxi_str_array_to_char(nesting, length);
|
|
332
|
+
|
|
333
|
+
void *graph;
|
|
334
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
335
|
+
|
|
336
|
+
const int64_t *id_ptr =
|
|
337
|
+
rdx_graph_resolve_constant(graph, StringValueCStr(const_name), (const char **)converted_file_paths, length);
|
|
338
|
+
|
|
339
|
+
for (size_t i = 0; i < length; i++) {
|
|
340
|
+
free(converted_file_paths[i]);
|
|
341
|
+
}
|
|
342
|
+
free(converted_file_paths);
|
|
343
|
+
|
|
344
|
+
if (id_ptr == NULL) {
|
|
345
|
+
return Qnil;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
int64_t id = *id_ptr;
|
|
349
|
+
free_i64(id_ptr);
|
|
350
|
+
VALUE argv[] = {self, LL2NUM(id)};
|
|
351
|
+
|
|
352
|
+
return rb_class_new_instance(2, argv, cDeclaration);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Graph#diagnostics -> Array[Rubydex::Diagnostic]
|
|
356
|
+
static VALUE rdxr_graph_diagnostics(VALUE self) {
|
|
357
|
+
void *graph;
|
|
358
|
+
TypedData_Get_Struct(self, void *, &graph_type, graph);
|
|
359
|
+
|
|
360
|
+
DiagnosticArray *array = rdx_graph_diagnostics(graph);
|
|
361
|
+
if (array == NULL || array->len == 0) {
|
|
362
|
+
if (array != NULL) {
|
|
363
|
+
rdx_diagnostics_free(array);
|
|
364
|
+
}
|
|
365
|
+
return rb_ary_new();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
VALUE diagnostics = rb_ary_new_capa((long)array->len);
|
|
369
|
+
for (size_t i = 0; i < array->len; i++) {
|
|
370
|
+
DiagnosticEntry entry = array->items[i];
|
|
371
|
+
VALUE message = entry.message == NULL ? Qnil : rb_utf8_str_new_cstr(entry.message);
|
|
372
|
+
VALUE rule = rb_str_new2(entry.rule);
|
|
373
|
+
VALUE location = rdxi_build_location_value(entry.location);
|
|
374
|
+
|
|
375
|
+
VALUE kwargs = rb_hash_new();
|
|
376
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("rule")), rule);
|
|
377
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("message")), message);
|
|
378
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location);
|
|
379
|
+
|
|
380
|
+
VALUE diagnostic = rb_class_new_instance_kw(1, &kwargs, cDiagnostic, RB_PASS_KEYWORDS);
|
|
381
|
+
rb_ary_push(diagnostics, diagnostic);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
rdx_diagnostics_free(array);
|
|
385
|
+
return diagnostics;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
void rdxi_initialize_graph(VALUE mRubydex) {
|
|
389
|
+
VALUE eRubydexError = rb_const_get(mRubydex, rb_intern("Error"));
|
|
390
|
+
eIndexingError = rb_define_class_under(mRubydex, "IndexingError", eRubydexError);
|
|
391
|
+
|
|
392
|
+
cGraph = rb_define_class_under(mRubydex, "Graph", rb_cObject);
|
|
393
|
+
rb_define_alloc_func(cGraph, rdxr_graph_alloc);
|
|
394
|
+
rb_define_method(cGraph, "index_all", rdxr_graph_index_all, 1);
|
|
395
|
+
rb_define_method(cGraph, "resolve", rdxr_graph_resolve, 0);
|
|
396
|
+
rb_define_method(cGraph, "resolve_constant", rdxr_graph_resolve_constant, 2);
|
|
397
|
+
rb_define_method(cGraph, "declarations", rdxr_graph_declarations, 0);
|
|
398
|
+
rb_define_method(cGraph, "documents", rdxr_graph_documents, 0);
|
|
399
|
+
rb_define_method(cGraph, "constant_references", rdxr_graph_constant_references, 0);
|
|
400
|
+
rb_define_method(cGraph, "method_references", rdxr_graph_method_references, 0);
|
|
401
|
+
rb_define_method(cGraph, "diagnostics", rdxr_graph_diagnostics, 0);
|
|
402
|
+
rb_define_method(cGraph, "[]", rdxr_graph_aref, 1);
|
|
403
|
+
rb_define_method(cGraph, "search", rdxr_graph_search, 1);
|
|
404
|
+
rb_define_method(cGraph, "set_encoding", rdxr_graph_set_encoding, 1);
|
|
405
|
+
}
|
data/ext/rubydex/graph.h
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#ifndef RUBYDEX_HANDLE_H
|
|
2
|
+
#define RUBYDEX_HANDLE_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
VALUE graph_obj; // Ruby Graph object to keep it alive
|
|
8
|
+
int64_t id; // Canonical ID (i64) mapping to a DeclarationId, DefinitionId, UriId, etc. See `ids.rs`.
|
|
9
|
+
} HandleData;
|
|
10
|
+
|
|
11
|
+
static void handle_mark(void *ptr) {
|
|
12
|
+
if (ptr) {
|
|
13
|
+
HandleData *data = (HandleData *)ptr;
|
|
14
|
+
rb_gc_mark(data->graph_obj);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static void handle_free(void *ptr) {
|
|
19
|
+
if (ptr) {
|
|
20
|
+
xfree(ptr);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static const rb_data_type_t handle_type = {
|
|
25
|
+
"RubydexHandle", {handle_mark, handle_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY};
|
|
26
|
+
|
|
27
|
+
static VALUE rdxr_handle_alloc(VALUE klass) {
|
|
28
|
+
HandleData *data = ALLOC(HandleData);
|
|
29
|
+
data->graph_obj = Qnil;
|
|
30
|
+
data->id = 0;
|
|
31
|
+
|
|
32
|
+
return TypedData_Wrap_Struct(klass, &handle_type, data);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static VALUE rdxr_handle_initialize(VALUE self, VALUE graph_obj, VALUE id_val) {
|
|
36
|
+
HandleData *data;
|
|
37
|
+
TypedData_Get_Struct(self, HandleData, &handle_type, data);
|
|
38
|
+
data->graph_obj = graph_obj;
|
|
39
|
+
data->id = NUM2LL(id_val);
|
|
40
|
+
|
|
41
|
+
return self;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#endif // RUBYDEX_HANDLE_H
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#include "location.h"
|
|
2
|
+
|
|
3
|
+
VALUE cLocation;
|
|
4
|
+
|
|
5
|
+
VALUE rdxi_build_location_value(Location *loc) {
|
|
6
|
+
if (loc == NULL) {
|
|
7
|
+
return Qnil;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
VALUE uri = rb_utf8_str_new_cstr(loc->uri);
|
|
11
|
+
|
|
12
|
+
VALUE kwargs = rb_hash_new_capa(5);
|
|
13
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("uri")), uri);
|
|
14
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("start_line")), UINT2NUM(loc->start_line));
|
|
15
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("end_line")), UINT2NUM(loc->end_line));
|
|
16
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("start_column")), UINT2NUM(loc->start_column));
|
|
17
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("end_column")), UINT2NUM(loc->end_column));
|
|
18
|
+
|
|
19
|
+
return rb_class_new_instance_kw(1, &kwargs, cLocation, RB_PASS_KEYWORDS);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void rdxi_initialize_location(VALUE mRubydex) { cLocation = rb_define_class_under(mRubydex, "Location", rb_cObject); }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef RUBYDEX_LOCATION_H
|
|
2
|
+
#define RUBYDEX_LOCATION_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
#include "rustbindings.h"
|
|
6
|
+
|
|
7
|
+
extern VALUE cLocation;
|
|
8
|
+
|
|
9
|
+
void rdxi_initialize_location(VALUE mRubydex);
|
|
10
|
+
|
|
11
|
+
// Helper to build a Ruby Rubydex::Location from a C Location pointer.
|
|
12
|
+
// Does not take ownership; caller remains responsible for freeing the C Location on the Rust side.
|
|
13
|
+
VALUE rdxi_build_location_value(Location *loc);
|
|
14
|
+
|
|
15
|
+
#endif // RUBYDEX_LOCATION_H
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#include "reference.h"
|
|
2
|
+
#include "graph.h"
|
|
3
|
+
#include "handle.h"
|
|
4
|
+
#include "location.h"
|
|
5
|
+
#include "rustbindings.h"
|
|
6
|
+
|
|
7
|
+
VALUE cReference;
|
|
8
|
+
VALUE cConstantReference;
|
|
9
|
+
VALUE cMethodReference;
|
|
10
|
+
|
|
11
|
+
// ConstantReference#name -> String
|
|
12
|
+
static VALUE rdxr_constant_reference_name(VALUE self) {
|
|
13
|
+
HandleData *data;
|
|
14
|
+
TypedData_Get_Struct(self, HandleData, &handle_type, data);
|
|
15
|
+
|
|
16
|
+
void *graph;
|
|
17
|
+
TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
|
|
18
|
+
|
|
19
|
+
const char *name = rdx_constant_reference_name(graph, data->id);
|
|
20
|
+
if (name == NULL) {
|
|
21
|
+
return Qnil;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
VALUE str = rb_utf8_str_new_cstr(name);
|
|
25
|
+
free_c_string(name);
|
|
26
|
+
return str;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ConstantReference#location -> Rubydex::Location
|
|
30
|
+
static VALUE rdxr_constant_reference_location(VALUE self) {
|
|
31
|
+
HandleData *data;
|
|
32
|
+
TypedData_Get_Struct(self, HandleData, &handle_type, data);
|
|
33
|
+
|
|
34
|
+
void *graph;
|
|
35
|
+
TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
|
|
36
|
+
|
|
37
|
+
Location *loc = rdx_constant_reference_location(graph, data->id);
|
|
38
|
+
VALUE location = rdxi_build_location_value(loc);
|
|
39
|
+
rdx_location_free(loc);
|
|
40
|
+
return location;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// MethodReference#name -> String
|
|
44
|
+
static VALUE rdxr_method_reference_name(VALUE self) {
|
|
45
|
+
HandleData *data;
|
|
46
|
+
TypedData_Get_Struct(self, HandleData, &handle_type, data);
|
|
47
|
+
|
|
48
|
+
void *graph;
|
|
49
|
+
TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
|
|
50
|
+
|
|
51
|
+
const char *name = rdx_method_reference_name(graph, data->id);
|
|
52
|
+
if (name == NULL) {
|
|
53
|
+
return Qnil;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
VALUE str = rb_utf8_str_new_cstr(name);
|
|
57
|
+
free_c_string(name);
|
|
58
|
+
return str;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// MethodReference#location -> Rubydex::Location
|
|
62
|
+
static VALUE rdxr_method_reference_location(VALUE self) {
|
|
63
|
+
HandleData *data;
|
|
64
|
+
TypedData_Get_Struct(self, HandleData, &handle_type, data);
|
|
65
|
+
|
|
66
|
+
void *graph;
|
|
67
|
+
TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
|
|
68
|
+
|
|
69
|
+
Location *loc = rdx_method_reference_location(graph, data->id);
|
|
70
|
+
VALUE location = rdxi_build_location_value(loc);
|
|
71
|
+
rdx_location_free(loc);
|
|
72
|
+
return location;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Keep this in sync with unresolved_reference_api.rs
|
|
76
|
+
VALUE rdxi_reference_class_for_kind(ReferenceKind kind) {
|
|
77
|
+
switch (kind) {
|
|
78
|
+
case ReferenceKind_Constant:
|
|
79
|
+
return cConstantReference;
|
|
80
|
+
case ReferenceKind_Method:
|
|
81
|
+
return cMethodReference;
|
|
82
|
+
default:
|
|
83
|
+
rb_raise(rb_eRuntimeError, "Unknown UnresolvedReferenceKind: %d", kind);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void rdxi_initialize_reference(VALUE mRubydex) {
|
|
88
|
+
cReference = rb_define_class_under(mRubydex, "Reference", rb_cObject);
|
|
89
|
+
rb_define_alloc_func(cReference, rdxr_handle_alloc);
|
|
90
|
+
rb_define_method(cReference, "initialize", rdxr_handle_initialize, 2);
|
|
91
|
+
rb_funcall(rb_singleton_class(cReference), rb_intern("private"), 1, ID2SYM(rb_intern("new")));
|
|
92
|
+
|
|
93
|
+
cConstantReference = rb_define_class_under(mRubydex, "ConstantReference", cReference);
|
|
94
|
+
rb_define_alloc_func(cConstantReference, rdxr_handle_alloc);
|
|
95
|
+
rb_define_method(cConstantReference, "initialize", rdxr_handle_initialize, 2);
|
|
96
|
+
rb_define_method(cConstantReference, "name", rdxr_constant_reference_name, 0);
|
|
97
|
+
rb_define_method(cConstantReference, "location", rdxr_constant_reference_location, 0);
|
|
98
|
+
|
|
99
|
+
cMethodReference = rb_define_class_under(mRubydex, "MethodReference", cReference);
|
|
100
|
+
rb_define_alloc_func(cMethodReference, rdxr_handle_alloc);
|
|
101
|
+
rb_define_method(cMethodReference, "initialize", rdxr_handle_initialize, 2);
|
|
102
|
+
rb_define_method(cMethodReference, "name", rdxr_method_reference_name, 0);
|
|
103
|
+
rb_define_method(cMethodReference, "location", rdxr_method_reference_location, 0);
|
|
104
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#ifndef RUBYDEX_REFERENCE_H
|
|
2
|
+
#define RUBYDEX_REFERENCE_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
#include "rustbindings.h"
|
|
6
|
+
|
|
7
|
+
extern VALUE cReference;
|
|
8
|
+
extern VALUE cConstantReference;
|
|
9
|
+
extern VALUE cMethodReference;
|
|
10
|
+
|
|
11
|
+
void rdxi_initialize_reference(VALUE mRubydex);
|
|
12
|
+
|
|
13
|
+
// Returns the Ruby class for a given UnresolvedReferenceKind without calling back into Rust
|
|
14
|
+
VALUE rdxi_reference_class_for_kind(ReferenceKind kind);
|
|
15
|
+
|
|
16
|
+
#endif // RUBYDEX_REFERENCE_H
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#include "declaration.h"
|
|
2
|
+
#include "definition.h"
|
|
3
|
+
#include "diagnostic.h"
|
|
4
|
+
#include "document.h"
|
|
5
|
+
#include "graph.h"
|
|
6
|
+
#include "location.h"
|
|
7
|
+
#include "reference.h"
|
|
8
|
+
|
|
9
|
+
VALUE mRubydex;
|
|
10
|
+
|
|
11
|
+
void Init_rubydex(void) {
|
|
12
|
+
rb_ext_ractor_safe(true);
|
|
13
|
+
|
|
14
|
+
mRubydex = rb_define_module("Rubydex");
|
|
15
|
+
rdxi_initialize_graph(mRubydex);
|
|
16
|
+
rdxi_initialize_declaration(mRubydex);
|
|
17
|
+
rdxi_initialize_document(mRubydex);
|
|
18
|
+
rdxi_initialize_definition(mRubydex);
|
|
19
|
+
rdxi_initialize_location(mRubydex);
|
|
20
|
+
rdxi_initialize_diagnostic(mRubydex);
|
|
21
|
+
rdxi_initialize_reference(mRubydex);
|
|
22
|
+
}
|
data/ext/rubydex/utils.c
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#include "utils.h"
|
|
2
|
+
|
|
3
|
+
// Convert a Ruby array of strings into a double char pointer so that we can pass that to Rust.
|
|
4
|
+
// This copies the data so it must be freed
|
|
5
|
+
char **rdxi_str_array_to_char(VALUE array, size_t length) {
|
|
6
|
+
char **converted_array = malloc(length * sizeof(char *));
|
|
7
|
+
|
|
8
|
+
for (size_t i = 0; i < length; i++) {
|
|
9
|
+
VALUE item = rb_ary_entry(array, i);
|
|
10
|
+
const char *string = StringValueCStr(item);
|
|
11
|
+
|
|
12
|
+
converted_array[i] = malloc(strlen(string) + 1);
|
|
13
|
+
strcpy(converted_array[i], string);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return converted_array;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Verify that the Ruby object is an array of strings or raise `TypeError`
|
|
20
|
+
void rdxi_check_array_of_strings(VALUE array) {
|
|
21
|
+
Check_Type(array, T_ARRAY);
|
|
22
|
+
|
|
23
|
+
for (long i = 0; i < RARRAY_LEN(array); i++) {
|
|
24
|
+
VALUE item = rb_ary_entry(array, i);
|
|
25
|
+
Check_Type(item, T_STRING);
|
|
26
|
+
}
|
|
27
|
+
}
|
data/ext/rubydex/utils.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#ifndef RUBYDEX_UTILS_H
|
|
2
|
+
#define RUBYDEX_UTILS_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
|
|
6
|
+
// Convert a Ruby array of strings into a double char pointer so that we can pass that to Rust.
|
|
7
|
+
// This copies the data so it must be freed
|
|
8
|
+
char **rdxi_str_array_to_char(VALUE array, size_t length);
|
|
9
|
+
|
|
10
|
+
// Verify that the Ruby object is an array of strings or raise `TypeError`
|
|
11
|
+
void rdxi_check_array_of_strings(VALUE array);
|
|
12
|
+
|
|
13
|
+
#endif // RUBYDEX_UTILS_H
|
data/lib/rubydex/3.2/rubydex.so
CHANGED
|
Binary file
|
data/lib/rubydex/3.3/rubydex.so
CHANGED
|
Binary file
|
data/lib/rubydex/3.4/rubydex.so
CHANGED
|
Binary file
|