rubydex 0.1.0.beta12-aarch64-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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +23 -0
  3. data/README.md +125 -0
  4. data/THIRD_PARTY_LICENSES.html +4562 -0
  5. data/exe/rdx +47 -0
  6. data/ext/rubydex/declaration.c +453 -0
  7. data/ext/rubydex/declaration.h +23 -0
  8. data/ext/rubydex/definition.c +284 -0
  9. data/ext/rubydex/definition.h +28 -0
  10. data/ext/rubydex/diagnostic.c +6 -0
  11. data/ext/rubydex/diagnostic.h +11 -0
  12. data/ext/rubydex/document.c +97 -0
  13. data/ext/rubydex/document.h +10 -0
  14. data/ext/rubydex/extconf.rb +138 -0
  15. data/ext/rubydex/graph.c +681 -0
  16. data/ext/rubydex/graph.h +10 -0
  17. data/ext/rubydex/handle.h +44 -0
  18. data/ext/rubydex/location.c +22 -0
  19. data/ext/rubydex/location.h +15 -0
  20. data/ext/rubydex/reference.c +123 -0
  21. data/ext/rubydex/reference.h +15 -0
  22. data/ext/rubydex/rubydex.c +22 -0
  23. data/ext/rubydex/utils.c +108 -0
  24. data/ext/rubydex/utils.h +34 -0
  25. data/lib/rubydex/3.2/rubydex.so +0 -0
  26. data/lib/rubydex/3.3/rubydex.so +0 -0
  27. data/lib/rubydex/3.4/rubydex.so +0 -0
  28. data/lib/rubydex/4.0/rubydex.so +0 -0
  29. data/lib/rubydex/comment.rb +17 -0
  30. data/lib/rubydex/diagnostic.rb +21 -0
  31. data/lib/rubydex/failures.rb +15 -0
  32. data/lib/rubydex/graph.rb +98 -0
  33. data/lib/rubydex/keyword.rb +17 -0
  34. data/lib/rubydex/keyword_parameter.rb +13 -0
  35. data/lib/rubydex/librubydex_sys.so +0 -0
  36. data/lib/rubydex/location.rb +90 -0
  37. data/lib/rubydex/mixin.rb +22 -0
  38. data/lib/rubydex/version.rb +5 -0
  39. data/lib/rubydex.rb +23 -0
  40. data/rbi/rubydex.rbi +422 -0
  41. data/rust/Cargo.lock +1851 -0
  42. data/rust/Cargo.toml +29 -0
  43. data/rust/about.hbs +78 -0
  44. data/rust/about.toml +10 -0
  45. data/rust/rubydex/Cargo.toml +42 -0
  46. data/rust/rubydex/src/compile_assertions.rs +13 -0
  47. data/rust/rubydex/src/diagnostic.rs +110 -0
  48. data/rust/rubydex/src/errors.rs +28 -0
  49. data/rust/rubydex/src/indexing/local_graph.rs +224 -0
  50. data/rust/rubydex/src/indexing/rbs_indexer.rs +1551 -0
  51. data/rust/rubydex/src/indexing/ruby_indexer.rs +2329 -0
  52. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +4962 -0
  53. data/rust/rubydex/src/indexing.rs +210 -0
  54. data/rust/rubydex/src/integrity.rs +279 -0
  55. data/rust/rubydex/src/job_queue.rs +205 -0
  56. data/rust/rubydex/src/lib.rs +17 -0
  57. data/rust/rubydex/src/listing.rs +371 -0
  58. data/rust/rubydex/src/main.rs +160 -0
  59. data/rust/rubydex/src/model/built_in.rs +83 -0
  60. data/rust/rubydex/src/model/comment.rs +24 -0
  61. data/rust/rubydex/src/model/declaration.rs +671 -0
  62. data/rust/rubydex/src/model/definitions.rs +1682 -0
  63. data/rust/rubydex/src/model/document.rs +222 -0
  64. data/rust/rubydex/src/model/encoding.rs +22 -0
  65. data/rust/rubydex/src/model/graph.rs +3754 -0
  66. data/rust/rubydex/src/model/id.rs +110 -0
  67. data/rust/rubydex/src/model/identity_maps.rs +58 -0
  68. data/rust/rubydex/src/model/ids.rs +60 -0
  69. data/rust/rubydex/src/model/keywords.rs +256 -0
  70. data/rust/rubydex/src/model/name.rs +298 -0
  71. data/rust/rubydex/src/model/references.rs +111 -0
  72. data/rust/rubydex/src/model/string_ref.rs +50 -0
  73. data/rust/rubydex/src/model/visibility.rs +41 -0
  74. data/rust/rubydex/src/model.rs +15 -0
  75. data/rust/rubydex/src/offset.rs +147 -0
  76. data/rust/rubydex/src/position.rs +6 -0
  77. data/rust/rubydex/src/query.rs +1841 -0
  78. data/rust/rubydex/src/resolution.rs +6517 -0
  79. data/rust/rubydex/src/stats/memory.rs +71 -0
  80. data/rust/rubydex/src/stats/orphan_report.rs +264 -0
  81. data/rust/rubydex/src/stats/timer.rs +127 -0
  82. data/rust/rubydex/src/stats.rs +11 -0
  83. data/rust/rubydex/src/test_utils/context.rs +226 -0
  84. data/rust/rubydex/src/test_utils/graph_test.rs +730 -0
  85. data/rust/rubydex/src/test_utils/local_graph_test.rs +602 -0
  86. data/rust/rubydex/src/test_utils.rs +52 -0
  87. data/rust/rubydex/src/visualization/dot.rs +192 -0
  88. data/rust/rubydex/src/visualization.rs +6 -0
  89. data/rust/rubydex/tests/cli.rs +185 -0
  90. data/rust/rubydex-mcp/Cargo.toml +28 -0
  91. data/rust/rubydex-mcp/src/main.rs +48 -0
  92. data/rust/rubydex-mcp/src/server.rs +1145 -0
  93. data/rust/rubydex-mcp/src/tools.rs +49 -0
  94. data/rust/rubydex-mcp/tests/mcp.rs +302 -0
  95. data/rust/rubydex-sys/Cargo.toml +20 -0
  96. data/rust/rubydex-sys/build.rs +14 -0
  97. data/rust/rubydex-sys/cbindgen.toml +12 -0
  98. data/rust/rubydex-sys/src/declaration_api.rs +485 -0
  99. data/rust/rubydex-sys/src/definition_api.rs +443 -0
  100. data/rust/rubydex-sys/src/diagnostic_api.rs +99 -0
  101. data/rust/rubydex-sys/src/document_api.rs +85 -0
  102. data/rust/rubydex-sys/src/graph_api.rs +948 -0
  103. data/rust/rubydex-sys/src/lib.rs +79 -0
  104. data/rust/rubydex-sys/src/location_api.rs +79 -0
  105. data/rust/rubydex-sys/src/name_api.rs +135 -0
  106. data/rust/rubydex-sys/src/reference_api.rs +267 -0
  107. data/rust/rubydex-sys/src/utils.rs +70 -0
  108. data/rust/rustfmt.toml +2 -0
  109. metadata +159 -0
