rubydex 0.4.1-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 +11 -0
- data/THIRD_PARTY_LICENSES.html +13 -24
- data/lib/rubydex/cli/command/dead_code.rb +59 -0
- data/lib/rubydex/librubydex_sys.so +0 -0
- 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/version.rb +1 -1
- data/rust/Cargo.lock +17 -11
- data/rust/Cargo.toml +3 -0
- data/rust/rubydex/Cargo.toml +2 -2
- data/rust/rubydex/src/compile_assertions.rs +2 -0
- data/rust/rubydex/src/config.rs +1 -1
- 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 +3 -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 +1 -1
- data/rust/rubydex-sys/src/graph_api.rs +96 -49
- data/rust/rubydex-sys/src/name_api.rs +193 -58
- metadata +199 -198
|
@@ -1,63 +1,105 @@
|
|
|
1
1
|
use rubydex::model::{graph::Graph, ids::NameId, name::ParentScope};
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
struct NameTracker<'graph> {
|
|
4
|
+
graph: &'graph mut Graph,
|
|
5
|
+
tracked_name_ids: Vec<NameId>,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
impl<'graph> NameTracker<'graph> {
|
|
9
|
+
fn new(graph: &'graph mut Graph) -> Self {
|
|
10
|
+
Self {
|
|
11
|
+
graph,
|
|
12
|
+
tracked_name_ids: Vec::new(),
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fn track_name(&mut self, string: &str, parent_scope: ParentScope, nesting: Option<NameId>) -> NameId {
|
|
17
|
+
let str_id = self.graph.intern_string(string.to_owned());
|
|
18
|
+
let name_id = self.graph.add_name(str_id, parent_scope, nesting);
|
|
19
|
+
self.tracked_name_ids.push(name_id);
|
|
20
|
+
name_id
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl Drop for NameTracker<'_> {
|
|
25
|
+
fn drop(&mut self) {
|
|
26
|
+
for name_id in self.tracked_name_ids.drain(..) {
|
|
27
|
+
self.graph.untrack_name(name_id);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// A name temporarily tracked in a graph. Dropping this guard undoes every name and string reference-count increment
|
|
33
|
+
/// made while building the name.
|
|
34
|
+
pub struct TrackedName<'graph> {
|
|
35
|
+
tracker: NameTracker<'graph>,
|
|
36
|
+
name_id: NameId,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl<'graph> TrackedName<'graph> {
|
|
40
|
+
fn new(tracker: NameTracker<'graph>, name_id: NameId) -> Self {
|
|
41
|
+
TrackedName { tracker, name_id }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[must_use]
|
|
45
|
+
pub fn name_id(&self) -> NameId {
|
|
46
|
+
self.name_id
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#[must_use]
|
|
50
|
+
pub fn graph(&self) -> &Graph {
|
|
51
|
+
&*self.tracker.graph
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pub fn graph_mut(&mut self) -> &mut Graph {
|
|
55
|
+
&mut *self.tracker.graph
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Takes a constant name and nesting names (e.g.: `["Foo", "Bar::Baz", "Qux"]`) and transforms them into a `NameId`,
|
|
60
|
+
/// registering each required part in the graph. The names are untracked when the returned guard is dropped.
|
|
61
|
+
/// Returns `None` if the constant name contains no valid identifier parts (e.g.: `""`, `"::"`, `"Foo::"`).
|
|
62
|
+
pub fn name_from_nesting_names<'graph>(
|
|
63
|
+
graph: &'graph mut Graph,
|
|
8
64
|
const_name: &str,
|
|
9
65
|
nesting: Vec<String>,
|
|
10
|
-
) -> Option<
|
|
66
|
+
) -> Option<TrackedName<'graph>> {
|
|
11
67
|
let mut current_nesting = None;
|
|
12
68
|
let mut current_name = ParentScope::None;
|
|
13
|
-
let mut
|
|
69
|
+
let mut tracker = NameTracker::new(graph);
|
|
14
70
|
|
|
15
71
|
for entry in nesting {
|
|
16
|
-
process_qualified_name(
|
|
72
|
+
process_qualified_name(&mut tracker, &entry, current_nesting, &mut current_name);
|
|
17
73
|
current_nesting = current_name.as_ref().copied();
|
|
18
74
|
current_name = ParentScope::None;
|
|
19
75
|
}
|
|
20
76
|
|
|
21
|
-
process_qualified_name(
|
|
22
|
-
graph,
|
|
23
|
-
const_name,
|
|
24
|
-
current_nesting,
|
|
25
|
-
&mut current_name,
|
|
26
|
-
&mut names_to_untrack,
|
|
27
|
-
);
|
|
77
|
+
process_qualified_name(&mut tracker, const_name, current_nesting, &mut current_name);
|
|
28
78
|
|
|
29
79
|
let (ParentScope::Some(name_id) | ParentScope::Attached(name_id)) = current_name else {
|
|
30
|
-
// Invalid names may leave temporary parts in the graph (e.g. `Foo` from `Foo::`).
|
|
31
|
-
for name_id in names_to_untrack {
|
|
32
|
-
graph.untrack_name(name_id);
|
|
33
|
-
}
|
|
34
80
|
return None;
|
|
35
81
|
};
|
|
36
82
|
|
|
37
|
-
Some((
|
|
83
|
+
Some(TrackedName::new(tracker, name_id))
|
|
38
84
|
}
|
|
39
85
|
|
|
40
|
-
/// Takes a constant name and an existing lexical nesting and transforms
|
|
41
|
-
/// part in the graph.
|
|
42
|
-
pub fn
|
|
43
|
-
graph: &mut Graph,
|
|
86
|
+
/// Takes a constant name and an existing lexical nesting and transforms them into a `NameId`, registering each required
|
|
87
|
+
/// part in the graph. The names are untracked when the returned guard is dropped.
|
|
88
|
+
pub fn name_from_lexical_nesting<'graph>(
|
|
89
|
+
graph: &'graph mut Graph,
|
|
44
90
|
const_name: &str,
|
|
45
91
|
nesting: Option<NameId>,
|
|
46
|
-
) -> Option<
|
|
92
|
+
) -> Option<TrackedName<'graph>> {
|
|
47
93
|
let mut current_name = ParentScope::None;
|
|
48
|
-
let mut
|
|
94
|
+
let mut tracker = NameTracker::new(graph);
|
|
49
95
|
|
|
50
|
-
process_qualified_name(
|
|
96
|
+
process_qualified_name(&mut tracker, const_name, nesting, &mut current_name);
|
|
51
97
|
|
|
52
98
|
let (ParentScope::Some(name_id) | ParentScope::Attached(name_id)) = current_name else {
|
|
53
|
-
// Invalid names may leave temporary parts in the graph (e.g. `Foo` from `Foo::`).
|
|
54
|
-
for name_id in names_to_untrack {
|
|
55
|
-
graph.untrack_name(name_id);
|
|
56
|
-
}
|
|
57
99
|
return None;
|
|
58
100
|
};
|
|
59
101
|
|
|
60
|
-
Some((
|
|
102
|
+
Some(TrackedName::new(tracker, name_id))
|
|
61
103
|
}
|
|
62
104
|
|
|
63
105
|
/// Processes a qualified name (e.g., `"Foo::Bar"` or `"<Foo>"`) by splitting on `"::"` and registering each part in the
|
|
@@ -66,11 +108,10 @@ pub fn name_in_nesting_to_name_id(
|
|
|
66
108
|
/// When a singleton is the first part (i.e., `current_name` has no parent), `current_nesting` is used as the attachment
|
|
67
109
|
/// point.
|
|
68
110
|
fn process_qualified_name(
|
|
69
|
-
|
|
111
|
+
tracker: &mut NameTracker<'_>,
|
|
70
112
|
qualified_name: &str,
|
|
71
113
|
current_nesting: Option<NameId>,
|
|
72
114
|
current_name: &mut ParentScope,
|
|
73
|
-
names_to_untrack: &mut Vec<NameId>,
|
|
74
115
|
) {
|
|
75
116
|
for part in qualified_name.split("::") {
|
|
76
117
|
if part.is_empty() {
|
|
@@ -90,9 +131,7 @@ fn process_qualified_name(
|
|
|
90
131
|
(*current_name, current_nesting)
|
|
91
132
|
};
|
|
92
133
|
|
|
93
|
-
let
|
|
94
|
-
let name_id = graph.add_name(str_id, parent_scope, nesting_for_part);
|
|
95
|
-
names_to_untrack.push(name_id);
|
|
134
|
+
let name_id = tracker.track_name(part, parent_scope, nesting_for_part);
|
|
96
135
|
*current_name = ParentScope::Some(name_id);
|
|
97
136
|
}
|
|
98
137
|
}
|
|
@@ -107,38 +146,41 @@ mod tests {
|
|
|
107
146
|
fn nesting_is_converted_to_name_id() {
|
|
108
147
|
let mut graph = Graph::new();
|
|
109
148
|
|
|
110
|
-
let
|
|
149
|
+
let tracked_name = name_from_nesting_names(
|
|
111
150
|
&mut graph,
|
|
112
151
|
"Some::CONST",
|
|
113
152
|
vec!["Foo".into(), "Bar::Zip".into(), "Qux".into()],
|
|
114
153
|
)
|
|
115
154
|
.unwrap();
|
|
155
|
+
let name_id = tracked_name.name_id();
|
|
116
156
|
|
|
117
|
-
let const_name = graph.names().get(&name_id).unwrap();
|
|
157
|
+
let const_name = tracked_name.graph().names().get(&name_id).unwrap();
|
|
118
158
|
assert_eq!(StringId::from("CONST"), *const_name.str());
|
|
119
159
|
|
|
120
|
-
let some_name =
|
|
160
|
+
let some_name = tracked_name
|
|
161
|
+
.graph()
|
|
121
162
|
.names()
|
|
122
163
|
.get(&const_name.parent_scope().expect("Parent scope should exist"))
|
|
123
164
|
.unwrap();
|
|
124
165
|
assert_eq!(StringId::from("Some"), *some_name.str());
|
|
125
166
|
assert_eq!(const_name.nesting(), some_name.nesting());
|
|
126
167
|
|
|
127
|
-
let qux_name = graph.names().get(&some_name.nesting().unwrap()).unwrap();
|
|
168
|
+
let qux_name = tracked_name.graph().names().get(&some_name.nesting().unwrap()).unwrap();
|
|
128
169
|
assert_eq!(StringId::from("Qux"), *qux_name.str());
|
|
129
170
|
assert!(qux_name.parent_scope().is_none());
|
|
130
171
|
|
|
131
|
-
let zip_name = graph.names().get(&qux_name.nesting().unwrap()).unwrap();
|
|
172
|
+
let zip_name = tracked_name.graph().names().get(&qux_name.nesting().unwrap()).unwrap();
|
|
132
173
|
assert_eq!(StringId::from("Zip"), *zip_name.str());
|
|
133
174
|
|
|
134
|
-
let bar_name =
|
|
175
|
+
let bar_name = tracked_name
|
|
176
|
+
.graph()
|
|
135
177
|
.names()
|
|
136
178
|
.get(&zip_name.parent_scope().expect("Parent scope should exist"))
|
|
137
179
|
.unwrap();
|
|
138
180
|
assert_eq!(StringId::from("Bar"), *bar_name.str());
|
|
139
181
|
assert_eq!(zip_name.nesting(), bar_name.nesting());
|
|
140
182
|
|
|
141
|
-
let foo_name = graph.names().get(&bar_name.nesting().unwrap()).unwrap();
|
|
183
|
+
let foo_name = tracked_name.graph().names().get(&bar_name.nesting().unwrap()).unwrap();
|
|
142
184
|
assert_eq!(StringId::from("Foo"), *foo_name.str());
|
|
143
185
|
assert!(foo_name.parent_scope().is_none());
|
|
144
186
|
assert!(foo_name.nesting().is_none());
|
|
@@ -148,13 +190,18 @@ mod tests {
|
|
|
148
190
|
fn top_level_reference_is_converted_to_name_id() {
|
|
149
191
|
let mut graph = Graph::new();
|
|
150
192
|
|
|
151
|
-
let
|
|
193
|
+
let tracked_name = name_from_nesting_names(&mut graph, "::CONST", vec!["Foo".into()]).unwrap();
|
|
194
|
+
let name_id = tracked_name.name_id();
|
|
152
195
|
|
|
153
|
-
let const_name = graph.names().get(&name_id).unwrap();
|
|
196
|
+
let const_name = tracked_name.graph().names().get(&name_id).unwrap();
|
|
154
197
|
assert_eq!(StringId::from("CONST"), *const_name.str());
|
|
155
198
|
assert!(const_name.parent_scope().is_top_level());
|
|
156
199
|
|
|
157
|
-
let foo_name =
|
|
200
|
+
let foo_name = tracked_name
|
|
201
|
+
.graph()
|
|
202
|
+
.names()
|
|
203
|
+
.get(&const_name.nesting().unwrap())
|
|
204
|
+
.unwrap();
|
|
158
205
|
assert_eq!(StringId::from("Foo"), *foo_name.str());
|
|
159
206
|
assert!(foo_name.nesting().is_none());
|
|
160
207
|
assert!(foo_name.parent_scope().is_none());
|
|
@@ -164,13 +211,18 @@ mod tests {
|
|
|
164
211
|
fn singleton_class_names_use_attached_parent_scope() {
|
|
165
212
|
let mut graph = Graph::new();
|
|
166
213
|
|
|
167
|
-
let
|
|
214
|
+
let tracked_name = name_from_nesting_names(&mut graph, "CONST", vec!["Foo".into(), "<Foo>".into()]).unwrap();
|
|
215
|
+
let name_id = tracked_name.name_id();
|
|
168
216
|
|
|
169
|
-
let const_name = graph.names().get(&name_id).unwrap();
|
|
217
|
+
let const_name = tracked_name.graph().names().get(&name_id).unwrap();
|
|
170
218
|
assert_eq!(StringId::from("CONST"), *const_name.str());
|
|
171
219
|
|
|
172
220
|
// The nesting should be <Foo> with an Attached parent scope
|
|
173
|
-
let singleton_name =
|
|
221
|
+
let singleton_name = tracked_name
|
|
222
|
+
.graph()
|
|
223
|
+
.names()
|
|
224
|
+
.get(&const_name.nesting().unwrap())
|
|
225
|
+
.unwrap();
|
|
174
226
|
assert_eq!(StringId::from("<Foo>"), *singleton_name.str());
|
|
175
227
|
assert!(
|
|
176
228
|
matches!(singleton_name.parent_scope(), ParentScope::Attached(_)),
|
|
@@ -180,7 +232,7 @@ mod tests {
|
|
|
180
232
|
|
|
181
233
|
// The attached parent should be Foo
|
|
182
234
|
let foo_id = singleton_name.parent_scope().expect("Attached should have an id");
|
|
183
|
-
let foo_name = graph.names().get(&foo_id).unwrap();
|
|
235
|
+
let foo_name = tracked_name.graph().names().get(&foo_id).unwrap();
|
|
184
236
|
assert_eq!(StringId::from("Foo"), *foo_name.str());
|
|
185
237
|
}
|
|
186
238
|
|
|
@@ -188,33 +240,116 @@ mod tests {
|
|
|
188
240
|
fn top_level_nesting_is_converted_to_name_id() {
|
|
189
241
|
let mut graph = Graph::new();
|
|
190
242
|
|
|
191
|
-
let
|
|
243
|
+
let tracked_name = name_from_nesting_names(&mut graph, "CONST", vec!["Foo".into(), "::Bar".into()]).unwrap();
|
|
244
|
+
let name_id = tracked_name.name_id();
|
|
192
245
|
|
|
193
|
-
let const_name = graph.names().get(&name_id).unwrap();
|
|
246
|
+
let const_name = tracked_name.graph().names().get(&name_id).unwrap();
|
|
194
247
|
assert_eq!(StringId::from("CONST"), *const_name.str());
|
|
195
248
|
assert!(const_name.parent_scope().is_none());
|
|
196
249
|
|
|
197
|
-
let bar_name =
|
|
250
|
+
let bar_name = tracked_name
|
|
251
|
+
.graph()
|
|
252
|
+
.names()
|
|
253
|
+
.get(&const_name.nesting().unwrap())
|
|
254
|
+
.unwrap();
|
|
198
255
|
assert_eq!(StringId::from("Bar"), *bar_name.str());
|
|
199
256
|
assert!(bar_name.parent_scope().is_top_level());
|
|
200
257
|
|
|
201
|
-
let foo_name = graph.names().get(&bar_name.nesting().unwrap()).unwrap();
|
|
258
|
+
let foo_name = tracked_name.graph().names().get(&bar_name.nesting().unwrap()).unwrap();
|
|
202
259
|
assert_eq!(StringId::from("Foo"), *foo_name.str());
|
|
203
260
|
assert!(foo_name.parent_scope().is_none());
|
|
204
261
|
assert!(foo_name.nesting().is_none());
|
|
205
262
|
}
|
|
206
263
|
|
|
207
264
|
#[test]
|
|
208
|
-
fn
|
|
265
|
+
fn invalid_names_restore_name_and_string_counts() {
|
|
266
|
+
let mut graph = Graph::new();
|
|
267
|
+
let name_count = graph.names().len();
|
|
268
|
+
let string_count = graph.strings().len();
|
|
269
|
+
|
|
270
|
+
assert!(name_from_nesting_names(&mut graph, "", vec!["Foo".into()]).is_none());
|
|
271
|
+
assert_eq!(name_count, graph.names().len());
|
|
272
|
+
assert_eq!(string_count, graph.strings().len());
|
|
273
|
+
|
|
274
|
+
assert!(name_from_nesting_names(&mut graph, "Foo::", vec!["Bar".into()]).is_none());
|
|
275
|
+
assert_eq!(name_count, graph.names().len());
|
|
276
|
+
assert_eq!(string_count, graph.strings().len());
|
|
277
|
+
|
|
278
|
+
assert!(name_from_lexical_nesting(&mut graph, "Foo::", None).is_none());
|
|
279
|
+
assert_eq!(name_count, graph.names().len());
|
|
280
|
+
assert_eq!(string_count, graph.strings().len());
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
#[test]
|
|
284
|
+
fn invalid_name_restores_existing_name_reference_counts() {
|
|
285
|
+
let mut graph = Graph::new();
|
|
286
|
+
let string_id = graph.intern_string("Foo".to_owned());
|
|
287
|
+
let name_id = graph.add_name(string_id, ParentScope::None, None);
|
|
288
|
+
let name_ref_count = graph.names().get(&name_id).unwrap().ref_count();
|
|
289
|
+
let string_ref_count = graph.strings().get(&string_id).unwrap().ref_count();
|
|
290
|
+
|
|
291
|
+
assert!(name_from_nesting_names(&mut graph, "", vec!["Foo".into()]).is_none());
|
|
292
|
+
|
|
293
|
+
assert_eq!(name_ref_count, graph.names().get(&name_id).unwrap().ref_count());
|
|
294
|
+
assert_eq!(string_ref_count, graph.strings().get(&string_id).unwrap().ref_count());
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
#[test]
|
|
298
|
+
fn tracker_preserves_duplicate_name_ids() {
|
|
209
299
|
let mut graph = Graph::new();
|
|
210
300
|
let name_count = graph.names().len();
|
|
211
301
|
let string_count = graph.strings().len();
|
|
212
302
|
|
|
213
|
-
|
|
303
|
+
{
|
|
304
|
+
let mut tracker = NameTracker::new(&mut graph);
|
|
305
|
+
let first_id = tracker.track_name("Foo", ParentScope::None, None);
|
|
306
|
+
let second_id = tracker.track_name("Foo", ParentScope::None, None);
|
|
307
|
+
|
|
308
|
+
assert_eq!(first_id, second_id);
|
|
309
|
+
assert_eq!(2, tracker.graph.names().get(&first_id).unwrap().ref_count());
|
|
310
|
+
}
|
|
311
|
+
|
|
214
312
|
assert_eq!(name_count, graph.names().len());
|
|
215
313
|
assert_eq!(string_count, graph.strings().len());
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
#[test]
|
|
317
|
+
fn tracked_name_is_untracked_when_scope_ends() {
|
|
318
|
+
let mut graph = Graph::new();
|
|
319
|
+
let name_count = graph.names().len();
|
|
320
|
+
let string_count = graph.strings().len();
|
|
321
|
+
|
|
322
|
+
{
|
|
323
|
+
let tracked_name = name_from_nesting_names(&mut graph, "Bar::CONST", vec!["Foo".into()]).unwrap();
|
|
324
|
+
let name_id = tracked_name.name_id();
|
|
325
|
+
let const_name = tracked_name.graph().names().get(&name_id).unwrap();
|
|
326
|
+
|
|
327
|
+
assert_eq!(
|
|
328
|
+
"CONST",
|
|
329
|
+
tracked_name.graph().strings().get(const_name.str()).unwrap().as_str()
|
|
330
|
+
);
|
|
331
|
+
assert_eq!(name_count + 3, tracked_name.graph().names().len());
|
|
332
|
+
assert_eq!(string_count + 3, tracked_name.graph().strings().len());
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
assert_eq!(name_count, graph.names().len());
|
|
336
|
+
assert_eq!(string_count, graph.strings().len());
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
#[test]
|
|
340
|
+
fn tracked_name_is_untracked_during_unwind() {
|
|
341
|
+
let mut graph = Graph::new();
|
|
342
|
+
let name_count = graph.names().len();
|
|
343
|
+
let string_count = graph.strings().len();
|
|
344
|
+
|
|
345
|
+
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
|
346
|
+
let tracked_name = name_from_nesting_names(&mut graph, "Bar::CONST", vec!["Foo".into()]).unwrap();
|
|
347
|
+
|
|
348
|
+
assert_eq!(name_count + 3, tracked_name.graph().names().len());
|
|
349
|
+
panic!("unwind tracked name");
|
|
350
|
+
}));
|
|
216
351
|
|
|
217
|
-
assert!(
|
|
352
|
+
assert!(result.is_err());
|
|
218
353
|
assert_eq!(name_count, graph.names().len());
|
|
219
354
|
assert_eq!(string_count, graph.strings().len());
|
|
220
355
|
}
|