rubydex 0.4.0-aarch64-linux → 0.4.2-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.
- checksums.yaml +4 -4
- data/README.md +9 -14
- data/THIRD_PARTY_LICENSES.html +13 -24
- data/ext/rubydex/definition.c +34 -0
- data/ext/rubydex/definition.h +3 -0
- data/ext/rubydex/diagnostic.c +2 -49
- data/ext/rubydex/extconf.rb +4 -2
- data/ext/rubydex/graph.c +59 -11
- 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/cli/command/dead_code.rb +59 -0
- data/lib/rubydex/cli/command/lint/explain.rb +8 -6
- data/lib/rubydex/cli/command/lint.rb +10 -4
- data/lib/rubydex/librubydex_sys.so +0 -0
- data/lib/rubydex/linter/rule_loader.rb +1 -1
- data/lib/rubydex/mcp_server/tools/codebase_stats_tool.rb +1 -1
- data/lib/rubydex/mcp_server/tools/find_constant_references_tool.rb +4 -4
- data/lib/rubydex/mcp_server/tools/find_dead_code_candidates_tool.rb +33 -0
- data/lib/rubydex/mcp_server/tools/get_declaration_tool.rb +2 -2
- data/lib/rubydex/mcp_server/tools/get_descendants_tool.rb +4 -4
- data/lib/rubydex/mcp_server/tools/get_file_declarations_tool.rb +2 -2
- data/lib/rubydex/mcp_server/tools/search_declarations_tool.rb +6 -6
- data/lib/rubydex/mcp_server.rb +24 -12
- data/lib/rubydex/rules/dynamic_ancestor.rb +29 -0
- data/lib/rubydex/rules/dynamic_constant_reference.rb +25 -0
- data/lib/rubydex/rules/dynamic_singleton_definition.rb +30 -0
- data/lib/rubydex/rules/invalid_constant_visibility.rb +28 -0
- data/lib/rubydex/rules/invalid_method_visibility.rb +28 -0
- data/lib/rubydex/rules/parse_error.rb +25 -0
- data/lib/rubydex/rules/parse_warning.rb +28 -0
- data/lib/rubydex/rules/top_level_mixin_self.rb +27 -0
- data/lib/rubydex/rules/undefined_constant_visibility_target.rb +27 -0
- data/lib/rubydex/rules/undefined_method_visibility_target.rb +27 -0
- data/lib/rubydex/skill.rb +1 -0
- data/lib/rubydex/version.rb +1 -1
- data/lib/rubydex.rb +2 -0
- data/lib/rubydex_linter/rules/rule_structure.rb +19 -4
- data/rbi/rubydex.rbi +32 -130
- data/rust/Cargo.lock +17 -11
- data/rust/Cargo.toml +3 -0
- data/rust/rubydex/Cargo.toml +6 -2
- data/rust/rubydex/src/bin/generate_ruby_rules.rs +94 -0
- data/rust/rubydex/src/compile_assertions.rs +2 -0
- data/rust/rubydex/src/config.rs +1 -1
- data/rust/rubydex/src/diagnostic.rs +142 -51
- data/rust/rubydex/src/indexing/rbs_indexer.rs +4 -4
- data/rust/rubydex/src/indexing/ruby_indexer.rs +26 -18
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +42 -2
- data/rust/rubydex/src/indexing.rs +6 -6
- data/rust/rubydex/src/listing.rs +12 -12
- data/rust/rubydex/src/model/built_in.rs +1 -1
- data/rust/rubydex/src/model/comment.rs +4 -4
- data/rust/rubydex/src/model/declaration.rs +25 -17
- data/rust/rubydex/src/model/document.rs +11 -11
- data/rust/rubydex/src/model/graph.rs +3 -3
- data/rust/rubydex/src/offset.rs +1 -13
- data/rust/rubydex/src/operation/ruby_builder.rs +29 -19
- data/rust/rubydex/src/query.rs +193 -2
- data/rust/rubydex/src/test_utils/graph_test.rs +2 -2
- data/rust/rubydex/src/test_utils/local_graph_test.rs +13 -6
- data/rust/rubydex-sys/Cargo.toml +2 -2
- data/rust/rubydex-sys/src/definition_api.rs +69 -2
- data/rust/rubydex-sys/src/diagnostic_api.rs +0 -35
- data/rust/rubydex-sys/src/graph_api.rs +193 -45
- data/rust/rubydex-sys/src/name_api.rs +219 -48
- metadata +199 -187
|
@@ -10,9 +10,10 @@ use crate::{name_api, utils};
|
|
|
10
10
|
use libc::{c_char, c_void};
|
|
11
11
|
use rubydex::config::Config;
|
|
12
12
|
use rubydex::indexing::LanguageId;
|
|
13
|
+
use rubydex::model::definitions::Definition;
|
|
13
14
|
use rubydex::model::encoding::Encoding;
|
|
14
15
|
use rubydex::model::graph::Graph;
|
|
15
|
-
use rubydex::model::ids::{DeclarationId, NameId, UriId, declaration_id_from_lookup_name};
|
|
16
|
+
use rubydex::model::ids::{DeclarationId, DefinitionId, NameId, UriId, declaration_id_from_lookup_name};
|
|
16
17
|
use rubydex::model::keywords;
|
|
17
18
|
use rubydex::model::name::NameRef;
|
|
18
19
|
use rubydex::model::visibility::Visibility;
|
|
@@ -133,6 +134,27 @@ pub unsafe extern "C" fn rdx_graph_declarations_fuzzy_search(
|
|
|
133
134
|
DeclarationsIter::new(entries)
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
/// Returns an iterator over all dead code candidates in the graph.
|
|
138
|
+
///
|
|
139
|
+
/// # Safety
|
|
140
|
+
///
|
|
141
|
+
/// Expects `pointer` to be a valid graph. The returned iterator must be freed with `rdx_graph_declarations_iter_free`.
|
|
142
|
+
#[unsafe(no_mangle)]
|
|
143
|
+
pub unsafe extern "C" fn rdx_graph_dead_code_candidates(pointer: GraphPointer) -> *mut DeclarationsIter {
|
|
144
|
+
let entries = with_graph(pointer, |graph| {
|
|
145
|
+
query::dead_code_candidates(graph)
|
|
146
|
+
.into_iter()
|
|
147
|
+
.filter_map(|id| {
|
|
148
|
+
let decl = graph.declarations().get(&id)?;
|
|
149
|
+
Some(CDeclaration::from_declaration(id, decl))
|
|
150
|
+
})
|
|
151
|
+
.collect::<Vec<CDeclaration>>()
|
|
152
|
+
.into_boxed_slice()
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
DeclarationsIter::new(entries)
|
|
156
|
+
}
|
|
157
|
+
|
|
136
158
|
/// # Panics
|
|
137
159
|
///
|
|
138
160
|
/// Will panic if the nesting cannot be transformed into a vector of strings
|
|
@@ -151,25 +173,98 @@ pub unsafe extern "C" fn rdx_graph_resolve_constant(
|
|
|
151
173
|
let nesting: Vec<String> = unsafe { utils::convert_double_pointer_to_vec(nesting, count).unwrap() };
|
|
152
174
|
let const_name: String = unsafe { utils::convert_char_ptr_to_string(const_name).unwrap() };
|
|
153
175
|
|
|
154
|
-
let Some(
|
|
176
|
+
let Some(tracked_name) = name_api::name_from_nesting_names(graph, &const_name, nesting) else {
|
|
155
177
|
return ptr::null();
|
|
156
178
|
};
|
|
157
179
|
|
|
158
|
-
|
|
180
|
+
resolve_constant_name(tracked_name)
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// Result of resolving a constant using a namespace definition as its lexical context.
|
|
185
|
+
#[repr(u8)]
|
|
186
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
187
|
+
pub enum CDefinitionConstantResolution {
|
|
188
|
+
Resolved = 0,
|
|
189
|
+
NotFound = 1,
|
|
190
|
+
DefinitionNotFound = 2,
|
|
191
|
+
InvalidDefinitionKind = 3,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#[repr(C)]
|
|
195
|
+
#[derive(Debug)]
|
|
196
|
+
pub struct CDefinitionConstantResolutionResult {
|
|
197
|
+
pub status: CDefinitionConstantResolution,
|
|
198
|
+
pub declaration: *const CDeclaration,
|
|
199
|
+
}
|
|
159
200
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
201
|
+
/// Resolves a constant using a namespace definition as its lexical context.
|
|
202
|
+
///
|
|
203
|
+
/// # Panics
|
|
204
|
+
///
|
|
205
|
+
/// Panics if `const_name` cannot be converted to a string.
|
|
206
|
+
///
|
|
207
|
+
/// # Safety
|
|
208
|
+
///
|
|
209
|
+
/// Assumes that `pointer` and `const_name` are valid.
|
|
210
|
+
#[unsafe(no_mangle)]
|
|
211
|
+
pub unsafe extern "C" fn rdx_graph_resolve_constant_from_definition(
|
|
212
|
+
pointer: GraphPointer,
|
|
213
|
+
const_name: *const c_char,
|
|
214
|
+
definition_id: u64,
|
|
215
|
+
) -> CDefinitionConstantResolutionResult {
|
|
216
|
+
with_mut_graph(pointer, |graph| {
|
|
217
|
+
let const_name: String = unsafe { utils::convert_char_ptr_to_string(const_name).unwrap() };
|
|
218
|
+
let nesting = match class_or_module_definition_name_id(graph, DefinitionId::new(definition_id)) {
|
|
219
|
+
Ok(nesting) => nesting,
|
|
220
|
+
Err(status) => {
|
|
221
|
+
return CDefinitionConstantResolutionResult {
|
|
222
|
+
status,
|
|
223
|
+
declaration: ptr::null(),
|
|
224
|
+
};
|
|
164
225
|
}
|
|
165
|
-
None => ptr::null(),
|
|
166
226
|
};
|
|
167
227
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
228
|
+
let Some(tracked_name) = name_api::name_from_lexical_nesting(graph, &const_name, Some(nesting)) else {
|
|
229
|
+
return CDefinitionConstantResolutionResult {
|
|
230
|
+
status: CDefinitionConstantResolution::NotFound,
|
|
231
|
+
declaration: ptr::null(),
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
let declaration = resolve_constant_name(tracked_name);
|
|
236
|
+
let status = if declaration.is_null() {
|
|
237
|
+
CDefinitionConstantResolution::NotFound
|
|
238
|
+
} else {
|
|
239
|
+
CDefinitionConstantResolution::Resolved
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
CDefinitionConstantResolutionResult { status, declaration }
|
|
243
|
+
})
|
|
244
|
+
}
|
|
171
245
|
|
|
172
|
-
|
|
246
|
+
fn class_or_module_definition_name_id(
|
|
247
|
+
graph: &Graph,
|
|
248
|
+
definition_id: DefinitionId,
|
|
249
|
+
) -> Result<NameId, CDefinitionConstantResolution> {
|
|
250
|
+
let Some(definition) = graph.definitions().get(&definition_id) else {
|
|
251
|
+
return Err(CDefinitionConstantResolution::DefinitionNotFound);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
match definition {
|
|
255
|
+
Definition::Class(definition) => Ok(*definition.name_id()),
|
|
256
|
+
Definition::SingletonClass(definition) => Ok(*definition.name_id()),
|
|
257
|
+
Definition::Module(definition) => Ok(*definition.name_id()),
|
|
258
|
+
_ => Err(CDefinitionConstantResolution::InvalidDefinitionKind),
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
fn resolve_constant_name(mut tracked_name: name_api::TrackedName<'_>) -> *const CDeclaration {
|
|
263
|
+
let name_id = tracked_name.name_id();
|
|
264
|
+
let declaration_id = Resolver::new(tracked_name.graph_mut()).resolve_constant(name_id);
|
|
265
|
+
declaration_id.map_or(ptr::null(), |id| {
|
|
266
|
+
let declaration = tracked_name.graph().declarations().get(&id).unwrap();
|
|
267
|
+
Box::into_raw(Box::new(CDeclaration::from_declaration(id, declaration))).cast_const()
|
|
173
268
|
})
|
|
174
269
|
}
|
|
175
270
|
|
|
@@ -644,7 +739,7 @@ pub unsafe extern "C" fn rdx_index_source(
|
|
|
644
739
|
};
|
|
645
740
|
|
|
646
741
|
with_mut_graph(pointer, |graph| {
|
|
647
|
-
indexing::index_source(graph,
|
|
742
|
+
indexing::index_source(graph, uri_str.into(), source_str, &language);
|
|
648
743
|
IndexSourceResult::Success
|
|
649
744
|
})
|
|
650
745
|
}
|
|
@@ -714,19 +809,19 @@ pub unsafe extern "C" fn rdx_completion_candidates_free(ptr: *mut CompletionCand
|
|
|
714
809
|
}
|
|
715
810
|
}
|
|
716
811
|
|
|
717
|
-
/// Converts the nesting
|
|
718
|
-
/// The last
|
|
812
|
+
/// Converts the nesting names into a tracked name.
|
|
813
|
+
/// The last nesting name is treated as the self type; if the array is empty, `"Object"` is used.
|
|
719
814
|
///
|
|
720
|
-
/// Returns `
|
|
815
|
+
/// Returns `None` if the nesting array contains invalid UTF-8.
|
|
721
816
|
///
|
|
722
817
|
/// # Safety
|
|
723
818
|
///
|
|
724
819
|
/// `nesting` must point to `nesting_count` valid, null-terminated UTF-8 strings.
|
|
725
|
-
unsafe fn
|
|
820
|
+
unsafe fn completion_nesting_name(
|
|
726
821
|
graph: &mut Graph,
|
|
727
822
|
nesting: *const *const c_char,
|
|
728
823
|
nesting_count: usize,
|
|
729
|
-
) -> Option<
|
|
824
|
+
) -> Option<name_api::TrackedName<'_>> {
|
|
730
825
|
let mut nesting: Vec<String> = unsafe { utils::convert_double_pointer_to_vec(nesting, nesting_count).ok()? };
|
|
731
826
|
|
|
732
827
|
// When serving completion in a bare script, the self (top level) context is Object
|
|
@@ -736,7 +831,7 @@ unsafe fn completion_nesting_name_id(
|
|
|
736
831
|
nesting.pop().unwrap()
|
|
737
832
|
};
|
|
738
833
|
|
|
739
|
-
name_api::
|
|
834
|
+
name_api::name_from_nesting_names(graph, &self_name, nesting)
|
|
740
835
|
}
|
|
741
836
|
|
|
742
837
|
/// The result of a completion operation, carrying either a candidate array or an error message.
|
|
@@ -765,19 +860,10 @@ impl CompletionResult {
|
|
|
765
860
|
}
|
|
766
861
|
|
|
767
862
|
/// Runs completion for the given receiver and returns a structured result with candidates or an error message
|
|
768
|
-
fn run_and_finalize_completion(
|
|
769
|
-
graph: &mut Graph,
|
|
770
|
-
receiver: CompletionReceiver,
|
|
771
|
-
names_to_untrack: Vec<NameId>,
|
|
772
|
-
) -> CompletionResult {
|
|
863
|
+
fn run_and_finalize_completion(graph: &Graph, receiver: CompletionReceiver) -> CompletionResult {
|
|
773
864
|
let candidates = match query::completion_candidates(graph, CompletionContext::new(receiver)) {
|
|
774
865
|
Ok(candidates) => candidates,
|
|
775
|
-
Err(e) =>
|
|
776
|
-
for name_id in names_to_untrack {
|
|
777
|
-
graph.untrack_name(name_id);
|
|
778
|
-
}
|
|
779
|
-
return CompletionResult::error(&e.to_string());
|
|
780
|
-
}
|
|
866
|
+
Err(e) => return CompletionResult::error(&e.to_string()),
|
|
781
867
|
};
|
|
782
868
|
|
|
783
869
|
let entries: Vec<CCompletionCandidate> = candidates
|
|
@@ -825,10 +911,6 @@ fn run_and_finalize_completion(
|
|
|
825
911
|
})
|
|
826
912
|
.collect();
|
|
827
913
|
|
|
828
|
-
for name_id in names_to_untrack {
|
|
829
|
-
graph.untrack_name(name_id);
|
|
830
|
-
}
|
|
831
|
-
|
|
832
914
|
CompletionResult::success(CompletionCandidateArray::from_vec(entries))
|
|
833
915
|
}
|
|
834
916
|
|
|
@@ -849,20 +931,19 @@ pub unsafe extern "C" fn rdx_graph_complete_expression(
|
|
|
849
931
|
self_receiver: *const c_char,
|
|
850
932
|
) -> CompletionResult {
|
|
851
933
|
with_mut_graph(pointer, |graph| {
|
|
852
|
-
let Some(
|
|
853
|
-
else {
|
|
934
|
+
let Some(tracked_name) = (unsafe { completion_nesting_name(graph, nesting, nesting_count) }) else {
|
|
854
935
|
return CompletionResult::success(ptr::null_mut());
|
|
855
936
|
};
|
|
937
|
+
let name_id = tracked_name.name_id();
|
|
856
938
|
|
|
857
939
|
let self_decl_id = unsafe { decl_id_from_char_ptr(self_receiver) };
|
|
858
940
|
|
|
859
941
|
run_and_finalize_completion(
|
|
860
|
-
graph,
|
|
942
|
+
tracked_name.graph(),
|
|
861
943
|
CompletionReceiver::Expression {
|
|
862
944
|
self_decl_id,
|
|
863
945
|
nesting_name_id: name_id,
|
|
864
946
|
},
|
|
865
|
-
names_to_untrack,
|
|
866
947
|
)
|
|
867
948
|
})
|
|
868
949
|
}
|
|
@@ -896,7 +977,6 @@ pub unsafe extern "C" fn rdx_graph_complete_namespace_access(
|
|
|
896
977
|
self_decl_id,
|
|
897
978
|
namespace_decl_id: declaration_id_from_lookup_name(&name_str),
|
|
898
979
|
},
|
|
899
|
-
Vec::new(),
|
|
900
980
|
)
|
|
901
981
|
})
|
|
902
982
|
}
|
|
@@ -930,7 +1010,6 @@ pub unsafe extern "C" fn rdx_graph_complete_method_call(
|
|
|
930
1010
|
self_decl_id,
|
|
931
1011
|
receiver_decl_id: declaration_id_from_lookup_name(&name_str),
|
|
932
1012
|
},
|
|
933
|
-
Vec::new(),
|
|
934
1013
|
)
|
|
935
1014
|
})
|
|
936
1015
|
}
|
|
@@ -959,22 +1038,20 @@ pub unsafe extern "C" fn rdx_graph_complete_method_argument(
|
|
|
959
1038
|
};
|
|
960
1039
|
|
|
961
1040
|
with_mut_graph(pointer, |graph| {
|
|
962
|
-
let Some((
|
|
963
|
-
(unsafe { completion_nesting_name_id(graph, nesting, nesting_count) })
|
|
964
|
-
else {
|
|
1041
|
+
let Some(tracked_name) = (unsafe { completion_nesting_name(graph, nesting, nesting_count) }) else {
|
|
965
1042
|
return CompletionResult::success(ptr::null_mut());
|
|
966
1043
|
};
|
|
1044
|
+
let nesting_name_id = tracked_name.name_id();
|
|
967
1045
|
|
|
968
1046
|
let self_decl_id = unsafe { decl_id_from_char_ptr(self_receiver) };
|
|
969
1047
|
|
|
970
1048
|
run_and_finalize_completion(
|
|
971
|
-
graph,
|
|
1049
|
+
tracked_name.graph(),
|
|
972
1050
|
CompletionReceiver::MethodArgument {
|
|
973
1051
|
self_decl_id,
|
|
974
1052
|
nesting_name_id,
|
|
975
1053
|
method_decl_id: declaration_id_from_lookup_name(&name_str),
|
|
976
1054
|
},
|
|
977
|
-
names_to_untrack,
|
|
978
1055
|
)
|
|
979
1056
|
})
|
|
980
1057
|
}
|
|
@@ -1095,6 +1172,7 @@ pub unsafe extern "C" fn rdx_keyword_free(ptr: *const CKeyword) {
|
|
|
1095
1172
|
|
|
1096
1173
|
#[cfg(test)]
|
|
1097
1174
|
mod tests {
|
|
1175
|
+
use crate::declaration_api;
|
|
1098
1176
|
use rubydex::indexing::ruby_indexer::RubyIndexer;
|
|
1099
1177
|
|
|
1100
1178
|
use super::*;
|
|
@@ -1145,7 +1223,9 @@ mod tests {
|
|
|
1145
1223
|
nesting_ptrs.as_ptr(),
|
|
1146
1224
|
nesting_ptrs.len(),
|
|
1147
1225
|
);
|
|
1226
|
+
assert!(!decl.is_null());
|
|
1148
1227
|
assert_eq!((*decl).id(), *DeclarationId::from("Foo::BAR"));
|
|
1228
|
+
declaration_api::free_c_declaration(decl);
|
|
1149
1229
|
};
|
|
1150
1230
|
|
|
1151
1231
|
let graph = unsafe { Box::from_raw(graph_ptr.cast::<RwLock<Graph>>()) };
|
|
@@ -1167,4 +1247,72 @@ mod tests {
|
|
|
1167
1247
|
.ref_count()
|
|
1168
1248
|
);
|
|
1169
1249
|
}
|
|
1250
|
+
|
|
1251
|
+
#[test]
|
|
1252
|
+
fn names_are_untracked_after_completion_error() {
|
|
1253
|
+
let mut indexer = RubyIndexer::new(
|
|
1254
|
+
"file:///foo.rb".into(),
|
|
1255
|
+
"
|
|
1256
|
+
class Foo
|
|
1257
|
+
end
|
|
1258
|
+
",
|
|
1259
|
+
);
|
|
1260
|
+
indexer.index();
|
|
1261
|
+
|
|
1262
|
+
let mut graph = Graph::new();
|
|
1263
|
+
graph.consume_document_changes(indexer.local_graph());
|
|
1264
|
+
let mut resolver = Resolver::new(&mut graph);
|
|
1265
|
+
resolver.resolve();
|
|
1266
|
+
|
|
1267
|
+
let (foo_name_id, foo_string_id, name_ref_count, string_ref_count) = graph
|
|
1268
|
+
.names()
|
|
1269
|
+
.iter()
|
|
1270
|
+
.find_map(|(name_id, name)| {
|
|
1271
|
+
let string_id = *name.str();
|
|
1272
|
+
if graph.strings().get(&string_id).unwrap().as_str() == "Foo"
|
|
1273
|
+
&& name.parent_scope().is_none()
|
|
1274
|
+
&& name.nesting().is_none()
|
|
1275
|
+
{
|
|
1276
|
+
Some((
|
|
1277
|
+
*name_id,
|
|
1278
|
+
string_id,
|
|
1279
|
+
name.ref_count(),
|
|
1280
|
+
graph.strings().get(&string_id).unwrap().ref_count(),
|
|
1281
|
+
))
|
|
1282
|
+
} else {
|
|
1283
|
+
None
|
|
1284
|
+
}
|
|
1285
|
+
})
|
|
1286
|
+
.unwrap();
|
|
1287
|
+
let name_count = graph.names().len();
|
|
1288
|
+
let string_count = graph.strings().len();
|
|
1289
|
+
|
|
1290
|
+
let graph_ptr = Box::into_raw(Box::new(RwLock::new(graph))) as GraphPointer;
|
|
1291
|
+
let nesting_strings = [CString::new("Foo").unwrap()];
|
|
1292
|
+
let nesting_ptrs: Vec<*const c_char> = nesting_strings.iter().map(|s| s.as_ptr()).collect();
|
|
1293
|
+
let self_receiver = CString::new("Nonexistent").unwrap();
|
|
1294
|
+
|
|
1295
|
+
let result = unsafe {
|
|
1296
|
+
rdx_graph_complete_expression(
|
|
1297
|
+
graph_ptr,
|
|
1298
|
+
nesting_ptrs.as_ptr(),
|
|
1299
|
+
nesting_ptrs.len(),
|
|
1300
|
+
self_receiver.as_ptr(),
|
|
1301
|
+
)
|
|
1302
|
+
};
|
|
1303
|
+
assert!(result.candidates.is_null());
|
|
1304
|
+
assert!(!result.error.is_null());
|
|
1305
|
+
utils::free_c_string(result.error);
|
|
1306
|
+
|
|
1307
|
+
let graph = unsafe { Box::from_raw(graph_ptr.cast::<RwLock<Graph>>()) };
|
|
1308
|
+
let graph = graph.read().unwrap();
|
|
1309
|
+
|
|
1310
|
+
assert_eq!(name_count, graph.names().len());
|
|
1311
|
+
assert_eq!(string_count, graph.strings().len());
|
|
1312
|
+
assert_eq!(name_ref_count, graph.names().get(&foo_name_id).unwrap().ref_count());
|
|
1313
|
+
assert_eq!(
|
|
1314
|
+
string_ref_count,
|
|
1315
|
+
graph.strings().get(&foo_string_id).unwrap().ref_count()
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1170
1318
|
}
|