@@ -0,0 +1,485 @@
1
+ //! This file provides the C API for the Graph object
2
+
3
+ use libc::c_char;
4
+ use rubydex::model::declaration::{Ancestor, Declaration, Namespace};
5
+ use std::ffi::CString;
6
+ use std::ptr;
7
+
8
+ use crate::definition_api::{DefinitionsIter, rdx_definitions_iter_new_from_ids};
9
+ use crate::graph_api::{GraphPointer, with_graph};
10
+ use crate::reference_api::{CConstantReference, CMethodReference, ConstantReferencesIter, MethodReferencesIter};
11
+ use crate::utils;
12
+ use rubydex::model::ids::{DeclarationId, StringId};
13
+
14
+ #[repr(C)]
15
+ #[derive(Debug, Clone, Copy)]
16
+ pub enum CDeclarationKind {
17
+ Class = 0,
18
+ Module = 1,
19
+ SingletonClass = 2,
20
+ Constant = 3,
21
+ ConstantAlias = 4,
22
+ Method = 5,
23
+ GlobalVariable = 6,
24
+ InstanceVariable = 7,
25
+ ClassVariable = 8,
26
+ Todo = 9,
27
+ }
28
+
29
+ #[repr(C)]
30
+ #[derive(Debug, Clone, Copy)]
31
+ pub struct CDeclaration {
32
+ id: u64,
33
+ kind: CDeclarationKind,
34
+ }
35
+
36
+ impl CDeclaration {
37
+ #[must_use]
38
+ pub fn id(&self) -> u64 {
39
+ self.id
40
+ }
41
+
42
+ #[must_use]
43
+ pub fn from_declaration(id: DeclarationId, decl: &Declaration) -> Self {
44
+ Self {
45
+ id: *id,
46
+ kind: Self::kind_from_declaration(decl),
47
+ }
48
+ }
49
+
50
+ #[must_use]
51
+ pub fn kind_from_declaration(decl: &Declaration) -> CDeclarationKind {
52
+ match decl {
53
+ Declaration::Namespace(Namespace::Class(_)) => CDeclarationKind::Class,
54
+ Declaration::Namespace(Namespace::Module(_)) => CDeclarationKind::Module,
55
+ Declaration::Namespace(Namespace::SingletonClass(_)) => CDeclarationKind::SingletonClass,
56
+ Declaration::Namespace(Namespace::Todo(_)) => CDeclarationKind::Todo,
57
+ Declaration::Constant(_) => CDeclarationKind::Constant,
58
+ Declaration::ConstantAlias(_) => CDeclarationKind::ConstantAlias,
59
+ Declaration::Method(_) => CDeclarationKind::Method,
60
+ Declaration::GlobalVariable(_) => CDeclarationKind::GlobalVariable,
61
+ Declaration::InstanceVariable(_) => CDeclarationKind::InstanceVariable,
62
+ Declaration::ClassVariable(_) => CDeclarationKind::ClassVariable,
63
+ }
64
+ }
65
+ }
66
+
67
+ /// An iterator over declaration IDs
68
+ ///
69
+ /// We snapshot the IDs at iterator creation so if the graph is modified, the iterator will not see the changes
70
+ #[derive(Debug)]
71
+ pub struct DeclarationsIter {
72
+ /// The snapshot of declarations
73
+ entries: Box<[CDeclaration]>,
74
+ /// The current index of the iterator
75
+ index: usize,
76
+ }
77
+
78
+ iterator!(DeclarationsIter, entries: CDeclaration);
79
+
80
+ /// # Safety
81
+ /// `iter` must be a valid pointer previously returned by `DeclarationsIter::new`.
82
+ #[unsafe(no_mangle)]
83
+ pub unsafe extern "C" fn rdx_graph_declarations_iter_len(iter: *const DeclarationsIter) -> usize {
84
+ unsafe { DeclarationsIter::len(iter) }
85
+ }
86
+
87
+ /// # Safety
88
+ /// - `iter` must be a valid pointer previously returned by `DeclarationsIter::new`.
89
+ /// - `out` must be a valid, writable pointer.
90
+ #[unsafe(no_mangle)]
91
+ pub unsafe extern "C" fn rdx_graph_declarations_iter_next(iter: *mut DeclarationsIter, out: *mut CDeclaration) -> bool {
92
+ unsafe { DeclarationsIter::next(iter, out) }
93
+ }
94
+
95
+ /// # Safety
96
+ /// - `iter` must be a pointer previously returned by `DeclarationsIter::new`.
97
+ /// - `iter` must not be used after being freed.
98
+ #[unsafe(no_mangle)]
99
+ pub unsafe extern "C" fn rdx_graph_declarations_iter_free(iter: *mut DeclarationsIter) {
100
+ unsafe { DeclarationsIter::free(iter) }
101
+ }
102
+
103
+ /// Returns the UTF-8 name string for a declaration id.
104
+ /// Caller must free with `free_c_string`.
105
+ ///
106
+ /// # Safety
107
+ ///
108
+ /// Assumes pointer is valid.
109
+ ///
110
+ /// # Panics
111
+ ///
112
+ /// This function will panic if the name pointer is invalid.
113
+ #[unsafe(no_mangle)]
114
+ pub unsafe extern "C" fn rdx_declaration_name(pointer: GraphPointer, name_id: u64) -> *const c_char {
115
+ with_graph(pointer, |graph| {
116
+ let name_id = DeclarationId::new(name_id);
117
+ if let Some(decl) = graph.declarations().get(&name_id) {
118
+ CString::new(decl.name()).unwrap().into_raw().cast_const()
119
+ } else {
120
+ ptr::null()
121
+ }
122
+ })
123
+ }
124
+
125
+ /// Returns the declaration ID for a member from a declaration.
126
+ /// Returns NULL if the member is not found.
127
+ ///
128
+ /// # Safety
129
+ /// - `member` must be a valid, null-terminated UTF-8 string
130
+ ///
131
+ /// # Panics
132
+ ///
133
+ /// Will panic if there's inconsistent graph data
134
+ #[unsafe(no_mangle)]
135
+ pub unsafe extern "C" fn rdx_declaration_member(
136
+ pointer: GraphPointer,
137
+ name_id: u64,
138
+ member: *const c_char,
139
+ ) -> *const CDeclaration {
140
+ let Ok(member_str) = (unsafe { utils::convert_char_ptr_to_string(member) }) else {
141
+ return ptr::null();
142
+ };
143
+
144
+ with_graph(pointer, |graph| {
145
+ let name_id = DeclarationId::new(name_id);
146
+ if let Some(Declaration::Namespace(decl)) = graph.declarations().get(&name_id) {
147
+ let member_id = StringId::from(member_str.as_str());
148
+
149
+ if let Some(member_decl_id) = decl.member(&member_id) {
150
+ let member_decl = graph.declarations().get(member_decl_id).unwrap();
151
+ return Box::into_raw(Box::new(CDeclaration::from_declaration(*member_decl_id, member_decl)))
152
+ .cast_const();
153
+ }
154
+ }
155
+
156
+ ptr::null()
157
+ })
158
+ }
159
+
160
+ /// Searches for a member in the ancestors of the given declaration
161
+ ///
162
+ /// # Safety
163
+ /// - `member` must be a valid, null-terminated UTF-8 string
164
+ ///
165
+ /// # Panics
166
+ ///
167
+ /// Will panic if there's inconsistent graph data
168
+ #[unsafe(no_mangle)]
169
+ pub unsafe extern "C" fn rdx_declaration_find_member(
170
+ pointer: GraphPointer,
171
+ declaration_id: u64,
172
+ member: *const c_char,
173
+ only_inherited: bool,
174
+ ) -> *const CDeclaration {
175
+ let Ok(member_str) = (unsafe { utils::convert_char_ptr_to_string(member) }) else {
176
+ return ptr::null();
177
+ };
178
+
179
+ with_graph(pointer, |graph| {
180
+ let id = DeclarationId::new(declaration_id);
181
+
182
+ let Some(Declaration::Namespace(decl)) = graph.declarations().get(&id) else {
183
+ return ptr::null();
184
+ };
185
+
186
+ let member_id = StringId::from(member_str.as_str());
187
+ let mut found_main_namespace = false;
188
+
189
+ decl.ancestors()
190
+ .iter()
191
+ .find_map(|ancestor| match ancestor {
192
+ Ancestor::Complete(ancestor_id) => {
193
+ // When only_inherited, skip self and prepended modules
194
+ if only_inherited {
195
+ let is_self = *ancestor_id == id;
196
+ if is_self {
197
+ found_main_namespace = true;
198
+ }
199
+ if is_self || !found_main_namespace {
200
+ return None;
201
+ }
202
+ }
203
+
204
+ let ancestor_decl = graph.declarations().get(ancestor_id).unwrap().as_namespace().unwrap();
205
+
206
+ if let Some(member_decl_id) = ancestor_decl.member(&member_id) {
207
+ return Some((member_decl_id, graph.declarations().get(member_decl_id).unwrap()));
208
+ }
209
+
210
+ None
211
+ }
212
+ Ancestor::Partial(_) => None,
213
+ })
214
+ .map_or(ptr::null(), |(member_decl_id, member_decl)| {
215
+ Box::into_raw(Box::new(CDeclaration::from_declaration(*member_decl_id, member_decl))).cast_const()
216
+ })
217
+ })
218
+ }
219
+
220
+ /// Returns the UTF-8 unqualified name string for a declaration id.
221
+ /// Caller must free with `free_c_string`.
222
+ ///
223
+ /// # Safety
224
+ ///
225
+ /// Assumes pointer is valid.
226
+ ///
227
+ /// # Panics
228
+ ///
229
+ /// This function will panic if the name pointer is invalid.
230
+ #[unsafe(no_mangle)]
231
+ pub unsafe extern "C" fn rdx_declaration_unqualified_name(pointer: GraphPointer, name_id: u64) -> *const c_char {
232
+ with_graph(pointer, |graph| {
233
+ let name_id = DeclarationId::new(name_id);
234
+ if let Some(decl) = graph.declarations().get(&name_id) {
235
+ CString::new(decl.unqualified_name()).unwrap().into_raw().cast_const()
236
+ } else {
237
+ ptr::null()
238
+ }
239
+ })
240
+ }
241
+
242
+ /// An iterator over definition IDs and kinds for a given declaration
243
+ ///
244
+ /// We snapshot the IDs at iterator creation so if the graph is modified, the iterator will not see the changes
245
+ // Use shared DefinitionsIter directly in signatures
246
+ /// Creates a new iterator over definition IDs for a given declaration by snapshotting the current set of IDs.
247
+ ///
248
+ /// # Safety
249
+ ///
250
+ /// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
251
+ /// - The returned pointer must be freed with `rdx_declaration_definitions_iter_free`.
252
+ #[unsafe(no_mangle)]
253
+ pub unsafe extern "C" fn rdx_declaration_definitions_iter_new(
254
+ pointer: GraphPointer,
255
+ decl_id: u64,
256
+ ) -> *mut DefinitionsIter {
257
+ // Snapshot the IDs and kinds at iterator creation to avoid borrowing across FFI calls
258
+ with_graph(pointer, |graph| {
259
+ let decl_id = DeclarationId::new(decl_id);
260
+ if let Some(decl) = graph.declarations().get(&decl_id) {
261
+ rdx_definitions_iter_new_from_ids(graph, decl.definitions())
262
+ } else {
263
+ DefinitionsIter::new(Vec::<_>::new().into_boxed_slice())
264
+ }
265
+ })
266
+ }
267
+
268
+ /// Returns the declaration for the singleton class of the declaration
269
+ ///
270
+ /// # Safety
271
+ ///
272
+ /// Assumes pointer is valid
273
+ ///
274
+ /// # Panics
275
+ ///
276
+ /// Will panic if invoked on a non-existing or non-namespace declaration
277
+ #[unsafe(no_mangle)]
278
+ pub unsafe extern "C" fn rdx_declaration_singleton_class(pointer: GraphPointer, decl_id: u64) -> *const CDeclaration {
279
+ with_graph(pointer, |graph| {
280
+ let declaration = graph
281
+ .declarations()
282
+ .get(&DeclarationId::new(decl_id))
283
+ .unwrap()
284
+ .as_namespace()
285
+ .unwrap();
286
+
287
+ if let Some(singleton_id) = declaration.singleton_class() {
288
+ Box::into_raw(Box::new(CDeclaration::from_declaration(
289
+ *singleton_id,
290
+ graph.declarations().get(singleton_id).unwrap(),
291
+ )))
292
+ } else {
293
+ ptr::null()
294
+ }
295
+ })
296
+ }
297
+
298
+ /// Returns the owner of the declaration (attached object in the case of singleton classes)
299
+ ///
300
+ /// # Safety
301
+ ///
302
+ /// Assumes pointer is valid
303
+ ///
304
+ /// # Panics
305
+ ///
306
+ /// Will panic if invoked on a non-existing or non-namespace declaration
307
+ #[unsafe(no_mangle)]
308
+ pub unsafe extern "C" fn rdx_declaration_owner(pointer: GraphPointer, decl_id: u64) -> *const CDeclaration {
309
+ with_graph(pointer, |graph| {
310
+ let declaration = graph.declarations().get(&DeclarationId::new(decl_id)).unwrap();
311
+ let owner_id = *declaration.owner_id();
312
+ Box::into_raw(Box::new(CDeclaration::from_declaration(
313
+ owner_id,
314
+ graph.declarations().get(&owner_id).unwrap(),
315
+ )))
316
+ .cast_const()
317
+ })
318
+ }
319
+
320
+ /// Frees a `CDeclaration` allocated on the Rust side
321
+ ///
322
+ /// # Safety
323
+ ///
324
+ /// - `ptr` must be a valid pointer previously returned by a function returning `*const CDeclaration`
325
+ /// - `ptr` must not be used after being freed
326
+ #[unsafe(no_mangle)]
327
+ pub unsafe extern "C" fn free_c_declaration(ptr: *const CDeclaration) {
328
+ if ptr.is_null() {
329
+ return;
330
+ }
331
+
332
+ unsafe {
333
+ let _ = Box::from_raw(ptr.cast_mut());
334
+ }
335
+ }
336
+
337
+ /// Returns an iterator over the ancestor declarations of a given declaration
338
+ ///
339
+ /// # Safety
340
+ ///
341
+ /// Assumes that the graph and member pointers are valid
342
+ ///
343
+ /// # Panics
344
+ ///
345
+ /// Will panic if there's inconsistent graph data
346
+ #[unsafe(no_mangle)]
347
+ pub unsafe extern "C" fn rdx_declaration_ancestors(pointer: GraphPointer, decl_id: u64) -> *mut DeclarationsIter {
348
+ let declarations = with_graph(pointer, |graph| {
349
+ let declaration_id = DeclarationId::new(decl_id);
350
+
351
+ let Some(Declaration::Namespace(declaration)) = graph.declarations().get(&declaration_id) else {
352
+ return Vec::new();
353
+ };
354
+
355
+ declaration
356
+ .ancestors()
357
+ .into_iter()
358
+ .filter_map(|ancestor| match ancestor {
359
+ Ancestor::Complete(id) => Some(CDeclaration::from_declaration(
360
+ *id,
361
+ graph.declarations().get(id).unwrap(),
362
+ )),
363
+ Ancestor::Partial(_) => None,
364
+ })
365
+ .collect::<Vec<_>>()
366
+ });
367
+
368
+ DeclarationsIter::new(declarations.into_boxed_slice())
369
+ }
370
+
371
+ /// Returns an iterator over the descendant declarations of a given declaration
372
+ ///
373
+ /// # Safety
374
+ ///
375
+ /// Assumes that the graph and member pointers are valid
376
+ ///
377
+ /// # Panics
378
+ ///
379
+ /// Will panic if there's inconsistent graph data
380
+ #[unsafe(no_mangle)]
381
+ pub unsafe extern "C" fn rdx_declaration_descendants(pointer: GraphPointer, decl_id: u64) -> *mut DeclarationsIter {
382
+ let declarations = with_graph(pointer, |graph| {
383
+ let declaration_id = DeclarationId::new(decl_id);
384
+
385
+ let Some(Declaration::Namespace(declaration)) = graph.declarations().get(&declaration_id) else {
386
+ return Vec::new();
387
+ };
388
+
389
+ declaration
390
+ .descendants()
391
+ .iter()
392
+ .map(|id| CDeclaration::from_declaration(*id, graph.declarations().get(id).unwrap()))
393
+ .collect::<Vec<_>>()
394
+ });
395
+
396
+ DeclarationsIter::new(declarations.into_boxed_slice())
397
+ }
398
+
399
+ /// Returns an iterator over the member declarations of a given namespace declaration
400
+ ///
401
+ /// # Safety
402
+ ///
403
+ /// Assumes that the graph pointer is valid
404
+ ///
405
+ /// # Panics
406
+ ///
407
+ /// Will panic if there's inconsistent graph data
408
+ #[unsafe(no_mangle)]
409
+ pub unsafe extern "C" fn rdx_declaration_members(pointer: GraphPointer, decl_id: u64) -> *mut DeclarationsIter {
410
+ let declarations = with_graph(pointer, |graph| {
411
+ let declaration_id = DeclarationId::new(decl_id);
412
+
413
+ let Some(Declaration::Namespace(declaration)) = graph.declarations().get(&declaration_id) else {
414
+ return Vec::new();
415
+ };
416
+
417
+ declaration
418
+ .members()
419
+ .values()
420
+ .map(|id| CDeclaration::from_declaration(*id, graph.declarations().get(id).unwrap()))
421
+ .collect::<Vec<_>>()
422
+ });
423
+
424
+ DeclarationsIter::new(declarations.into_boxed_slice())
425
+ }
426
+
427
+ /// Creates a new iterator over constant references for a given declaration.
428
+ ///
429
+ /// # Safety
430
+ ///
431
+ /// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
432
+ /// - The returned pointer must be freed with `rdx_constant_references_iter_free`.
433
+ #[unsafe(no_mangle)]
434
+ pub unsafe extern "C" fn rdx_declaration_constant_references_iter_new(
435
+ pointer: GraphPointer,
436
+ declaration_id: u64,
437
+ ) -> *mut ConstantReferencesIter {
438
+ with_graph(pointer, |graph| {
439
+ let decl_id_typed = DeclarationId::new(declaration_id);
440
+
441
+ let Some(decl) = graph.declarations().get(&decl_id_typed) else {
442
+ return ptr::null_mut();
443
+ };
444
+ let Some(constant_references) = decl.constant_references() else {
445
+ return ptr::null_mut();
446
+ };
447
+
448
+ let entries: Vec<_> = constant_references
449
+ .iter()
450
+ .map(|ref_id| CConstantReference {
451
+ id: **ref_id,
452
+ declaration_id,
453
+ })
454
+ .collect();
455
+
456
+ ConstantReferencesIter::new(entries.into_boxed_slice())
457
+ })
458
+ }
459
+
460
+ /// Creates a new iterator over method references for a given declaration.
461
+ ///
462
+ /// # Safety
463
+ ///
464
+ /// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
465
+ /// - The returned pointer must be freed with `rdx_method_references_iter_free`.
466
+ #[unsafe(no_mangle)]
467
+ pub unsafe extern "C" fn rdx_declaration_method_references_iter_new(
468
+ pointer: GraphPointer,
469
+ decl_id: u64,
470
+ ) -> *mut MethodReferencesIter {
471
+ with_graph(pointer, |graph| {
472
+ let decl_id = DeclarationId::new(decl_id);
473
+ let Some(Declaration::Method(decl)) = graph.declarations().get(&decl_id) else {
474
+ return ptr::null_mut();
475
+ };
476
+
477
+ let entries: Vec<_> = decl
478
+ .references()
479
+ .iter()
480
+ .map(|ref_id| CMethodReference { id: **ref_id })
481
+ .collect();
482
+
483
+ MethodReferencesIter::new(entries.into_boxed_slice())
484
+ })
485
+ }