rubydex 0.2.9 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +69 -3
- data/THIRD_PARTY_LICENSES.html +34 -1
- data/exe/rdx +131 -55
- data/ext/rubydex/declaration.c +1 -1
- data/ext/rubydex/definition.c +32 -4
- data/ext/rubydex/graph.c +14 -3
- data/ext/rubydex/query.c +105 -0
- data/ext/rubydex/query.h +8 -0
- data/ext/rubydex/reference.c +60 -0
- data/ext/rubydex/rubydex.c +2 -0
- data/ext/rubydex/utils.c +12 -0
- data/ext/rubydex/utils.h +5 -0
- data/lib/rubydex/version.rb +1 -1
- data/rbi/rubydex.rbi +22 -0
- data/rust/Cargo.lock +7 -0
- data/rust/rubydex/Cargo.toml +1 -0
- data/rust/rubydex/benches/graph_memory.rs +22 -4
- data/rust/rubydex/src/compile_assertions.rs +15 -0
- data/rust/rubydex/src/diagnostic.rs +1 -1
- data/rust/rubydex/src/indexing/rbs_indexer.rs +14 -2
- data/rust/rubydex/src/indexing/ruby_indexer.rs +49 -58
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +72 -16
- data/rust/rubydex/src/main.rs +2 -124
- data/rust/rubydex/src/model/declaration.rs +0 -11
- data/rust/rubydex/src/model/definitions.rs +27 -26
- data/rust/rubydex/src/model/document.rs +43 -7
- data/rust/rubydex/src/model/graph.rs +40 -28
- data/rust/rubydex/src/model/id.rs +55 -0
- data/rust/rubydex/src/model/ids.rs +21 -9
- data/rust/rubydex/src/model/name.rs +35 -7
- data/rust/rubydex/src/model/references.rs +16 -13
- data/rust/rubydex/src/operation/ruby_builder.rs +48 -59
- data/rust/rubydex/src/query/cypher/schema.rs +790 -0
- data/rust/rubydex/src/query/cypher/schema_info.rs +161 -0
- data/rust/rubydex/src/query/cypher/tests.rs +228 -0
- data/rust/rubydex/src/query/cypher.rs +57 -0
- data/rust/rubydex/src/query.rs +2 -0
- data/rust/rubydex/src/resolution.rs +248 -227
- data/rust/rubydex/src/resolution_tests.rs +263 -65
- data/rust/rubydex-sys/src/declaration_api.rs +6 -3
- data/rust/rubydex-sys/src/definition_api.rs +27 -7
- data/rust/rubydex-sys/src/graph_api.rs +158 -14
- data/rust/rubydex-sys/src/reference_api.rs +58 -12
- metadata +8 -2
|
@@ -15,47 +15,51 @@ use rubydex::model::ids::{DeclarationId, NameId, UriId, declaration_id_from_look
|
|
|
15
15
|
use rubydex::model::keywords;
|
|
16
16
|
use rubydex::model::name::NameRef;
|
|
17
17
|
use rubydex::model::visibility::Visibility;
|
|
18
|
+
use rubydex::query::cypher::{self, OutputFormat};
|
|
18
19
|
use rubydex::query::{CompletionCandidate, CompletionContext, CompletionReceiver};
|
|
19
20
|
use rubydex::resolution::Resolver;
|
|
20
21
|
use rubydex::{indexing, integrity, listing, query};
|
|
21
22
|
use std::ffi::CString;
|
|
22
23
|
use std::path::{Path, PathBuf};
|
|
23
|
-
use std::{mem, ptr};
|
|
24
|
+
use std::{mem, ptr, sync::RwLock};
|
|
24
25
|
|
|
25
26
|
pub type GraphPointer = *mut c_void;
|
|
26
27
|
|
|
27
|
-
/// Creates a new graph
|
|
28
|
+
/// Creates a new graph wrapped in a `Box<RwLock<Graph>>` for thread-safe shared access across Ractors.
|
|
28
29
|
#[unsafe(no_mangle)]
|
|
29
30
|
pub extern "C" fn rdx_graph_new() -> GraphPointer {
|
|
30
|
-
Box::into_raw(Box::new(Graph::new())) as GraphPointer
|
|
31
|
+
Box::into_raw(Box::new(RwLock::new(Graph::new()))) as GraphPointer
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/// Frees a Graph through its pointer
|
|
34
35
|
#[unsafe(no_mangle)]
|
|
35
36
|
pub extern "C" fn rdx_graph_free(pointer: GraphPointer) {
|
|
36
37
|
unsafe {
|
|
37
|
-
let _ = Box::from_raw(pointer.cast::<Graph
|
|
38
|
+
let _ = Box::from_raw(pointer.cast::<RwLock<Graph>>());
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/// Runs `action` against the graph referenced by `pointer` under a read lock.
|
|
43
|
+
///
|
|
44
|
+
/// # Panics
|
|
45
|
+
///
|
|
46
|
+
/// Panics if the `RwLock` is poisoned (a writer panicked while holding the lock).
|
|
41
47
|
pub fn with_graph<F, T>(pointer: GraphPointer, action: F) -> T
|
|
42
48
|
where
|
|
43
49
|
F: FnOnce(&Graph) -> T,
|
|
44
50
|
{
|
|
45
|
-
let
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
result
|
|
51
|
+
let rwlock = unsafe { &*pointer.cast::<RwLock<Graph>>() };
|
|
52
|
+
let guard = rwlock.read().unwrap();
|
|
53
|
+
action(&guard)
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
fn with_mut_graph<F, T>(pointer: GraphPointer, action: F) -> T
|
|
52
57
|
where
|
|
53
58
|
F: FnOnce(&mut Graph) -> T,
|
|
54
59
|
{
|
|
55
|
-
let
|
|
56
|
-
let
|
|
57
|
-
|
|
58
|
-
result
|
|
60
|
+
let rwlock = unsafe { &*pointer.cast::<RwLock<Graph>>() };
|
|
61
|
+
let mut guard = rwlock.write().unwrap();
|
|
62
|
+
action(&mut guard)
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
/// Searches the graph using exact substring matching, returning every declaration whose name matches any of the
|
|
@@ -1062,6 +1066,145 @@ pub unsafe extern "C" fn rdx_keyword_get(name: *const c_char) -> *const CKeyword
|
|
|
1062
1066
|
}
|
|
1063
1067
|
}
|
|
1064
1068
|
|
|
1069
|
+
/// The result of running a Cypher query, carrying either the formatted output or an error message.
|
|
1070
|
+
#[repr(C)]
|
|
1071
|
+
pub struct CQueryResult {
|
|
1072
|
+
/// Non-null on success; null on error. Caller must free with `free_c_string`.
|
|
1073
|
+
pub output: *const c_char,
|
|
1074
|
+
/// Non-null on error; null on success. Caller must free with `free_c_string`.
|
|
1075
|
+
pub error: *const c_char,
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
impl CQueryResult {
|
|
1079
|
+
fn success(output: &str) -> Self {
|
|
1080
|
+
match CString::new(output) {
|
|
1081
|
+
Ok(c_string) => Self {
|
|
1082
|
+
output: c_string.into_raw().cast_const(),
|
|
1083
|
+
error: ptr::null(),
|
|
1084
|
+
},
|
|
1085
|
+
Err(_) => Self::error("query output contained an interior NUL byte"),
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
fn error(message: &str) -> Self {
|
|
1090
|
+
Self {
|
|
1091
|
+
output: ptr::null(),
|
|
1092
|
+
error: CString::new(message).map_or(ptr::null(), |s| s.into_raw().cast_const()),
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/// The result of parsing a Cypher query into an opaque, reusable parsed-query object.
|
|
1098
|
+
#[repr(C)]
|
|
1099
|
+
pub struct CParseResult {
|
|
1100
|
+
/// Non-null on success: a heap-allocated parsed query. Free with `rdx_cypher_query_free`.
|
|
1101
|
+
pub query: *mut c_void,
|
|
1102
|
+
/// Non-null on error; null on success. Caller must free with `free_c_string`.
|
|
1103
|
+
pub error: *const c_char,
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/// Parses a Cypher query string into an opaque parsed-query object, without needing a graph.
|
|
1107
|
+
///
|
|
1108
|
+
/// On success, `query` is a heap-allocated parsed query that can be executed against a graph with
|
|
1109
|
+
/// `rdx_query_run` and must eventually be freed with `rdx_cypher_query_free`. On failure, `error`
|
|
1110
|
+
/// holds the message.
|
|
1111
|
+
///
|
|
1112
|
+
/// # Safety
|
|
1113
|
+
///
|
|
1114
|
+
/// - `query` must be a valid, null-terminated UTF-8 string.
|
|
1115
|
+
#[unsafe(no_mangle)]
|
|
1116
|
+
pub unsafe extern "C" fn rdx_cypher_parse(query: *const c_char) -> CParseResult {
|
|
1117
|
+
let Ok(query_str) = (unsafe { utils::convert_char_ptr_to_string(query) }) else {
|
|
1118
|
+
return CParseResult {
|
|
1119
|
+
query: ptr::null_mut(),
|
|
1120
|
+
error: CString::new("query is not valid UTF-8").map_or(ptr::null(), |s| s.into_raw().cast_const()),
|
|
1121
|
+
};
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
match cypher::parse(&query_str) {
|
|
1125
|
+
Ok(parsed) => CParseResult {
|
|
1126
|
+
query: Box::into_raw(Box::new(parsed)).cast::<c_void>(),
|
|
1127
|
+
error: ptr::null(),
|
|
1128
|
+
},
|
|
1129
|
+
Err(error) => CParseResult {
|
|
1130
|
+
query: ptr::null_mut(),
|
|
1131
|
+
error: CString::new(error.to_string()).map_or(ptr::null(), |s| s.into_raw().cast_const()),
|
|
1132
|
+
},
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/// Frees a parsed query previously returned by `rdx_cypher_parse`.
|
|
1137
|
+
///
|
|
1138
|
+
/// # Safety
|
|
1139
|
+
///
|
|
1140
|
+
/// - `query` must be a pointer returned by `rdx_cypher_parse`, or null. It must not be used after.
|
|
1141
|
+
#[unsafe(no_mangle)]
|
|
1142
|
+
pub unsafe extern "C" fn rdx_cypher_query_free(query: *mut c_void) {
|
|
1143
|
+
if query.is_null() {
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
let _ = unsafe { Box::from_raw(query.cast::<cypher::Query>()) };
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/// Executes a previously parsed query (from `rdx_cypher_parse`) against the graph and returns the
|
|
1150
|
+
/// formatted output or an error message. `format` must be `"table"` or `"json"`.
|
|
1151
|
+
///
|
|
1152
|
+
/// # Safety
|
|
1153
|
+
///
|
|
1154
|
+
/// - `query` must be a valid pointer returned by `rdx_cypher_parse`.
|
|
1155
|
+
/// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
|
|
1156
|
+
/// - `format` must be a valid, null-terminated UTF-8 string.
|
|
1157
|
+
#[unsafe(no_mangle)]
|
|
1158
|
+
pub unsafe extern "C" fn rdx_query_run(
|
|
1159
|
+
query: *const c_void,
|
|
1160
|
+
pointer: GraphPointer,
|
|
1161
|
+
format: *const c_char,
|
|
1162
|
+
) -> CQueryResult {
|
|
1163
|
+
if query.is_null() {
|
|
1164
|
+
return CQueryResult::error("query is null");
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
let Ok(format_str) = (unsafe { utils::convert_char_ptr_to_string(format) }) else {
|
|
1168
|
+
return CQueryResult::error("format is not valid UTF-8");
|
|
1169
|
+
};
|
|
1170
|
+
|
|
1171
|
+
let output_format = match format_str.as_str() {
|
|
1172
|
+
"table" => OutputFormat::Table,
|
|
1173
|
+
"json" => OutputFormat::Json,
|
|
1174
|
+
other => {
|
|
1175
|
+
return CQueryResult::error(&format!("unknown query format `{other}` (expected `table` or `json`)"));
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
|
|
1179
|
+
let parsed = unsafe { &*query.cast::<cypher::Query>() };
|
|
1180
|
+
|
|
1181
|
+
with_graph(pointer, |graph| {
|
|
1182
|
+
match cypher::run_parsed(graph, parsed, output_format) {
|
|
1183
|
+
Ok(output) => CQueryResult::success(&output),
|
|
1184
|
+
Err(error) => CQueryResult::error(&error.to_string()),
|
|
1185
|
+
}
|
|
1186
|
+
})
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/// Returns a description of the queryable Cypher schema (node labels, relationship types, and
|
|
1190
|
+
/// properties) in the given format (`"table"` or `"json"`). The schema is static and requires no
|
|
1191
|
+
/// graph. Caller must free the returned pointer with `free_c_string`.
|
|
1192
|
+
///
|
|
1193
|
+
/// # Safety
|
|
1194
|
+
///
|
|
1195
|
+
/// - `format` must be a valid, null-terminated UTF-8 string.
|
|
1196
|
+
#[unsafe(no_mangle)]
|
|
1197
|
+
pub unsafe extern "C" fn rdx_cypher_schema(format: *const c_char) -> *const c_char {
|
|
1198
|
+
let format_str = unsafe { utils::convert_char_ptr_to_string(format) }.unwrap_or_else(|_| "table".to_string());
|
|
1199
|
+
let output_format = if format_str == "json" {
|
|
1200
|
+
OutputFormat::Json
|
|
1201
|
+
} else {
|
|
1202
|
+
OutputFormat::Table
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
CString::new(cypher::schema(output_format)).map_or(ptr::null(), |s| s.into_raw().cast_const())
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1065
1208
|
#[repr(u8)]
|
|
1066
1209
|
#[derive(Debug, Clone, Copy)]
|
|
1067
1210
|
pub enum CVisibility {
|
|
@@ -1170,7 +1313,7 @@ mod tests {
|
|
|
1170
1313
|
.ref_count()
|
|
1171
1314
|
);
|
|
1172
1315
|
|
|
1173
|
-
let graph_ptr = Box::into_raw(Box::new(graph)) as GraphPointer;
|
|
1316
|
+
let graph_ptr = Box::into_raw(Box::new(RwLock::new(graph))) as GraphPointer;
|
|
1174
1317
|
|
|
1175
1318
|
// Build the nesting array: ["Foo"] since BAR is inside class Foo
|
|
1176
1319
|
let nesting_strings = [CString::new("Foo").unwrap()];
|
|
@@ -1186,7 +1329,8 @@ mod tests {
|
|
|
1186
1329
|
assert_eq!((*decl).id(), *DeclarationId::from("Foo::BAR"));
|
|
1187
1330
|
};
|
|
1188
1331
|
|
|
1189
|
-
let graph = unsafe { Box::from_raw(graph_ptr.cast::<Graph
|
|
1332
|
+
let graph = unsafe { Box::from_raw(graph_ptr.cast::<RwLock<Graph>>()) };
|
|
1333
|
+
let graph = graph.read().unwrap();
|
|
1190
1334
|
|
|
1191
1335
|
assert_eq!(
|
|
1192
1336
|
1,
|
|
@@ -120,7 +120,7 @@ pub unsafe extern "C" fn rdx_method_references_iter_free(iter: *mut MethodRefere
|
|
|
120
120
|
unsafe { MethodReferencesIter::free(iter) }
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
/// Returns the UTF-8 name string for a constant reference id.
|
|
123
|
+
/// Returns the UTF-8 name string for a constant reference id, or NULL if the reference cannot be found.
|
|
124
124
|
/// Caller must free with `free_c_string`.
|
|
125
125
|
///
|
|
126
126
|
/// # Safety
|
|
@@ -129,12 +129,14 @@ pub unsafe extern "C" fn rdx_method_references_iter_free(iter: *mut MethodRefere
|
|
|
129
129
|
///
|
|
130
130
|
/// # Panics
|
|
131
131
|
///
|
|
132
|
-
/// This function will panic if the reference cannot be found.
|
|
132
|
+
/// This function will panic if the reference's name cannot be found.
|
|
133
133
|
#[unsafe(no_mangle)]
|
|
134
134
|
pub unsafe extern "C" fn rdx_constant_reference_name(pointer: GraphPointer, reference_id: u64) -> *const c_char {
|
|
135
135
|
with_graph(pointer, |graph| {
|
|
136
136
|
let ref_id = ConstantReferenceId::new(reference_id);
|
|
137
|
-
let reference = graph.constant_references().get(&ref_id)
|
|
137
|
+
let Some(reference) = graph.constant_references().get(&ref_id) else {
|
|
138
|
+
return ptr::null();
|
|
139
|
+
};
|
|
138
140
|
let name = graph.names().get(reference.name_id()).expect("Name ID should exist");
|
|
139
141
|
|
|
140
142
|
let name_string = graph
|
|
@@ -146,7 +148,7 @@ pub unsafe extern "C" fn rdx_constant_reference_name(pointer: GraphPointer, refe
|
|
|
146
148
|
})
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
/// Returns the UTF-8 name string for a method reference id.
|
|
151
|
+
/// Returns the UTF-8 name string for a method reference id, or NULL if the reference cannot be found.
|
|
150
152
|
/// Caller must free with `free_c_string`.
|
|
151
153
|
///
|
|
152
154
|
/// # Safety
|
|
@@ -155,12 +157,14 @@ pub unsafe extern "C" fn rdx_constant_reference_name(pointer: GraphPointer, refe
|
|
|
155
157
|
///
|
|
156
158
|
/// # Panics
|
|
157
159
|
///
|
|
158
|
-
/// This function will panic if the reference cannot be found.
|
|
160
|
+
/// This function will panic if the reference's name cannot be found.
|
|
159
161
|
#[unsafe(no_mangle)]
|
|
160
162
|
pub unsafe extern "C" fn rdx_method_reference_name(pointer: GraphPointer, reference_id: u64) -> *const c_char {
|
|
161
163
|
with_graph(pointer, |graph| {
|
|
162
164
|
let ref_id = MethodReferenceId::new(reference_id);
|
|
163
|
-
let reference = graph.method_references().get(&ref_id)
|
|
165
|
+
let Some(reference) = graph.method_references().get(&ref_id) else {
|
|
166
|
+
return ptr::null();
|
|
167
|
+
};
|
|
164
168
|
let name = graph
|
|
165
169
|
.strings()
|
|
166
170
|
.get(reference.str())
|
|
@@ -170,7 +174,7 @@ pub unsafe extern "C" fn rdx_method_reference_name(pointer: GraphPointer, refere
|
|
|
170
174
|
})
|
|
171
175
|
}
|
|
172
176
|
|
|
173
|
-
/// Returns a newly allocated `Location` for the given constant reference id.
|
|
177
|
+
/// Returns a newly allocated `Location` for the given constant reference id, or NULL if the reference cannot be found.
|
|
174
178
|
/// Caller must free the returned pointer with `rdx_location_free`.
|
|
175
179
|
///
|
|
176
180
|
/// # Safety
|
|
@@ -180,12 +184,14 @@ pub unsafe extern "C" fn rdx_method_reference_name(pointer: GraphPointer, refere
|
|
|
180
184
|
///
|
|
181
185
|
/// # Panics
|
|
182
186
|
///
|
|
183
|
-
/// This function will panic if
|
|
187
|
+
/// This function will panic if the reference's document cannot be found.
|
|
184
188
|
#[unsafe(no_mangle)]
|
|
185
189
|
pub unsafe extern "C" fn rdx_constant_reference_location(pointer: GraphPointer, reference_id: u64) -> *mut Location {
|
|
186
190
|
with_graph(pointer, |graph| {
|
|
187
191
|
let ref_id = ConstantReferenceId::new(reference_id);
|
|
188
|
-
let reference = graph.constant_references().get(&ref_id)
|
|
192
|
+
let Some(reference) = graph.constant_references().get(&ref_id) else {
|
|
193
|
+
return ptr::null_mut();
|
|
194
|
+
};
|
|
189
195
|
let document = graph
|
|
190
196
|
.documents()
|
|
191
197
|
.get(&reference.uri_id())
|
|
@@ -226,6 +232,25 @@ pub unsafe extern "C" fn rdx_resolved_constant_reference_declaration(
|
|
|
226
232
|
})
|
|
227
233
|
}
|
|
228
234
|
|
|
235
|
+
/// Returns a pointer to the URI ID of the document a constant reference belongs
|
|
236
|
+
/// to, or NULL if the reference cannot be found. Caller must free the returned
|
|
237
|
+
/// pointer with `free_u64`.
|
|
238
|
+
///
|
|
239
|
+
/// # Safety
|
|
240
|
+
/// - `pointer` must be a valid pointer previously returned by `rdx_graph_new`.
|
|
241
|
+
/// - `reference_id` must be a valid reference id.
|
|
242
|
+
#[unsafe(no_mangle)]
|
|
243
|
+
pub unsafe extern "C" fn rdx_constant_reference_document(pointer: GraphPointer, reference_id: u64) -> *const u64 {
|
|
244
|
+
with_graph(pointer, |graph| {
|
|
245
|
+
let ref_id = ConstantReferenceId::new(reference_id);
|
|
246
|
+
if let Some(reference) = graph.constant_references().get(&ref_id) {
|
|
247
|
+
Box::into_raw(Box::new(*reference.uri_id())).cast_const()
|
|
248
|
+
} else {
|
|
249
|
+
ptr::null()
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
|
|
229
254
|
/// Returns the declaration of the resolved receiver for the given method reference. Returns NULL when the method
|
|
230
255
|
/// reference has no tracked receiver or when the receiver could not be resolved. Caller must free with
|
|
231
256
|
/// `free_c_declaration`.
|
|
@@ -263,7 +288,7 @@ pub unsafe extern "C" fn rdx_method_reference_receiver_declaration(
|
|
|
263
288
|
})
|
|
264
289
|
}
|
|
265
290
|
|
|
266
|
-
/// Returns a newly allocated `Location` for the given method reference id.
|
|
291
|
+
/// Returns a newly allocated `Location` for the given method reference id, or NULL if the reference cannot be found.
|
|
267
292
|
/// Caller must free the returned pointer with `rdx_location_free`.
|
|
268
293
|
///
|
|
269
294
|
/// # Safety
|
|
@@ -273,12 +298,14 @@ pub unsafe extern "C" fn rdx_method_reference_receiver_declaration(
|
|
|
273
298
|
///
|
|
274
299
|
/// # Panics
|
|
275
300
|
///
|
|
276
|
-
/// This function will panic if
|
|
301
|
+
/// This function will panic if the reference's document cannot be found.
|
|
277
302
|
#[unsafe(no_mangle)]
|
|
278
303
|
pub unsafe extern "C" fn rdx_method_reference_location(pointer: GraphPointer, reference_id: u64) -> *mut Location {
|
|
279
304
|
with_graph(pointer, |graph| {
|
|
280
305
|
let ref_id = MethodReferenceId::new(reference_id);
|
|
281
|
-
let reference = graph.method_references().get(&ref_id)
|
|
306
|
+
let Some(reference) = graph.method_references().get(&ref_id) else {
|
|
307
|
+
return ptr::null_mut();
|
|
308
|
+
};
|
|
282
309
|
let document = graph
|
|
283
310
|
.documents()
|
|
284
311
|
.get(&reference.uri_id())
|
|
@@ -288,6 +315,25 @@ pub unsafe extern "C" fn rdx_method_reference_location(pointer: GraphPointer, re
|
|
|
288
315
|
})
|
|
289
316
|
}
|
|
290
317
|
|
|
318
|
+
/// Returns a pointer to the URI ID of the document a method reference belongs
|
|
319
|
+
/// to, or NULL if the reference cannot be found. Caller must free the returned
|
|
320
|
+
/// pointer with `free_u64`.
|
|
321
|
+
///
|
|
322
|
+
/// # Safety
|
|
323
|
+
/// - `pointer` must be a valid pointer previously returned by `rdx_graph_new`.
|
|
324
|
+
/// - `reference_id` must be a valid reference id.
|
|
325
|
+
#[unsafe(no_mangle)]
|
|
326
|
+
pub unsafe extern "C" fn rdx_method_reference_document(pointer: GraphPointer, reference_id: u64) -> *const u64 {
|
|
327
|
+
with_graph(pointer, |graph| {
|
|
328
|
+
let ref_id = MethodReferenceId::new(reference_id);
|
|
329
|
+
if let Some(reference) = graph.method_references().get(&ref_id) {
|
|
330
|
+
Box::into_raw(Box::new(*reference.uri_id())).cast_const()
|
|
331
|
+
} else {
|
|
332
|
+
ptr::null()
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
|
|
291
337
|
/// Frees a `CConstantReference` previously returned by an FFI function.
|
|
292
338
|
///
|
|
293
339
|
/// # Safety
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubydex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shopify
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A high-performance static analysis suite for Ruby, built in Rust with
|
|
14
14
|
Ruby APIs
|
|
@@ -38,6 +38,8 @@ files:
|
|
|
38
38
|
- ext/rubydex/handle.h
|
|
39
39
|
- ext/rubydex/location.c
|
|
40
40
|
- ext/rubydex/location.h
|
|
41
|
+
- ext/rubydex/query.c
|
|
42
|
+
- ext/rubydex/query.h
|
|
41
43
|
- ext/rubydex/reference.c
|
|
42
44
|
- ext/rubydex/reference.h
|
|
43
45
|
- ext/rubydex/rubydex.c
|
|
@@ -128,6 +130,10 @@ files:
|
|
|
128
130
|
- rust/rubydex/src/operation/ruby_builder.rs
|
|
129
131
|
- rust/rubydex/src/position.rs
|
|
130
132
|
- rust/rubydex/src/query.rs
|
|
133
|
+
- rust/rubydex/src/query/cypher.rs
|
|
134
|
+
- rust/rubydex/src/query/cypher/schema.rs
|
|
135
|
+
- rust/rubydex/src/query/cypher/schema_info.rs
|
|
136
|
+
- rust/rubydex/src/query/cypher/tests.rs
|
|
131
137
|
- rust/rubydex/src/resolution.rs
|
|
132
138
|
- rust/rubydex/src/resolution_tests.rs
|
|
133
139
|
- rust/rubydex/src/stats.rs
|