rubydex 0.1.0.beta11 → 0.1.0.beta13

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +23 -23
  3. data/README.md +125 -125
  4. data/THIRD_PARTY_LICENSES.html +2018 -945
  5. data/exe/rdx +47 -47
  6. data/ext/rubydex/declaration.c +453 -388
  7. data/ext/rubydex/declaration.h +23 -23
  8. data/ext/rubydex/definition.c +284 -197
  9. data/ext/rubydex/definition.h +28 -28
  10. data/ext/rubydex/diagnostic.c +6 -6
  11. data/ext/rubydex/diagnostic.h +11 -11
  12. data/ext/rubydex/document.c +97 -98
  13. data/ext/rubydex/document.h +10 -10
  14. data/ext/rubydex/extconf.rb +146 -127
  15. data/ext/rubydex/graph.c +701 -512
  16. data/ext/rubydex/graph.h +10 -10
  17. data/ext/rubydex/handle.h +44 -44
  18. data/ext/rubydex/location.c +22 -22
  19. data/ext/rubydex/location.h +15 -15
  20. data/ext/rubydex/reference.c +123 -104
  21. data/ext/rubydex/reference.h +15 -16
  22. data/ext/rubydex/rubydex.c +22 -22
  23. data/ext/rubydex/utils.c +108 -86
  24. data/ext/rubydex/utils.h +34 -28
  25. data/lib/rubydex/comment.rb +17 -17
  26. data/lib/rubydex/declaration.rb +11 -0
  27. data/lib/rubydex/diagnostic.rb +21 -21
  28. data/lib/rubydex/failures.rb +15 -15
  29. data/lib/rubydex/graph.rb +98 -92
  30. data/lib/rubydex/keyword.rb +17 -0
  31. data/lib/rubydex/keyword_parameter.rb +13 -0
  32. data/lib/rubydex/location.rb +90 -90
  33. data/lib/rubydex/mixin.rb +22 -0
  34. data/lib/rubydex/version.rb +5 -5
  35. data/lib/rubydex.rb +24 -20
  36. data/rbi/rubydex.rbi +425 -310
  37. data/rust/Cargo.lock +1851 -1851
  38. data/rust/Cargo.toml +29 -29
  39. data/rust/about.toml +10 -10
  40. data/rust/{about.hbs → about_templates/about.hbs} +81 -78
  41. data/rust/about_templates/mingw_licenses.hbs +1071 -0
  42. data/rust/rubydex/Cargo.toml +42 -42
  43. data/rust/rubydex/src/compile_assertions.rs +13 -13
  44. data/rust/rubydex/src/diagnostic.rs +110 -109
  45. data/rust/rubydex/src/errors.rs +28 -28
  46. data/rust/rubydex/src/indexing/local_graph.rs +224 -224
  47. data/rust/rubydex/src/indexing/rbs_indexer.rs +1551 -1554
  48. data/rust/rubydex/src/indexing/ruby_indexer.rs +2329 -6753
  49. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +4962 -0
  50. data/rust/rubydex/src/indexing.rs +210 -210
  51. data/rust/rubydex/src/integrity.rs +279 -278
  52. data/rust/rubydex/src/job_queue.rs +199 -205
  53. data/rust/rubydex/src/lib.rs +17 -17
  54. data/rust/rubydex/src/listing.rs +371 -272
  55. data/rust/rubydex/src/main.rs +160 -160
  56. data/rust/rubydex/src/model/built_in.rs +83 -0
  57. data/rust/rubydex/src/model/comment.rs +24 -24
  58. data/rust/rubydex/src/model/declaration.rs +679 -588
  59. data/rust/rubydex/src/model/definitions.rs +1682 -1602
  60. data/rust/rubydex/src/model/document.rs +222 -252
  61. data/rust/rubydex/src/model/encoding.rs +22 -22
  62. data/rust/rubydex/src/model/graph.rs +3782 -3556
  63. data/rust/rubydex/src/model/id.rs +110 -110
  64. data/rust/rubydex/src/model/identity_maps.rs +58 -58
  65. data/rust/rubydex/src/model/ids.rs +60 -38
  66. data/rust/rubydex/src/model/keywords.rs +256 -256
  67. data/rust/rubydex/src/model/name.rs +298 -298
  68. data/rust/rubydex/src/model/references.rs +111 -111
  69. data/rust/rubydex/src/model/string_ref.rs +50 -50
  70. data/rust/rubydex/src/model/visibility.rs +41 -41
  71. data/rust/rubydex/src/model.rs +15 -14
  72. data/rust/rubydex/src/offset.rs +147 -147
  73. data/rust/rubydex/src/position.rs +6 -6
  74. data/rust/rubydex/src/query.rs +1841 -1700
  75. data/rust/rubydex/src/resolution.rs +1852 -5895
  76. data/rust/rubydex/src/resolution_tests.rs +4701 -0
  77. data/rust/rubydex/src/stats/memory.rs +71 -71
  78. data/rust/rubydex/src/stats/orphan_report.rs +264 -263
  79. data/rust/rubydex/src/stats/timer.rs +127 -127
  80. data/rust/rubydex/src/stats.rs +11 -11
  81. data/rust/rubydex/src/test_utils/context.rs +226 -226
  82. data/rust/rubydex/src/test_utils/graph_test.rs +730 -679
  83. data/rust/rubydex/src/test_utils/local_graph_test.rs +602 -602
  84. data/rust/rubydex/src/test_utils.rs +52 -52
  85. data/rust/rubydex/src/visualization/dot.rs +192 -176
  86. data/rust/rubydex/src/visualization.rs +6 -6
  87. data/rust/rubydex/tests/cli.rs +185 -167
  88. data/rust/rubydex-mcp/Cargo.toml +28 -28
  89. data/rust/rubydex-mcp/src/main.rs +48 -48
  90. data/rust/rubydex-mcp/src/server.rs +1145 -1145
  91. data/rust/rubydex-mcp/src/tools.rs +49 -49
  92. data/rust/rubydex-mcp/tests/mcp.rs +302 -302
  93. data/rust/rubydex-sys/Cargo.toml +20 -20
  94. data/rust/rubydex-sys/build.rs +14 -14
  95. data/rust/rubydex-sys/cbindgen.toml +12 -12
  96. data/rust/rubydex-sys/src/declaration_api.rs +485 -469
  97. data/rust/rubydex-sys/src/definition_api.rs +443 -352
  98. data/rust/rubydex-sys/src/diagnostic_api.rs +99 -99
  99. data/rust/rubydex-sys/src/document_api.rs +85 -54
  100. data/rust/rubydex-sys/src/graph_api.rs +1017 -700
  101. data/rust/rubydex-sys/src/lib.rs +79 -9
  102. data/rust/rubydex-sys/src/location_api.rs +79 -79
  103. data/rust/rubydex-sys/src/name_api.rs +187 -135
  104. data/rust/rubydex-sys/src/reference_api.rs +267 -195
  105. data/rust/rubydex-sys/src/utils.rs +70 -70
  106. data/rust/rustfmt.toml +2 -2
  107. metadata +16 -9
  108. data/lib/rubydex/librubydex_sys.so +0 -0
@@ -1,588 +1,679 @@
1
- use crate::assert_mem_size;
2
- use crate::diagnostic::Diagnostic;
3
- use crate::model::{
4
- identity_maps::{IdentityHashMap, IdentityHashSet},
5
- ids::{DeclarationId, DefinitionId, NameId, ReferenceId, StringId},
6
- };
7
-
8
- /// A single ancestor in the linearized ancestor chain
9
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
10
- pub enum Ancestor {
11
- /// A complete ancestor that we have fully linearized
12
- Complete(DeclarationId),
13
- /// A partial ancestor that is missing linearization
14
- Partial(NameId),
15
- }
16
-
17
- /// The ancestor chain and its current state
18
- #[derive(Debug, Clone)]
19
- pub enum Ancestors {
20
- /// A complete linearization of ancestors with all parts resolved
21
- Complete(Vec<Ancestor>),
22
- /// A cyclic linearization of ancestors (e.g.: a module that includes itself)
23
- Cyclic(Vec<Ancestor>),
24
- /// A partial linearization of ancestors with some parts unresolved. This chain state always triggers retries
25
- Partial(Vec<Ancestor>),
26
- }
27
- assert_mem_size!(Ancestors, 32);
28
-
29
- impl Ancestors {
30
- pub fn iter(&self) -> std::slice::Iter<'_, Ancestor> {
31
- match self {
32
- Ancestors::Complete(ancestors) | Ancestors::Partial(ancestors) | Ancestors::Cyclic(ancestors) => {
33
- ancestors.iter()
34
- }
35
- }
36
- }
37
-
38
- #[must_use]
39
- pub fn to_partial(self) -> Self {
40
- match self {
41
- Ancestors::Complete(ancestors) | Ancestors::Cyclic(ancestors) | Ancestors::Partial(ancestors) => {
42
- Ancestors::Partial(ancestors)
43
- }
44
- }
45
- }
46
- }
47
-
48
- impl<'a> IntoIterator for &'a Ancestors {
49
- type Item = &'a Ancestor;
50
- type IntoIter = std::slice::Iter<'a, Ancestor>;
51
-
52
- fn into_iter(self) -> Self::IntoIter {
53
- self.iter()
54
- }
55
- }
56
-
57
- macro_rules! all_declarations {
58
- ($value:expr, $var:ident => $expr:expr) => {
59
- match $value {
60
- Declaration::Namespace(Namespace::Class($var)) => $expr,
61
- Declaration::Namespace(Namespace::Module($var)) => $expr,
62
- Declaration::Namespace(Namespace::SingletonClass($var)) => $expr,
63
- Declaration::Namespace(Namespace::Todo($var)) => $expr,
64
- Declaration::Constant($var) => $expr,
65
- Declaration::ConstantAlias($var) => $expr,
66
- Declaration::Method($var) => $expr,
67
- Declaration::GlobalVariable($var) => $expr,
68
- Declaration::InstanceVariable($var) => $expr,
69
- Declaration::ClassVariable($var) => $expr,
70
- }
71
- };
72
- }
73
-
74
- macro_rules! all_namespaces {
75
- ($value:expr, $var:ident => $expr:expr) => {
76
- match $value {
77
- Namespace::Class($var) => $expr,
78
- Namespace::Module($var) => $expr,
79
- Namespace::SingletonClass($var) => $expr,
80
- Namespace::Todo($var) => $expr,
81
- }
82
- };
83
- }
84
-
85
- /// Macro to generate a new struct for namespace-like declarations such as classes and modules
86
- macro_rules! namespace_declaration {
87
- ($variant:ident, $name:ident) => {
88
- #[derive(Debug)]
89
- pub struct $name {
90
- /// The fully qualified name of this declaration
91
- name: String,
92
- /// The list of definition IDs that compose this declaration
93
- definition_ids: Vec<DefinitionId>,
94
- /// The set of references that are made to this declaration
95
- references: IdentityHashSet<ReferenceId>,
96
- /// The ID of the owner of this declaration. For singleton classes, this is the ID of the attached object
97
- owner_id: DeclarationId,
98
- /// The entities that are owned by this declaration. For example, constants and methods that are defined inside of
99
- /// the namespace. Note that this is a hashmap of unqualified name IDs to declaration IDs. That assists the
100
- /// traversal of the graph when trying to resolve constant references or trying to discover which methods exist in a
101
- /// class
102
- members: IdentityHashMap<StringId, DeclarationId>,
103
- /// The linearized ancestor chain for this declaration. These are the other declarations that this
104
- /// declaration inherits from
105
- ancestors: Ancestors,
106
- /// The set of declarations that inherit from this declaration
107
- descendants: IdentityHashSet<DeclarationId>,
108
- /// The singleton class associated with this declaration
109
- singleton_class_id: Option<DeclarationId>,
110
- /// Diagnostics associated with this declaration
111
- diagnostics: Vec<Diagnostic>,
112
- }
113
-
114
- impl $name {
115
- #[must_use]
116
- pub fn new(name: String, owner_id: DeclarationId) -> Self {
117
- Self {
118
- name,
119
- definition_ids: Vec::new(),
120
- members: IdentityHashMap::default(),
121
- references: IdentityHashSet::default(),
122
- owner_id,
123
- ancestors: Ancestors::Partial(Vec::new()),
124
- descendants: IdentityHashSet::default(),
125
- singleton_class_id: None,
126
- diagnostics: Vec::new(),
127
- }
128
- }
129
-
130
- pub fn extend(&mut self, mut other: Declaration) {
131
- self.definition_ids.extend(other.definitions());
132
- self.references.extend(other.references());
133
- self.diagnostics.extend(other.take_diagnostics());
134
-
135
- if let Declaration::Namespace(namespace) = other {
136
- self.members.extend(namespace.members());
137
- }
138
- }
139
-
140
- pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
141
- self.singleton_class_id = Some(declaration_id);
142
- }
143
-
144
- pub fn singleton_class_id(&self) -> Option<&DeclarationId> {
145
- self.singleton_class_id.as_ref()
146
- }
147
-
148
- #[must_use]
149
- pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
150
- &self.members
151
- }
152
-
153
- pub fn add_member(&mut self, string_id: StringId, declaration_id: DeclarationId) {
154
- self.members.insert(string_id, declaration_id);
155
- }
156
-
157
- pub fn remove_member(&mut self, string_id: &StringId) -> Option<DeclarationId> {
158
- self.members.remove(string_id)
159
- }
160
-
161
- #[must_use]
162
- pub fn member(&self, string_id: &StringId) -> Option<&DeclarationId> {
163
- self.members.get(string_id)
164
- }
165
-
166
- pub fn set_ancestors(&mut self, ancestors: Ancestors) {
167
- self.ancestors = ancestors;
168
- }
169
-
170
- pub fn ancestors(&self) -> &Ancestors {
171
- &self.ancestors
172
- }
173
-
174
- pub fn ancestors_mut(&mut self) -> &mut Ancestors {
175
- &mut self.ancestors
176
- }
177
-
178
- #[must_use]
179
- pub fn clone_ancestors(&self) -> Ancestors {
180
- self.ancestors.clone()
181
- }
182
-
183
- #[must_use]
184
- pub fn has_complete_ancestors(&self) -> bool {
185
- matches!(&self.ancestors, Ancestors::Complete(_) | Ancestors::Cyclic(_))
186
- }
187
-
188
- pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
189
- self.descendants.insert(descendant_id);
190
- }
191
-
192
- fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
193
- self.descendants.remove(descendant_id);
194
- }
195
-
196
- pub fn clear_descendants(&mut self) {
197
- self.descendants.clear();
198
- }
199
-
200
- pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
201
- &self.descendants
202
- }
203
- }
204
- };
205
- }
206
-
207
- /// Macro to generate a new struct for simple declarations like variables and methods
208
- macro_rules! simple_declaration {
209
- ($name:ident) => {
210
- #[derive(Debug)]
211
- pub struct $name {
212
- /// The fully qualified name of this declaration
213
- name: String,
214
- /// The list of definition IDs that compose this declaration
215
- definition_ids: Vec<DefinitionId>,
216
- /// The set of references that are made to this declaration
217
- references: IdentityHashSet<ReferenceId>,
218
- /// The ID of the owner of this declaration
219
- owner_id: DeclarationId,
220
- /// Diagnostics associated with this declaration
221
- diagnostics: Vec<Diagnostic>,
222
- }
223
-
224
- impl $name {
225
- #[must_use]
226
- pub fn new(name: String, owner_id: DeclarationId) -> Self {
227
- Self {
228
- name,
229
- definition_ids: Vec::new(),
230
- references: IdentityHashSet::default(),
231
- owner_id,
232
- diagnostics: Vec::new(),
233
- }
234
- }
235
-
236
- pub fn extend(&mut self, mut other: Declaration) {
237
- self.definition_ids.extend(other.definitions());
238
- self.references.extend(other.references());
239
- self.diagnostics.extend(other.take_diagnostics());
240
- }
241
- }
242
- };
243
- }
244
-
245
- /// A `Declaration` represents the global concept of an entity in Ruby. For example, the class `Foo` may be defined 3
246
- /// times in different files and the `Foo` declaration is the combination of all of those definitions that contribute to
247
- /// the same fully qualified name
248
- #[derive(Debug)]
249
- pub enum Declaration {
250
- Namespace(Namespace),
251
- Constant(Box<ConstantDeclaration>),
252
- ConstantAlias(Box<ConstantAliasDeclaration>),
253
- Method(Box<MethodDeclaration>),
254
- GlobalVariable(Box<GlobalVariableDeclaration>),
255
- InstanceVariable(Box<InstanceVariableDeclaration>),
256
- ClassVariable(Box<ClassVariableDeclaration>),
257
- }
258
- assert_mem_size!(Declaration, 16);
259
-
260
- impl Declaration {
261
- #[must_use]
262
- pub fn name(&self) -> &str {
263
- all_declarations!(self, it => &it.name)
264
- }
265
-
266
- #[must_use]
267
- pub fn kind(&self) -> &'static str {
268
- match self {
269
- Declaration::Namespace(namespace) => namespace.kind(),
270
- Declaration::Constant(_) => "Constant",
271
- Declaration::ConstantAlias(_) => "ConstantAlias",
272
- Declaration::Method(_) => "Method",
273
- Declaration::GlobalVariable(_) => "GlobalVariable",
274
- Declaration::InstanceVariable(_) => "InstanceVariable",
275
- Declaration::ClassVariable(_) => "ClassVariable",
276
- }
277
- }
278
-
279
- #[must_use]
280
- pub fn as_namespace(&self) -> Option<&Namespace> {
281
- match self {
282
- Declaration::Namespace(namespace) => Some(namespace),
283
- _ => None,
284
- }
285
- }
286
-
287
- #[must_use]
288
- pub fn as_namespace_mut(&mut self) -> Option<&mut Namespace> {
289
- match self {
290
- Declaration::Namespace(namespace) => Some(namespace),
291
- _ => None,
292
- }
293
- }
294
-
295
- #[must_use]
296
- pub fn references(&self) -> &IdentityHashSet<ReferenceId> {
297
- all_declarations!(self, it => &it.references)
298
- }
299
-
300
- #[must_use]
301
- pub fn definitions(&self) -> &[DefinitionId] {
302
- all_declarations!(self, it => &it.definition_ids)
303
- }
304
-
305
- #[must_use]
306
- pub fn has_no_definitions(&self) -> bool {
307
- all_declarations!(self, it => it.definition_ids.is_empty())
308
- }
309
-
310
- pub fn add_definition(&mut self, definition_id: DefinitionId) {
311
- all_declarations!(self, it => {
312
- debug_assert!(
313
- !it.definition_ids.contains(&definition_id),
314
- "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs"
315
- );
316
-
317
- it.definition_ids.push(definition_id);
318
- });
319
- }
320
-
321
- pub fn add_reference(&mut self, id: ReferenceId) {
322
- all_declarations!(self, it => {
323
- it.references.insert(id);
324
- });
325
- }
326
-
327
- pub fn remove_reference(&mut self, reference_id: &ReferenceId) {
328
- all_declarations!(self, it => {
329
- it.references.remove(reference_id);
330
- });
331
- }
332
-
333
- // Deletes a definition from this declaration
334
- pub fn remove_definition(&mut self, definition_id: &DefinitionId) -> bool {
335
- all_declarations!(self, it => {
336
- if let Some(pos) = it.definition_ids.iter().position(|id| id == definition_id) {
337
- it.definition_ids.swap_remove(pos);
338
- it.definition_ids.shrink_to_fit();
339
- true
340
- } else {
341
- false
342
- }
343
- })
344
- }
345
-
346
- #[must_use]
347
- pub fn owner_id(&self) -> &DeclarationId {
348
- all_declarations!(self, it => &it.owner_id)
349
- }
350
-
351
- // Splits the fully qualified name either in the last `::` or the `#` to return the simple name of this declaration
352
- #[must_use]
353
- pub fn unqualified_name(&self) -> String {
354
- all_declarations!(self, it => {
355
- let after_colons = it.name.rsplit("::").next().unwrap_or(&it.name);
356
- after_colons.rsplit('#').next().unwrap_or(after_colons).to_string()
357
- })
358
- }
359
-
360
- #[must_use]
361
- pub fn diagnostics(&self) -> &[Diagnostic] {
362
- all_declarations!(self, it => &it.diagnostics)
363
- }
364
-
365
- pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
366
- all_declarations!(self, it => std::mem::take(&mut it.diagnostics))
367
- }
368
-
369
- pub fn add_diagnostic(&mut self, diagnostic: Diagnostic) {
370
- all_declarations!(self, it => it.diagnostics.push(diagnostic));
371
- }
372
-
373
- pub fn clear_diagnostics(&mut self) {
374
- all_declarations!(self, it => it.diagnostics.clear());
375
- }
376
- }
377
-
378
- #[derive(Debug)]
379
- pub enum Namespace {
380
- Class(Box<ClassDeclaration>),
381
- SingletonClass(Box<SingletonClassDeclaration>),
382
- Module(Box<ModuleDeclaration>),
383
- Todo(Box<TodoDeclaration>),
384
- }
385
- assert_mem_size!(Namespace, 16);
386
-
387
- impl Namespace {
388
- #[must_use]
389
- pub fn kind(&self) -> &'static str {
390
- match self {
391
- Namespace::Class(_) => "Class",
392
- Namespace::SingletonClass(_) => "SingletonClass",
393
- Namespace::Module(_) => "Module",
394
- Namespace::Todo(_) => "<TODO>",
395
- }
396
- }
397
-
398
- #[must_use]
399
- pub fn references(&self) -> &IdentityHashSet<ReferenceId> {
400
- all_namespaces!(self, it => &it.references)
401
- }
402
-
403
- #[must_use]
404
- pub fn definitions(&self) -> &[DefinitionId] {
405
- all_namespaces!(self, it => &it.definition_ids)
406
- }
407
-
408
- #[must_use]
409
- pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
410
- all_namespaces!(self, it => &it.members)
411
- }
412
-
413
- #[must_use]
414
- pub fn diagnostics(&self) -> &[Diagnostic] {
415
- all_namespaces!(self, it => &it.diagnostics)
416
- }
417
-
418
- pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
419
- all_namespaces!(self, it => std::mem::take(&mut it.diagnostics))
420
- }
421
-
422
- pub fn extend(&mut self, other: Declaration) {
423
- all_namespaces!(self, it => it.extend(other));
424
- }
425
-
426
- #[must_use]
427
- pub fn ancestors(&self) -> &Ancestors {
428
- all_namespaces!(self, it => it.ancestors())
429
- }
430
-
431
- #[must_use]
432
- pub fn clone_ancestors(&self) -> Ancestors {
433
- all_namespaces!(self, it => it.clone_ancestors())
434
- }
435
-
436
- pub fn set_ancestors(&mut self, ancestors: Ancestors) {
437
- all_namespaces!(self, it => it.set_ancestors(ancestors));
438
- }
439
-
440
- #[must_use]
441
- pub fn has_complete_ancestors(&self) -> bool {
442
- all_namespaces!(self, it => it.has_complete_ancestors())
443
- }
444
-
445
- #[must_use]
446
- pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
447
- all_namespaces!(self, it => it.descendants())
448
- }
449
-
450
- pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
451
- all_namespaces!(self, it => it.add_descendant(descendant_id));
452
- }
453
-
454
- pub fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
455
- all_namespaces!(self, it => it.remove_descendant(descendant_id));
456
- }
457
-
458
- pub fn for_each_ancestor<F>(&self, mut f: F)
459
- where
460
- F: FnMut(&Ancestor),
461
- {
462
- all_namespaces!(self, it => it.ancestors().iter().for_each(&mut f));
463
- }
464
-
465
- pub fn for_each_descendant<F>(&self, mut f: F)
466
- where
467
- F: FnMut(&DeclarationId),
468
- {
469
- all_namespaces!(self, it => it.descendants().iter().for_each(&mut f));
470
- }
471
-
472
- pub fn clear_ancestors(&mut self) {
473
- all_namespaces!(self, it => it.set_ancestors(Ancestors::Partial(vec![])));
474
- }
475
-
476
- pub fn clear_descendants(&mut self) {
477
- all_namespaces!(self, it => it.clear_descendants());
478
- }
479
-
480
- #[must_use]
481
- pub fn member(&self, str_id: &StringId) -> Option<&DeclarationId> {
482
- all_namespaces!(self, it => it.member(str_id))
483
- }
484
-
485
- pub fn remove_member(&mut self, str_id: &StringId) -> Option<DeclarationId> {
486
- all_namespaces!(self, it => it.remove_member(str_id))
487
- }
488
-
489
- #[must_use]
490
- pub fn singleton_class(&self) -> Option<&DeclarationId> {
491
- all_namespaces!(self, it => it.singleton_class_id())
492
- }
493
-
494
- pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
495
- all_namespaces!(self, it => it.set_singleton_class_id(declaration_id));
496
- }
497
-
498
- #[must_use]
499
- pub fn owner_id(&self) -> &DeclarationId {
500
- all_namespaces!(self, it => &it.owner_id)
501
- }
502
-
503
- #[must_use]
504
- pub fn name(&self) -> &str {
505
- all_namespaces!(self, it => &it.name)
506
- }
507
- }
508
-
509
- namespace_declaration!(Class, ClassDeclaration);
510
- assert_mem_size!(ClassDeclaration, 216);
511
- namespace_declaration!(Module, ModuleDeclaration);
512
- assert_mem_size!(ModuleDeclaration, 216);
513
- namespace_declaration!(SingletonClass, SingletonClassDeclaration);
514
- assert_mem_size!(SingletonClassDeclaration, 216);
515
- namespace_declaration!(Todo, TodoDeclaration);
516
- assert_mem_size!(TodoDeclaration, 216);
517
- simple_declaration!(ConstantDeclaration);
518
- assert_mem_size!(ConstantDeclaration, 112);
519
- simple_declaration!(MethodDeclaration);
520
- assert_mem_size!(MethodDeclaration, 112);
521
- simple_declaration!(GlobalVariableDeclaration);
522
- assert_mem_size!(GlobalVariableDeclaration, 112);
523
- simple_declaration!(InstanceVariableDeclaration);
524
- assert_mem_size!(InstanceVariableDeclaration, 112);
525
- simple_declaration!(ClassVariableDeclaration);
526
- assert_mem_size!(ClassVariableDeclaration, 112);
527
- simple_declaration!(ConstantAliasDeclaration);
528
- assert_mem_size!(ConstantAliasDeclaration, 112);
529
-
530
- #[cfg(test)]
531
- mod tests {
532
- use super::*;
533
-
534
- #[test]
535
- #[should_panic(expected = "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs")]
536
- fn inserting_duplicate_definitions() {
537
- let mut decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
538
- "MyDecl".to_string(),
539
- DeclarationId::from("Object"),
540
- ))));
541
- let def_id = DefinitionId::new(123);
542
-
543
- // The second call will panic because we're adding the same exact ID twice
544
- decl.add_definition(def_id);
545
- decl.add_definition(def_id);
546
- }
547
-
548
- #[test]
549
- fn adding_and_removing_members() {
550
- let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
551
- "Foo".to_string(),
552
- DeclarationId::from("Object"),
553
- ))));
554
- let member_name_id = StringId::from("Bar");
555
- let member_decl_id = DeclarationId::from("Foo::Bar");
556
-
557
- let Declaration::Namespace(Namespace::Class(mut class)) = decl else {
558
- panic!("Expected a class declaration");
559
- };
560
- class.add_member(member_name_id, member_decl_id);
561
- assert_eq!(class.members.len(), 1);
562
-
563
- let removed = class.remove_member(&member_name_id);
564
- assert_eq!(removed, Some(member_decl_id));
565
- assert_eq!(class.members.len(), 0);
566
- }
567
-
568
- #[test]
569
- fn unqualified_name() {
570
- let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
571
- "Foo".to_string(),
572
- DeclarationId::from("Foo"),
573
- ))));
574
- assert_eq!(decl.unqualified_name(), "Foo");
575
-
576
- let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
577
- "Foo::Bar".to_string(),
578
- DeclarationId::from("Foo"),
579
- ))));
580
- assert_eq!(decl.unqualified_name(), "Bar");
581
-
582
- let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
583
- "Foo::Bar#baz".to_string(),
584
- DeclarationId::from("Foo::Bar"),
585
- ))));
586
- assert_eq!(decl.unqualified_name(), "baz");
587
- }
588
- }
1
+ use crate::assert_mem_size;
2
+ use crate::diagnostic::Diagnostic;
3
+ use crate::model::ids::{
4
+ ClassVariableReferenceId, GlobalVariableReferenceId, InstanceVariableReferenceId, MethodReferenceId,
5
+ };
6
+ use crate::model::{
7
+ identity_maps::{IdentityHashMap, IdentityHashSet},
8
+ ids::{ConstantReferenceId, DeclarationId, DefinitionId, NameId, StringId},
9
+ };
10
+
11
+ /// A single ancestor in the linearized ancestor chain
12
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
13
+ pub enum Ancestor {
14
+ /// A complete ancestor that we have fully linearized
15
+ Complete(DeclarationId),
16
+ /// A partial ancestor that is missing linearization
17
+ Partial(NameId),
18
+ }
19
+
20
+ /// The ancestor chain and its current state
21
+ #[derive(Debug, Clone)]
22
+ pub enum Ancestors {
23
+ /// A complete linearization of ancestors with all parts resolved
24
+ Complete(Vec<Ancestor>),
25
+ /// A cyclic linearization of ancestors (e.g.: a module that includes itself)
26
+ Cyclic(Vec<Ancestor>),
27
+ /// A partial linearization of ancestors with some parts unresolved. This chain state always triggers retries
28
+ Partial(Vec<Ancestor>),
29
+ }
30
+ assert_mem_size!(Ancestors, 32);
31
+
32
+ impl Ancestors {
33
+ pub fn iter(&self) -> std::slice::Iter<'_, Ancestor> {
34
+ match self {
35
+ Ancestors::Complete(ancestors) | Ancestors::Partial(ancestors) | Ancestors::Cyclic(ancestors) => {
36
+ ancestors.iter()
37
+ }
38
+ }
39
+ }
40
+
41
+ #[must_use]
42
+ pub fn to_partial(self) -> Self {
43
+ match self {
44
+ Ancestors::Complete(ancestors) | Ancestors::Cyclic(ancestors) | Ancestors::Partial(ancestors) => {
45
+ Ancestors::Partial(ancestors)
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ impl<'a> IntoIterator for &'a Ancestors {
52
+ type Item = &'a Ancestor;
53
+ type IntoIter = std::slice::Iter<'a, Ancestor>;
54
+
55
+ fn into_iter(self) -> Self::IntoIter {
56
+ self.iter()
57
+ }
58
+ }
59
+
60
+ macro_rules! all_declarations {
61
+ ($value:expr, $var:ident => $expr:expr) => {
62
+ match $value {
63
+ Declaration::Namespace(Namespace::Class($var)) => $expr,
64
+ Declaration::Namespace(Namespace::Module($var)) => $expr,
65
+ Declaration::Namespace(Namespace::SingletonClass($var)) => $expr,
66
+ Declaration::Namespace(Namespace::Todo($var)) => $expr,
67
+ Declaration::Constant($var) => $expr,
68
+ Declaration::ConstantAlias($var) => $expr,
69
+ Declaration::Method($var) => $expr,
70
+ Declaration::GlobalVariable($var) => $expr,
71
+ Declaration::InstanceVariable($var) => $expr,
72
+ Declaration::ClassVariable($var) => $expr,
73
+ }
74
+ };
75
+ }
76
+
77
+ macro_rules! all_namespaces {
78
+ ($value:expr, $var:ident => $expr:expr) => {
79
+ match $value {
80
+ Namespace::Class($var) => $expr,
81
+ Namespace::Module($var) => $expr,
82
+ Namespace::SingletonClass($var) => $expr,
83
+ Namespace::Todo($var) => $expr,
84
+ }
85
+ };
86
+ }
87
+
88
+ /// Macro to generate a new struct for namespace-like declarations such as classes and modules
89
+ macro_rules! namespace_declaration {
90
+ ($variant:ident, $name:ident) => {
91
+ #[derive(Debug)]
92
+ pub struct $name {
93
+ /// The fully qualified name of this declaration
94
+ name: String,
95
+ /// The list of definition IDs that compose this declaration
96
+ definition_ids: Vec<DefinitionId>,
97
+ /// The set of references that are made to this declaration
98
+ references: IdentityHashSet<ConstantReferenceId>,
99
+ /// The ID of the owner of this declaration. For singleton classes, this is the ID of the attached object
100
+ owner_id: DeclarationId,
101
+ /// The entities that are owned by this declaration. For example, constants and methods that are defined inside of
102
+ /// the namespace. Note that this is a hashmap of unqualified name IDs to declaration IDs. That assists the
103
+ /// traversal of the graph when trying to resolve constant references or trying to discover which methods exist in a
104
+ /// class
105
+ members: IdentityHashMap<StringId, DeclarationId>,
106
+ /// The linearized ancestor chain for this declaration. These are the other declarations that this
107
+ /// declaration inherits from
108
+ ancestors: Ancestors,
109
+ /// The set of declarations that inherit from this declaration
110
+ descendants: IdentityHashSet<DeclarationId>,
111
+ /// The singleton class associated with this declaration
112
+ singleton_class_id: Option<DeclarationId>,
113
+ /// Diagnostics associated with this declaration
114
+ diagnostics: Vec<Diagnostic>,
115
+ }
116
+
117
+ impl $name {
118
+ #[must_use]
119
+ pub fn new(name: String, owner_id: DeclarationId) -> Self {
120
+ Self {
121
+ name,
122
+ definition_ids: Vec::new(),
123
+ members: IdentityHashMap::default(),
124
+ references: IdentityHashSet::default(),
125
+ owner_id,
126
+ ancestors: Ancestors::Partial(Vec::new()),
127
+ descendants: IdentityHashSet::default(),
128
+ singleton_class_id: None,
129
+ diagnostics: Vec::new(),
130
+ }
131
+ }
132
+
133
+ pub fn extend(&mut self, mut other: Declaration) {
134
+ self.definition_ids.extend(other.definitions());
135
+ self.diagnostics.extend(other.take_diagnostics());
136
+
137
+ match other {
138
+ Declaration::Namespace(namespace) => {
139
+ self.members.extend(namespace.members());
140
+ self.references.extend(namespace.references());
141
+ }
142
+ Declaration::Constant(constant) => {
143
+ self.references.extend(constant.references());
144
+ }
145
+ Declaration::ConstantAlias(constant_alias) => {
146
+ self.references.extend(constant_alias.references());
147
+ }
148
+ Declaration::Method(_)
149
+ | Declaration::GlobalVariable(_)
150
+ | Declaration::InstanceVariable(_)
151
+ | Declaration::ClassVariable(_) => {
152
+ panic!("Cannot extend a namespace declaration with a non-namespace declaration");
153
+ }
154
+ }
155
+ }
156
+
157
+ pub fn add_reference(&mut self, reference_id: ConstantReferenceId) {
158
+ self.references.insert(reference_id);
159
+ }
160
+
161
+ pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
162
+ self.singleton_class_id = Some(declaration_id);
163
+ }
164
+
165
+ pub fn clear_singleton_class_id(&mut self) {
166
+ self.singleton_class_id = None;
167
+ }
168
+
169
+ pub fn singleton_class_id(&self) -> Option<&DeclarationId> {
170
+ self.singleton_class_id.as_ref()
171
+ }
172
+
173
+ #[must_use]
174
+ pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
175
+ &self.members
176
+ }
177
+
178
+ pub fn add_member(&mut self, string_id: StringId, declaration_id: DeclarationId) {
179
+ self.members.insert(string_id, declaration_id);
180
+ }
181
+
182
+ pub fn remove_member(&mut self, string_id: &StringId) -> Option<DeclarationId> {
183
+ self.members.remove(string_id)
184
+ }
185
+
186
+ #[must_use]
187
+ pub fn member(&self, string_id: &StringId) -> Option<&DeclarationId> {
188
+ self.members.get(string_id)
189
+ }
190
+
191
+ pub fn set_ancestors(&mut self, ancestors: Ancestors) {
192
+ self.ancestors = ancestors;
193
+ }
194
+
195
+ pub fn ancestors(&self) -> &Ancestors {
196
+ &self.ancestors
197
+ }
198
+
199
+ pub fn ancestors_mut(&mut self) -> &mut Ancestors {
200
+ &mut self.ancestors
201
+ }
202
+
203
+ #[must_use]
204
+ pub fn clone_ancestors(&self) -> Ancestors {
205
+ self.ancestors.clone()
206
+ }
207
+
208
+ #[must_use]
209
+ pub fn has_complete_ancestors(&self) -> bool {
210
+ matches!(&self.ancestors, Ancestors::Complete(_) | Ancestors::Cyclic(_))
211
+ }
212
+
213
+ pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
214
+ self.descendants.insert(descendant_id);
215
+ }
216
+
217
+ fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
218
+ self.descendants.remove(descendant_id);
219
+ }
220
+
221
+ pub fn clear_descendants(&mut self) {
222
+ self.descendants.clear();
223
+ }
224
+
225
+ pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
226
+ &self.descendants
227
+ }
228
+ }
229
+ };
230
+ }
231
+
232
+ /// Macro to generate a new struct for simple declarations like variables and methods
233
+ macro_rules! simple_declaration {
234
+ ($name:ident, $reference_type:ty) => {
235
+ #[derive(Debug)]
236
+ pub struct $name {
237
+ /// The fully qualified name of this declaration
238
+ name: String,
239
+ /// The list of definition IDs that compose this declaration
240
+ definition_ids: Vec<DefinitionId>,
241
+ /// The set of references that are made to this declaration
242
+ references: IdentityHashSet<$reference_type>,
243
+ /// The ID of the owner of this declaration
244
+ owner_id: DeclarationId,
245
+ /// Diagnostics associated with this declaration
246
+ diagnostics: Vec<Diagnostic>,
247
+ }
248
+
249
+ impl $name {
250
+ #[must_use]
251
+ pub fn new(name: String, owner_id: DeclarationId) -> Self {
252
+ Self {
253
+ name,
254
+ definition_ids: Vec::new(),
255
+ references: IdentityHashSet::default(),
256
+ owner_id,
257
+ diagnostics: Vec::new(),
258
+ }
259
+ }
260
+
261
+ pub fn extend(&mut self, mut other: $name) {
262
+ self.definition_ids.extend(other.definitions());
263
+ self.diagnostics.extend(other.take_diagnostics());
264
+ self.references.extend(other.references());
265
+ }
266
+
267
+ #[must_use]
268
+ pub fn references(&self) -> &IdentityHashSet<$reference_type> {
269
+ &self.references
270
+ }
271
+
272
+ pub fn add_reference(&mut self, reference_id: $reference_type) {
273
+ self.references.insert(reference_id);
274
+ }
275
+
276
+ pub fn remove_reference(&mut self, reference_id: &$reference_type) {
277
+ self.references.remove(reference_id);
278
+ }
279
+
280
+ pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
281
+ std::mem::take(&mut self.diagnostics)
282
+ }
283
+
284
+ #[must_use]
285
+ pub fn definitions(&self) -> &[DefinitionId] {
286
+ &self.definition_ids
287
+ }
288
+ }
289
+ };
290
+ }
291
+
292
+ /// A `Declaration` represents the global concept of an entity in Ruby. For example, the class `Foo` may be defined 3
293
+ /// times in different files and the `Foo` declaration is the combination of all of those definitions that contribute to
294
+ /// the same fully qualified name
295
+ #[derive(Debug)]
296
+ pub enum Declaration {
297
+ Namespace(Namespace),
298
+ Constant(Box<ConstantDeclaration>),
299
+ ConstantAlias(Box<ConstantAliasDeclaration>),
300
+ Method(Box<MethodDeclaration>),
301
+ GlobalVariable(Box<GlobalVariableDeclaration>),
302
+ InstanceVariable(Box<InstanceVariableDeclaration>),
303
+ ClassVariable(Box<ClassVariableDeclaration>),
304
+ }
305
+ assert_mem_size!(Declaration, 16);
306
+
307
+ impl Declaration {
308
+ #[must_use]
309
+ pub fn name(&self) -> &str {
310
+ all_declarations!(self, it => &it.name)
311
+ }
312
+
313
+ #[must_use]
314
+ pub fn kind(&self) -> &'static str {
315
+ match self {
316
+ Declaration::Namespace(namespace) => namespace.kind(),
317
+ Declaration::Constant(_) => "Constant",
318
+ Declaration::ConstantAlias(_) => "ConstantAlias",
319
+ Declaration::Method(_) => "Method",
320
+ Declaration::GlobalVariable(_) => "GlobalVariable",
321
+ Declaration::InstanceVariable(_) => "InstanceVariable",
322
+ Declaration::ClassVariable(_) => "ClassVariable",
323
+ }
324
+ }
325
+
326
+ #[must_use]
327
+ pub fn as_namespace(&self) -> Option<&Namespace> {
328
+ match self {
329
+ Declaration::Namespace(namespace) => Some(namespace),
330
+ _ => None,
331
+ }
332
+ }
333
+
334
+ #[must_use]
335
+ pub fn as_namespace_mut(&mut self) -> Option<&mut Namespace> {
336
+ match self {
337
+ Declaration::Namespace(namespace) => Some(namespace),
338
+ _ => None,
339
+ }
340
+ }
341
+
342
+ #[must_use]
343
+ pub fn definitions(&self) -> &[DefinitionId] {
344
+ all_declarations!(self, it => &it.definition_ids)
345
+ }
346
+
347
+ #[must_use]
348
+ pub fn has_no_definitions(&self) -> bool {
349
+ all_declarations!(self, it => it.definition_ids.is_empty())
350
+ }
351
+
352
+ pub fn add_definition(&mut self, definition_id: DefinitionId) {
353
+ all_declarations!(self, it => {
354
+ debug_assert!(
355
+ !it.definition_ids.contains(&definition_id),
356
+ "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs"
357
+ );
358
+
359
+ it.definition_ids.push(definition_id);
360
+ });
361
+ }
362
+
363
+ // Deletes a definition from this declaration
364
+ pub fn remove_definition(&mut self, definition_id: &DefinitionId) -> bool {
365
+ all_declarations!(self, it => {
366
+ if let Some(pos) = it.definition_ids.iter().position(|id| id == definition_id) {
367
+ it.definition_ids.swap_remove(pos);
368
+ it.definition_ids.shrink_to_fit();
369
+ true
370
+ } else {
371
+ false
372
+ }
373
+ })
374
+ }
375
+
376
+ #[must_use]
377
+ pub fn owner_id(&self) -> &DeclarationId {
378
+ all_declarations!(self, it => &it.owner_id)
379
+ }
380
+
381
+ // Splits the fully qualified name either in the last `::` or the `#` to return the simple name of this declaration
382
+ #[must_use]
383
+ pub fn unqualified_name(&self) -> String {
384
+ all_declarations!(self, it => {
385
+ let after_colons = it.name.rsplit("::").next().unwrap_or(&it.name);
386
+ after_colons.rsplit('#').next().unwrap_or(after_colons).to_string()
387
+ })
388
+ }
389
+
390
+ #[must_use]
391
+ pub fn diagnostics(&self) -> &[Diagnostic] {
392
+ all_declarations!(self, it => &it.diagnostics)
393
+ }
394
+
395
+ pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
396
+ all_declarations!(self, it => std::mem::take(&mut it.diagnostics))
397
+ }
398
+
399
+ pub fn add_diagnostic(&mut self, diagnostic: Diagnostic) {
400
+ all_declarations!(self, it => it.diagnostics.push(diagnostic));
401
+ }
402
+
403
+ pub fn clear_diagnostics(&mut self) {
404
+ all_declarations!(self, it => it.diagnostics.clear());
405
+ }
406
+
407
+ #[must_use]
408
+ pub fn reference_count(&self) -> usize {
409
+ all_declarations!(self, it => it.references.len())
410
+ }
411
+
412
+ /// Returns the constant reference IDs for declarations that track constant references (`Namespace`, `Constant`,
413
+ /// `ConstantAlias`). Returns `None` for other declaration types.
414
+ #[must_use]
415
+ pub fn constant_references(&self) -> Option<&IdentityHashSet<ConstantReferenceId>> {
416
+ match self {
417
+ Declaration::Namespace(it) => Some(it.references()),
418
+ Declaration::Constant(it) => Some(it.references()),
419
+ Declaration::ConstantAlias(it) => Some(it.references()),
420
+ _ => None,
421
+ }
422
+ }
423
+
424
+ /// Adds a constant reference to this declaration.
425
+ ///
426
+ /// # Panics
427
+ ///
428
+ /// Panics if called on a declaration that doesn't track constant references.
429
+ pub fn add_constant_reference(&mut self, reference_id: ConstantReferenceId) {
430
+ match self {
431
+ Declaration::Namespace(it) => it.add_reference(reference_id),
432
+ Declaration::Constant(it) => it.add_reference(reference_id),
433
+ Declaration::ConstantAlias(it) => it.add_reference(reference_id),
434
+ _ => unreachable!("Cannot add constant reference to {} declaration", self.kind()),
435
+ }
436
+ }
437
+
438
+ /// Removes a constant reference from this declaration.
439
+ ///
440
+ /// # Panics
441
+ ///
442
+ /// Panics if called on a declaration that doesn't track constant references.
443
+ pub fn remove_constant_reference(&mut self, reference_id: &ConstantReferenceId) {
444
+ match self {
445
+ Declaration::Namespace(it) => it.remove_reference(reference_id),
446
+ Declaration::Constant(it) => it.remove_reference(reference_id),
447
+ Declaration::ConstantAlias(it) => it.remove_reference(reference_id),
448
+ _ => unreachable!("Cannot remove constant reference from {} declaration", self.kind()),
449
+ }
450
+ }
451
+ }
452
+
453
+ #[derive(Debug)]
454
+ pub enum Namespace {
455
+ Class(Box<ClassDeclaration>),
456
+ SingletonClass(Box<SingletonClassDeclaration>),
457
+ Module(Box<ModuleDeclaration>),
458
+ Todo(Box<TodoDeclaration>),
459
+ }
460
+ assert_mem_size!(Namespace, 16);
461
+
462
+ impl Namespace {
463
+ #[must_use]
464
+ pub fn kind(&self) -> &'static str {
465
+ match self {
466
+ Namespace::Class(_) => "Class",
467
+ Namespace::SingletonClass(_) => "SingletonClass",
468
+ Namespace::Module(_) => "Module",
469
+ Namespace::Todo(_) => "<TODO>",
470
+ }
471
+ }
472
+
473
+ #[must_use]
474
+ pub fn references(&self) -> &IdentityHashSet<ConstantReferenceId> {
475
+ all_namespaces!(self, it => &it.references)
476
+ }
477
+
478
+ pub fn remove_reference(&mut self, reference_id: &ConstantReferenceId) {
479
+ all_namespaces!(self, it => {
480
+ it.references.remove(reference_id);
481
+ });
482
+ }
483
+
484
+ pub fn add_reference(&mut self, reference_id: ConstantReferenceId) {
485
+ all_namespaces!(self, it => {
486
+ it.references.insert(reference_id);
487
+ });
488
+ }
489
+
490
+ #[must_use]
491
+ pub fn definitions(&self) -> &[DefinitionId] {
492
+ all_namespaces!(self, it => &it.definition_ids)
493
+ }
494
+
495
+ #[must_use]
496
+ pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
497
+ all_namespaces!(self, it => &it.members)
498
+ }
499
+
500
+ #[must_use]
501
+ pub fn diagnostics(&self) -> &[Diagnostic] {
502
+ all_namespaces!(self, it => &it.diagnostics)
503
+ }
504
+
505
+ pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
506
+ all_namespaces!(self, it => std::mem::take(&mut it.diagnostics))
507
+ }
508
+
509
+ pub fn extend(&mut self, other: Declaration) {
510
+ all_namespaces!(self, it => it.extend(other));
511
+ }
512
+
513
+ #[must_use]
514
+ pub fn ancestors(&self) -> &Ancestors {
515
+ all_namespaces!(self, it => it.ancestors())
516
+ }
517
+
518
+ #[must_use]
519
+ pub fn clone_ancestors(&self) -> Ancestors {
520
+ all_namespaces!(self, it => it.clone_ancestors())
521
+ }
522
+
523
+ pub fn set_ancestors(&mut self, ancestors: Ancestors) {
524
+ all_namespaces!(self, it => it.set_ancestors(ancestors));
525
+ }
526
+
527
+ #[must_use]
528
+ pub fn has_complete_ancestors(&self) -> bool {
529
+ all_namespaces!(self, it => it.has_complete_ancestors())
530
+ }
531
+
532
+ #[must_use]
533
+ pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
534
+ all_namespaces!(self, it => it.descendants())
535
+ }
536
+
537
+ pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
538
+ all_namespaces!(self, it => it.add_descendant(descendant_id));
539
+ }
540
+
541
+ pub fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
542
+ all_namespaces!(self, it => it.remove_descendant(descendant_id));
543
+ }
544
+
545
+ pub fn for_each_ancestor<F>(&self, mut f: F)
546
+ where
547
+ F: FnMut(&Ancestor),
548
+ {
549
+ all_namespaces!(self, it => it.ancestors().iter().for_each(&mut f));
550
+ }
551
+
552
+ pub fn for_each_descendant<F>(&self, mut f: F)
553
+ where
554
+ F: FnMut(&DeclarationId),
555
+ {
556
+ all_namespaces!(self, it => it.descendants().iter().for_each(&mut f));
557
+ }
558
+
559
+ pub fn clear_ancestors(&mut self) {
560
+ all_namespaces!(self, it => it.set_ancestors(Ancestors::Partial(vec![])));
561
+ }
562
+
563
+ pub fn clear_descendants(&mut self) {
564
+ all_namespaces!(self, it => it.clear_descendants());
565
+ }
566
+
567
+ #[must_use]
568
+ pub fn member(&self, str_id: &StringId) -> Option<&DeclarationId> {
569
+ all_namespaces!(self, it => it.member(str_id))
570
+ }
571
+
572
+ pub fn remove_member(&mut self, str_id: &StringId) -> Option<DeclarationId> {
573
+ all_namespaces!(self, it => it.remove_member(str_id))
574
+ }
575
+
576
+ #[must_use]
577
+ pub fn singleton_class(&self) -> Option<&DeclarationId> {
578
+ all_namespaces!(self, it => it.singleton_class_id())
579
+ }
580
+
581
+ pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
582
+ all_namespaces!(self, it => it.set_singleton_class_id(declaration_id));
583
+ }
584
+
585
+ pub fn clear_singleton_class_id(&mut self) {
586
+ all_namespaces!(self, it => it.clear_singleton_class_id());
587
+ }
588
+
589
+ #[must_use]
590
+ pub fn owner_id(&self) -> &DeclarationId {
591
+ all_namespaces!(self, it => &it.owner_id)
592
+ }
593
+
594
+ #[must_use]
595
+ pub fn name(&self) -> &str {
596
+ all_namespaces!(self, it => &it.name)
597
+ }
598
+ }
599
+
600
+ namespace_declaration!(Class, ClassDeclaration);
601
+ assert_mem_size!(ClassDeclaration, 216);
602
+ namespace_declaration!(Module, ModuleDeclaration);
603
+ assert_mem_size!(ModuleDeclaration, 216);
604
+ namespace_declaration!(SingletonClass, SingletonClassDeclaration);
605
+ assert_mem_size!(SingletonClassDeclaration, 216);
606
+ namespace_declaration!(Todo, TodoDeclaration);
607
+ assert_mem_size!(TodoDeclaration, 216);
608
+ simple_declaration!(ConstantDeclaration, ConstantReferenceId);
609
+ assert_mem_size!(ConstantDeclaration, 112);
610
+ simple_declaration!(MethodDeclaration, MethodReferenceId);
611
+ assert_mem_size!(MethodDeclaration, 112);
612
+ simple_declaration!(GlobalVariableDeclaration, GlobalVariableReferenceId);
613
+ assert_mem_size!(GlobalVariableDeclaration, 112);
614
+ simple_declaration!(InstanceVariableDeclaration, InstanceVariableReferenceId);
615
+ assert_mem_size!(InstanceVariableDeclaration, 112);
616
+ simple_declaration!(ClassVariableDeclaration, ClassVariableReferenceId);
617
+ assert_mem_size!(ClassVariableDeclaration, 112);
618
+ simple_declaration!(ConstantAliasDeclaration, ConstantReferenceId);
619
+ assert_mem_size!(ConstantAliasDeclaration, 112);
620
+
621
+ #[cfg(test)]
622
+ mod tests {
623
+ use super::*;
624
+
625
+ #[test]
626
+ #[should_panic(expected = "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs")]
627
+ fn inserting_duplicate_definitions() {
628
+ let mut decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
629
+ "MyDecl".to_string(),
630
+ DeclarationId::from("Object"),
631
+ ))));
632
+ let def_id = DefinitionId::new(123);
633
+
634
+ // The second call will panic because we're adding the same exact ID twice
635
+ decl.add_definition(def_id);
636
+ decl.add_definition(def_id);
637
+ }
638
+
639
+ #[test]
640
+ fn adding_and_removing_members() {
641
+ let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
642
+ "Foo".to_string(),
643
+ DeclarationId::from("Object"),
644
+ ))));
645
+ let member_name_id = StringId::from("Bar");
646
+ let member_decl_id = DeclarationId::from("Foo::Bar");
647
+
648
+ let Declaration::Namespace(Namespace::Class(mut class)) = decl else {
649
+ panic!("Expected a class declaration");
650
+ };
651
+ class.add_member(member_name_id, member_decl_id);
652
+ assert_eq!(class.members.len(), 1);
653
+
654
+ let removed = class.remove_member(&member_name_id);
655
+ assert_eq!(removed, Some(member_decl_id));
656
+ assert_eq!(class.members.len(), 0);
657
+ }
658
+
659
+ #[test]
660
+ fn unqualified_name() {
661
+ let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
662
+ "Foo".to_string(),
663
+ DeclarationId::from("Foo"),
664
+ ))));
665
+ assert_eq!(decl.unqualified_name(), "Foo");
666
+
667
+ let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
668
+ "Foo::Bar".to_string(),
669
+ DeclarationId::from("Foo"),
670
+ ))));
671
+ assert_eq!(decl.unqualified_name(), "Bar");
672
+
673
+ let decl = Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
674
+ "Foo::Bar#baz".to_string(),
675
+ DeclarationId::from("Foo::Bar"),
676
+ ))));
677
+ assert_eq!(decl.unqualified_name(), "baz");
678
+ }
679
+ }