rubydex 0.2.9 → 0.4.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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +110 -6
  3. data/THIRD_PARTY_LICENSES.html +271 -2
  4. data/exe/rdx +2 -73
  5. data/ext/rubydex/config.c +140 -0
  6. data/ext/rubydex/config.h +16 -0
  7. data/ext/rubydex/declaration.c +1 -1
  8. data/ext/rubydex/definition.c +32 -4
  9. data/ext/rubydex/diagnostic.c +75 -1
  10. data/ext/rubydex/diagnostic.h +2 -0
  11. data/ext/rubydex/graph.c +27 -48
  12. data/ext/rubydex/graph.h +6 -0
  13. data/ext/rubydex/query.c +487 -0
  14. data/ext/rubydex/query.h +8 -0
  15. data/ext/rubydex/reference.c +60 -0
  16. data/ext/rubydex/rubydex.c +4 -0
  17. data/ext/rubydex/utils.c +23 -4
  18. data/ext/rubydex/utils.h +5 -0
  19. data/lib/ruby_lsp/rubydex/addon.rb +211 -0
  20. data/lib/rubydex/cli/command/console.rb +55 -0
  21. data/lib/rubydex/cli/command/lint/explain.rb +74 -0
  22. data/lib/rubydex/cli/command/lint.rb +202 -0
  23. data/lib/rubydex/cli/command/mcp.rb +30 -0
  24. data/lib/rubydex/cli/command/query.rb +70 -0
  25. data/lib/rubydex/cli/command/skill.rb +69 -0
  26. data/lib/rubydex/cli/command.rb +168 -0
  27. data/lib/rubydex/cli.rb +93 -0
  28. data/lib/rubydex/config.rb +59 -0
  29. data/lib/rubydex/diagnostic.rb +12 -3
  30. data/lib/rubydex/errors.rb +42 -1
  31. data/lib/rubydex/graph.rb +10 -3
  32. data/lib/rubydex/linter/custom_rule.rb +97 -0
  33. data/lib/rubydex/linter/helpers/path_helpers.rb +78 -0
  34. data/lib/rubydex/linter/helpers/source_access_helpers.rb +31 -0
  35. data/lib/rubydex/linter/rule_loader.rb +36 -0
  36. data/lib/rubydex/linter/rule_test_case.rb +343 -0
  37. data/lib/rubydex/linter/runner.rb +56 -0
  38. data/lib/rubydex/linter.rb +19 -0
  39. data/lib/rubydex/location.rb +3 -0
  40. data/lib/rubydex/mcp_server.rb +1 -2
  41. data/lib/rubydex/related_information.rb +17 -0
  42. data/lib/rubydex/rule.rb +33 -0
  43. data/lib/rubydex/severity.rb +70 -0
  44. data/lib/rubydex/skill.rb +88 -0
  45. data/lib/rubydex/skill_registry.rb +62 -0
  46. data/lib/rubydex/version.rb +1 -1
  47. data/lib/rubydex.rb +6 -0
  48. data/lib/rubydex_linter/rules/rule_structure.rb +125 -0
  49. data/rbi/rubydex.rbi +578 -15
  50. data/rust/Cargo.lock +7 -0
  51. data/rust/rubydex/Cargo.toml +1 -0
  52. data/rust/rubydex/benches/graph_memory.rs +20 -4
  53. data/rust/rubydex/src/compile_assertions.rs +15 -0
  54. data/rust/rubydex/src/config.rs +538 -157
  55. data/rust/rubydex/src/diagnostic.rs +66 -40
  56. data/rust/rubydex/src/errors.rs +0 -1
  57. data/rust/rubydex/src/indexing/local_graph.rs +6 -5
  58. data/rust/rubydex/src/indexing/rbs_indexer.rs +284 -8
  59. data/rust/rubydex/src/indexing/ruby_indexer.rs +59 -70
  60. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +195 -86
  61. data/rust/rubydex/src/lib.rs +1 -0
  62. data/rust/rubydex/src/listing.rs +26 -1
  63. data/rust/rubydex/src/main.rs +9 -128
  64. data/rust/rubydex/src/model/declaration.rs +301 -229
  65. data/rust/rubydex/src/model/definitions.rs +27 -26
  66. data/rust/rubydex/src/model/document.rs +43 -7
  67. data/rust/rubydex/src/model/graph.rs +67 -68
  68. data/rust/rubydex/src/model/id.rs +55 -0
  69. data/rust/rubydex/src/model/ids.rs +21 -9
  70. data/rust/rubydex/src/model/name.rs +88 -19
  71. data/rust/rubydex/src/model/references.rs +16 -13
  72. data/rust/rubydex/src/operation/ruby_builder.rs +78 -104
  73. data/rust/rubydex/src/path_helpers.rs +77 -0
  74. data/rust/rubydex/src/query/cypher/schema.rs +853 -0
  75. data/rust/rubydex/src/query/cypher/schema_info.rs +161 -0
  76. data/rust/rubydex/src/query/cypher/tests.rs +253 -0
  77. data/rust/rubydex/src/query/cypher.rs +54 -0
  78. data/rust/rubydex/src/query.rs +125 -43
  79. data/rust/rubydex/src/resolution.rs +368 -395
  80. data/rust/rubydex/src/resolution_tests.rs +504 -78
  81. data/rust/rubydex/src/test_utils/context.rs +2 -1
  82. data/rust/rubydex/src/test_utils/graph_test.rs +26 -12
  83. data/rust/rubydex/src/test_utils/local_graph_test.rs +19 -0
  84. data/rust/rubydex/tests/cli.rs +4 -4
  85. data/rust/rubydex-sys/src/config_api.rs +205 -0
  86. data/rust/rubydex-sys/src/cypher_api.rs +791 -0
  87. data/rust/rubydex-sys/src/declaration_api.rs +6 -3
  88. data/rust/rubydex-sys/src/definition_api.rs +27 -7
  89. data/rust/rubydex-sys/src/diagnostic_api.rs +77 -8
  90. data/rust/rubydex-sys/src/graph_api.rs +31 -68
  91. data/rust/rubydex-sys/src/lib.rs +2 -0
  92. data/rust/rubydex-sys/src/name_api.rs +2 -6
  93. data/rust/rubydex-sys/src/reference_api.rs +58 -12
  94. data/rust/rubydex-sys/src/utils.rs +37 -0
  95. data/skills/send-private-method/SKILL.md +133 -0
  96. metadata +37 -2
@@ -1,3 +1,5 @@
1
+ use std::hash::Hash;
2
+
1
3
  use crate::assert_mem_size;
2
4
  use crate::model::ids::{
3
5
  ClassVariableReferenceId, GlobalVariableReferenceId, InstanceVariableReferenceId, MethodReferenceId,
@@ -57,23 +59,6 @@ impl<'a> IntoIterator for &'a Ancestors {
57
59
  }
58
60
  }
59
61
 
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
62
  macro_rules! all_namespaces {
78
63
  ($value:expr, $var:ident => $expr:expr) => {
79
64
  match $value {
@@ -90,56 +75,29 @@ macro_rules! namespace_declaration {
90
75
  ($variant:ident, $name:ident) => {
91
76
  #[derive(Debug)]
92
77
  pub struct $name {
93
- /// The fully qualified name of this declaration
94
- name: Box<str>,
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>,
78
+ core: DeclarationCore<ConstantReferenceId>,
79
+ namespace_store: NamespaceStore,
113
80
  }
114
81
 
115
82
  impl $name {
116
83
  #[must_use]
117
84
  pub fn new(name: String, owner_id: DeclarationId) -> Self {
118
85
  Self {
119
- name: name.into_boxed_str(),
120
- definition_ids: Vec::new(),
121
- members: IdentityHashMap::default(),
122
- references: IdentityHashSet::default(),
123
- owner_id,
124
- ancestors: Ancestors::Partial(Vec::new()),
125
- descendants: IdentityHashSet::default(),
126
- singleton_class_id: None,
86
+ core: DeclarationCore::new(name, owner_id),
87
+ namespace_store: NamespaceStore::new(),
127
88
  }
128
89
  }
129
90
 
130
91
  pub fn extend(&mut self, other: Declaration) {
131
- self.definition_ids.extend(other.definitions());
92
+ self.core.definition_ids.extend(other.definitions());
132
93
 
133
94
  match other {
134
95
  Declaration::Namespace(namespace) => {
135
- self.members.extend(namespace.members());
136
- self.references.extend(namespace.references());
137
- }
138
- Declaration::Constant(constant) => {
139
- self.references.extend(constant.references());
96
+ self.namespace_store.members.extend(namespace.members());
97
+ self.core.references.extend(namespace.references());
140
98
  }
141
- Declaration::ConstantAlias(constant_alias) => {
142
- self.references.extend(constant_alias.references());
99
+ Declaration::Constant(it) | Declaration::ConstantAlias(it) => {
100
+ self.core.references.extend(it.references());
143
101
  }
144
102
  Declaration::Method(_)
145
103
  | Declaration::GlobalVariable(_)
@@ -149,132 +107,198 @@ macro_rules! namespace_declaration {
149
107
  }
150
108
  }
151
109
  }
110
+ }
111
+ };
112
+ }
152
113
 
153
- pub fn add_reference(&mut self, reference_id: ConstantReferenceId) {
154
- self.references.insert(reference_id);
155
- }
114
+ /// The core data of a declaration, shared across all of them
115
+ #[derive(Debug)]
116
+ pub struct DeclarationCore<T> {
117
+ /// The fully qualified name of this declaration
118
+ name: Box<str>,
119
+ /// The list of definition IDs that compose this declaration
120
+ definition_ids: Vec<DefinitionId>,
121
+ /// The set of references that are made to this declaration
122
+ references: IdentityHashSet<T>,
123
+ /// The ID of the owner of this declaration
124
+ owner_id: DeclarationId,
125
+ }
156
126
 
157
- pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
158
- self.singleton_class_id = Some(declaration_id);
159
- }
127
+ impl<T: Eq + Hash> DeclarationCore<T> {
128
+ #[must_use]
129
+ pub fn new(name: String, owner_id: DeclarationId) -> Self {
130
+ Self {
131
+ name: name.into_boxed_str(),
132
+ definition_ids: Vec::new(),
133
+ references: IdentityHashSet::default(),
134
+ owner_id,
135
+ }
136
+ }
160
137
 
161
- pub fn clear_singleton_class_id(&mut self) {
162
- self.singleton_class_id = None;
163
- }
138
+ #[must_use]
139
+ pub fn name(&self) -> &str {
140
+ &self.name
141
+ }
164
142
 
165
- pub fn singleton_class_id(&self) -> Option<&DeclarationId> {
166
- self.singleton_class_id.as_ref()
167
- }
143
+ #[must_use]
144
+ pub fn unqualified_name(&self) -> String {
145
+ let after_colons = self.name.rsplit("::").next().unwrap_or(&self.name);
146
+ after_colons.rsplit('#').next().unwrap_or(after_colons).to_string()
147
+ }
168
148
 
169
- #[must_use]
170
- pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
171
- &self.members
172
- }
149
+ pub fn extend(&mut self, other: Self) {
150
+ self.definition_ids.extend(other.definition_ids);
151
+ self.references.extend(other.references);
152
+ }
173
153
 
174
- pub fn add_member(&mut self, string_id: StringId, declaration_id: DeclarationId) {
175
- self.members.insert(string_id, declaration_id);
176
- }
154
+ #[must_use]
155
+ pub fn references(&self) -> &IdentityHashSet<T> {
156
+ &self.references
157
+ }
177
158
 
178
- pub fn remove_member(&mut self, string_id: &StringId) -> Option<DeclarationId> {
179
- self.members.remove(string_id)
180
- }
159
+ pub fn add_reference(&mut self, reference_id: T) {
160
+ self.references.insert(reference_id);
161
+ }
181
162
 
182
- #[must_use]
183
- pub fn member(&self, string_id: &StringId) -> Option<&DeclarationId> {
184
- self.members.get(string_id)
185
- }
163
+ pub fn remove_reference(&mut self, reference_id: &T) {
164
+ self.references.remove(reference_id);
165
+ }
186
166
 
187
- pub fn set_ancestors(&mut self, ancestors: Ancestors) {
188
- self.ancestors = ancestors;
189
- }
167
+ #[must_use]
168
+ pub fn has_no_definitions(&self) -> bool {
169
+ self.definition_ids.is_empty()
170
+ }
190
171
 
191
- pub fn ancestors(&self) -> &Ancestors {
192
- &self.ancestors
193
- }
172
+ #[must_use]
173
+ pub fn definitions(&self) -> &[DefinitionId] {
174
+ &self.definition_ids
175
+ }
194
176
 
195
- pub fn ancestors_mut(&mut self) -> &mut Ancestors {
196
- &mut self.ancestors
197
- }
177
+ pub fn add_definition(&mut self, definition_id: DefinitionId) {
178
+ debug_assert!(
179
+ !self.definition_ids.contains(&definition_id),
180
+ "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs"
181
+ );
198
182
 
199
- #[must_use]
200
- pub fn clone_ancestors(&self) -> Ancestors {
201
- self.ancestors.clone()
202
- }
183
+ self.definition_ids.push(definition_id);
184
+ }
203
185
 
204
- #[must_use]
205
- pub fn has_complete_ancestors(&self) -> bool {
206
- matches!(&self.ancestors, Ancestors::Complete(_) | Ancestors::Cyclic(_))
207
- }
186
+ pub fn remove_definition(&mut self, definition_id: &DefinitionId) -> bool {
187
+ if let Some(pos) = self.definition_ids.iter().position(|id| id == definition_id) {
188
+ self.definition_ids.swap_remove(pos);
189
+ self.definition_ids.shrink_to_fit();
190
+ true
191
+ } else {
192
+ false
193
+ }
194
+ }
195
+ }
208
196
 
209
- pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
210
- self.descendants.insert(descendant_id);
211
- }
197
+ /// Storage for namespace data, like ancestors, descendants, members and singleton class
198
+ #[derive(Debug)]
199
+ pub struct NamespaceStore {
200
+ /// The entities that are owned by this declaration. For example, constants and methods that are defined inside of
201
+ /// the namespace. Note that this is a hashmap of unqualified name IDs to declaration IDs. That assists the
202
+ /// traversal of the graph when trying to resolve constant references or trying to discover which methods exist in a
203
+ /// class
204
+ members: IdentityHashMap<StringId, DeclarationId>,
205
+ /// The linearized ancestor chain for this declaration. These are the other declarations that this
206
+ /// declaration inherits from
207
+ ancestors: Ancestors,
208
+ /// The set of declarations that inherit from this declaration
209
+ descendants: IdentityHashSet<DeclarationId>,
210
+ /// The singleton class associated with this declaration
211
+ singleton_class_id: Option<DeclarationId>,
212
+ }
212
213
 
213
- fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
214
- self.descendants.remove(descendant_id);
215
- }
214
+ impl NamespaceStore {
215
+ #[must_use]
216
+ pub fn new() -> Self {
217
+ Self {
218
+ members: IdentityHashMap::default(),
219
+ ancestors: Ancestors::Partial(Vec::new()),
220
+ descendants: IdentityHashSet::default(),
221
+ singleton_class_id: None,
222
+ }
223
+ }
216
224
 
217
- pub fn clear_descendants(&mut self) {
218
- self.descendants.clear();
219
- }
225
+ pub fn extend(&mut self, other: Self) {
226
+ self.members.extend(other.members);
227
+ self.descendants.extend(other.descendants);
228
+ }
220
229
 
221
- pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
222
- &self.descendants
223
- }
224
- }
225
- };
226
- }
230
+ pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
231
+ self.singleton_class_id = Some(declaration_id);
232
+ }
227
233
 
228
- /// Macro to generate a new struct for simple declarations like variables and methods
229
- macro_rules! simple_declaration {
230
- ($name:ident, $reference_type:ty) => {
231
- #[derive(Debug)]
232
- pub struct $name {
233
- /// The fully qualified name of this declaration
234
- name: Box<str>,
235
- /// The list of definition IDs that compose this declaration
236
- definition_ids: Vec<DefinitionId>,
237
- /// The set of references that are made to this declaration
238
- references: IdentityHashSet<$reference_type>,
239
- /// The ID of the owner of this declaration
240
- owner_id: DeclarationId,
241
- }
234
+ pub fn clear_singleton_class_id(&mut self) {
235
+ self.singleton_class_id = None;
236
+ }
242
237
 
243
- impl $name {
244
- #[must_use]
245
- pub fn new(name: String, owner_id: DeclarationId) -> Self {
246
- Self {
247
- name: name.into_boxed_str(),
248
- definition_ids: Vec::new(),
249
- references: IdentityHashSet::default(),
250
- owner_id,
251
- }
252
- }
238
+ #[must_use]
239
+ pub fn singleton_class_id(&self) -> Option<&DeclarationId> {
240
+ self.singleton_class_id.as_ref()
241
+ }
253
242
 
254
- pub fn extend(&mut self, other: $name) {
255
- self.definition_ids.extend(other.definitions());
256
- self.references.extend(other.references());
257
- }
243
+ #[must_use]
244
+ pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
245
+ &self.members
246
+ }
258
247
 
259
- #[must_use]
260
- pub fn references(&self) -> &IdentityHashSet<$reference_type> {
261
- &self.references
262
- }
248
+ pub fn add_member(&mut self, string_id: StringId, declaration_id: DeclarationId) {
249
+ self.members.insert(string_id, declaration_id);
250
+ }
263
251
 
264
- pub fn add_reference(&mut self, reference_id: $reference_type) {
265
- self.references.insert(reference_id);
266
- }
252
+ pub fn remove_member(&mut self, string_id: &StringId) -> Option<DeclarationId> {
253
+ self.members.remove(string_id)
254
+ }
267
255
 
268
- pub fn remove_reference(&mut self, reference_id: &$reference_type) {
269
- self.references.remove(reference_id);
270
- }
256
+ #[must_use]
257
+ pub fn member(&self, string_id: &StringId) -> Option<&DeclarationId> {
258
+ self.members.get(string_id)
259
+ }
271
260
 
272
- #[must_use]
273
- pub fn definitions(&self) -> &[DefinitionId] {
274
- &self.definition_ids
275
- }
276
- }
277
- };
261
+ pub fn set_ancestors(&mut self, ancestors: Ancestors) {
262
+ self.ancestors = ancestors;
263
+ }
264
+
265
+ #[must_use]
266
+ pub fn ancestors(&self) -> &Ancestors {
267
+ &self.ancestors
268
+ }
269
+
270
+ #[must_use]
271
+ pub fn clone_ancestors(&self) -> Ancestors {
272
+ self.ancestors.clone()
273
+ }
274
+
275
+ #[must_use]
276
+ pub fn has_complete_ancestors(&self) -> bool {
277
+ matches!(&self.ancestors, Ancestors::Complete(_) | Ancestors::Cyclic(_))
278
+ }
279
+
280
+ pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
281
+ self.descendants.insert(descendant_id);
282
+ }
283
+
284
+ fn remove_descendant(&mut self, descendant_id: DeclarationId) {
285
+ self.descendants.remove(&descendant_id);
286
+ }
287
+
288
+ pub fn clear_descendants(&mut self) {
289
+ self.descendants.clear();
290
+ }
291
+
292
+ #[must_use]
293
+ pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
294
+ &self.descendants
295
+ }
296
+ }
297
+
298
+ impl Default for NamespaceStore {
299
+ fn default() -> Self {
300
+ Self::new()
301
+ }
278
302
  }
279
303
 
280
304
  /// A `Declaration` represents the global concept of an entity in Ruby. For example, the class `Foo` may be defined 3
@@ -295,7 +319,14 @@ assert_mem_size!(Declaration, 16);
295
319
  impl Declaration {
296
320
  #[must_use]
297
321
  pub fn name(&self) -> &str {
298
- all_declarations!(self, it => &it.name)
322
+ match self {
323
+ Self::Namespace(namespace) => namespace.core().name(),
324
+ Self::ConstantAlias(it) | Self::Constant(it) => it.name(),
325
+ Self::Method(it) => it.name(),
326
+ Self::GlobalVariable(it) => it.name(),
327
+ Self::InstanceVariable(it) => it.name(),
328
+ Self::ClassVariable(it) => it.name(),
329
+ }
299
330
  }
300
331
 
301
332
  #[must_use]
@@ -377,55 +408,86 @@ impl Declaration {
377
408
 
378
409
  #[must_use]
379
410
  pub fn definitions(&self) -> &[DefinitionId] {
380
- all_declarations!(self, it => &it.definition_ids)
411
+ match self {
412
+ Self::Namespace(namespace) => namespace.core().definitions(),
413
+ Self::Constant(it) | Self::ConstantAlias(it) => it.definitions(),
414
+ Self::Method(it) => it.definitions(),
415
+ Self::GlobalVariable(it) => it.definitions(),
416
+ Self::InstanceVariable(it) => it.definitions(),
417
+ Self::ClassVariable(it) => it.definitions(),
418
+ }
381
419
  }
382
420
 
383
421
  #[must_use]
384
422
  pub fn has_no_definitions(&self) -> bool {
385
- all_declarations!(self, it => it.definition_ids.is_empty())
423
+ match self {
424
+ Self::Namespace(namespace) => namespace.core().has_no_definitions(),
425
+ Self::Constant(it) | Self::ConstantAlias(it) => it.has_no_definitions(),
426
+ Self::Method(it) => it.has_no_definitions(),
427
+ Self::GlobalVariable(it) => it.has_no_definitions(),
428
+ Self::InstanceVariable(it) => it.has_no_definitions(),
429
+ Self::ClassVariable(it) => it.has_no_definitions(),
430
+ }
386
431
  }
387
432
 
388
433
  pub fn add_definition(&mut self, definition_id: DefinitionId) {
389
- all_declarations!(self, it => {
390
- debug_assert!(
391
- !it.definition_ids.contains(&definition_id),
392
- "Cannot add the same exact definition to a declaration twice. Duplicate definition IDs"
393
- );
394
-
395
- it.definition_ids.push(definition_id);
396
- });
434
+ match self {
435
+ Self::Namespace(namespace) => namespace.core_mut().add_definition(definition_id),
436
+ Self::Constant(it) | Self::ConstantAlias(it) => it.add_definition(definition_id),
437
+ Self::Method(it) => it.add_definition(definition_id),
438
+ Self::GlobalVariable(it) => it.add_definition(definition_id),
439
+ Self::InstanceVariable(it) => it.add_definition(definition_id),
440
+ Self::ClassVariable(it) => it.add_definition(definition_id),
441
+ }
397
442
  }
398
443
 
399
444
  // Deletes a definition from this declaration
400
445
  pub fn remove_definition(&mut self, definition_id: &DefinitionId) -> bool {
401
- all_declarations!(self, it => {
402
- if let Some(pos) = it.definition_ids.iter().position(|id| id == definition_id) {
403
- it.definition_ids.swap_remove(pos);
404
- it.definition_ids.shrink_to_fit();
405
- true
406
- } else {
407
- false
408
- }
409
- })
446
+ match self {
447
+ Self::Namespace(namespace) => namespace.core_mut().remove_definition(definition_id),
448
+ Self::Constant(it) | Self::ConstantAlias(it) => it.remove_definition(definition_id),
449
+ Self::Method(it) => it.remove_definition(definition_id),
450
+ Self::GlobalVariable(it) => it.remove_definition(definition_id),
451
+ Self::InstanceVariable(it) => it.remove_definition(definition_id),
452
+ Self::ClassVariable(it) => it.remove_definition(definition_id),
453
+ }
410
454
  }
411
455
 
412
456
  #[must_use]
413
457
  pub fn owner_id(&self) -> &DeclarationId {
414
- all_declarations!(self, it => &it.owner_id)
458
+ match self {
459
+ Self::Namespace(namespace) => &namespace.core().owner_id,
460
+ Self::Constant(it) | Self::ConstantAlias(it) => &it.owner_id,
461
+ Self::Method(it) => &it.owner_id,
462
+ Self::GlobalVariable(it) => &it.owner_id,
463
+ Self::InstanceVariable(it) => &it.owner_id,
464
+ Self::ClassVariable(it) => &it.owner_id,
465
+ }
415
466
  }
416
467
 
417
468
  // Splits the fully qualified name either in the last `::` or the `#` to return the simple name of this declaration
418
469
  #[must_use]
419
470
  pub fn unqualified_name(&self) -> String {
420
- all_declarations!(self, it => {
421
- let after_colons = it.name.rsplit("::").next().unwrap_or(&it.name);
422
- after_colons.rsplit('#').next().unwrap_or(after_colons).to_string()
423
- })
471
+ match self {
472
+ Self::Namespace(namespace) => namespace.core().unqualified_name(),
473
+ Self::Constant(it) | Self::ConstantAlias(it) => it.unqualified_name(),
474
+ Self::Method(it) => it.unqualified_name(),
475
+ Self::GlobalVariable(it) => it.unqualified_name(),
476
+ Self::InstanceVariable(it) => it.unqualified_name(),
477
+ Self::ClassVariable(it) => it.unqualified_name(),
478
+ }
424
479
  }
425
480
 
426
481
  #[must_use]
427
482
  pub fn reference_count(&self) -> usize {
428
- all_declarations!(self, it => it.references.len())
483
+ match self {
484
+ Self::Namespace(namespace) => namespace.core().references.len(),
485
+ Self::Constant(it) | Self::ConstantAlias(it) => it.references.len(),
486
+ Self::Method(it) => it.references.len(),
487
+ Self::GlobalVariable(it) => it.references.len(),
488
+ Self::InstanceVariable(it) => it.references.len(),
489
+ Self::ClassVariable(it) => it.references.len(),
490
+ }
429
491
  }
430
492
 
431
493
  /// Returns the constant reference IDs for declarations that track constant references (`Namespace`, `Constant`,
@@ -434,8 +496,7 @@ impl Declaration {
434
496
  pub fn constant_references(&self) -> Option<&IdentityHashSet<ConstantReferenceId>> {
435
497
  match self {
436
498
  Declaration::Namespace(it) => Some(it.references()),
437
- Declaration::Constant(it) => Some(it.references()),
438
- Declaration::ConstantAlias(it) => Some(it.references()),
499
+ Declaration::Constant(it) | Declaration::ConstantAlias(it) => Some(it.references()),
439
500
  _ => None,
440
501
  }
441
502
  }
@@ -448,8 +509,7 @@ impl Declaration {
448
509
  pub fn add_constant_reference(&mut self, reference_id: ConstantReferenceId) {
449
510
  match self {
450
511
  Declaration::Namespace(it) => it.add_reference(reference_id),
451
- Declaration::Constant(it) => it.add_reference(reference_id),
452
- Declaration::ConstantAlias(it) => it.add_reference(reference_id),
512
+ Declaration::Constant(it) | Declaration::ConstantAlias(it) => it.add_reference(reference_id),
453
513
  _ => unreachable!("Cannot add constant reference to {} declaration", self.kind()),
454
514
  }
455
515
  }
@@ -462,8 +522,7 @@ impl Declaration {
462
522
  pub fn remove_constant_reference(&mut self, reference_id: &ConstantReferenceId) {
463
523
  match self {
464
524
  Declaration::Namespace(it) => it.remove_reference(reference_id),
465
- Declaration::Constant(it) => it.remove_reference(reference_id),
466
- Declaration::ConstantAlias(it) => it.remove_reference(reference_id),
525
+ Declaration::Constant(it) | Declaration::ConstantAlias(it) => it.remove_reference(reference_id),
467
526
  _ => unreachable!("Cannot remove constant reference from {} declaration", self.kind()),
468
527
  }
469
528
  }
@@ -479,6 +538,16 @@ pub enum Namespace {
479
538
  assert_mem_size!(Namespace, 16);
480
539
 
481
540
  impl Namespace {
541
+ #[must_use]
542
+ pub fn core(&self) -> &DeclarationCore<ConstantReferenceId> {
543
+ all_namespaces!(self, it => &it.core)
544
+ }
545
+
546
+ #[must_use]
547
+ pub fn core_mut(&mut self) -> &mut DeclarationCore<ConstantReferenceId> {
548
+ all_namespaces!(self, it => &mut it.core)
549
+ }
550
+
482
551
  #[must_use]
483
552
  pub fn kind(&self) -> &'static str {
484
553
  match self {
@@ -491,29 +560,29 @@ impl Namespace {
491
560
 
492
561
  #[must_use]
493
562
  pub fn references(&self) -> &IdentityHashSet<ConstantReferenceId> {
494
- all_namespaces!(self, it => &it.references)
563
+ all_namespaces!(self, it => &it.core.references)
495
564
  }
496
565
 
497
566
  pub fn remove_reference(&mut self, reference_id: &ConstantReferenceId) {
498
567
  all_namespaces!(self, it => {
499
- it.references.remove(reference_id);
568
+ it.core.remove_reference(reference_id);
500
569
  });
501
570
  }
502
571
 
503
572
  pub fn add_reference(&mut self, reference_id: ConstantReferenceId) {
504
573
  all_namespaces!(self, it => {
505
- it.references.insert(reference_id);
574
+ it.core.add_reference(reference_id);
506
575
  });
507
576
  }
508
577
 
509
578
  #[must_use]
510
579
  pub fn definitions(&self) -> &[DefinitionId] {
511
- all_namespaces!(self, it => &it.definition_ids)
580
+ all_namespaces!(self, it => &it.core.definitions())
512
581
  }
513
582
 
514
583
  #[must_use]
515
584
  pub fn members(&self) -> &IdentityHashMap<StringId, DeclarationId> {
516
- all_namespaces!(self, it => &it.members)
585
+ all_namespaces!(self, it => &it.namespace_store.members)
517
586
  }
518
587
 
519
588
  pub fn extend(&mut self, other: Declaration) {
@@ -522,88 +591,85 @@ impl Namespace {
522
591
 
523
592
  #[must_use]
524
593
  pub fn ancestors(&self) -> &Ancestors {
525
- all_namespaces!(self, it => it.ancestors())
594
+ all_namespaces!(self, it => it.namespace_store.ancestors())
526
595
  }
527
596
 
528
597
  #[must_use]
529
598
  pub fn clone_ancestors(&self) -> Ancestors {
530
- all_namespaces!(self, it => it.clone_ancestors())
599
+ all_namespaces!(self, it => it.namespace_store.clone_ancestors())
531
600
  }
532
601
 
533
602
  pub fn set_ancestors(&mut self, ancestors: Ancestors) {
534
- all_namespaces!(self, it => it.set_ancestors(ancestors));
603
+ all_namespaces!(self, it => it.namespace_store.set_ancestors(ancestors));
535
604
  }
536
605
 
537
606
  #[must_use]
538
607
  pub fn has_complete_ancestors(&self) -> bool {
539
- all_namespaces!(self, it => it.has_complete_ancestors())
608
+ all_namespaces!(self, it => it.namespace_store.has_complete_ancestors())
540
609
  }
541
610
 
542
611
  #[must_use]
543
612
  pub fn descendants(&self) -> &IdentityHashSet<DeclarationId> {
544
- all_namespaces!(self, it => it.descendants())
613
+ all_namespaces!(self, it => it.namespace_store.descendants())
545
614
  }
546
615
 
547
616
  pub fn add_descendant(&mut self, descendant_id: DeclarationId) {
548
- all_namespaces!(self, it => it.add_descendant(descendant_id));
549
- }
550
-
551
- pub fn remove_descendant(&mut self, descendant_id: &DeclarationId) {
552
- all_namespaces!(self, it => it.remove_descendant(descendant_id));
617
+ all_namespaces!(self, it => it.namespace_store.add_descendant(descendant_id));
553
618
  }
554
619
 
555
- pub fn for_each_ancestor<F>(&self, mut f: F)
556
- where
557
- F: FnMut(&Ancestor),
558
- {
559
- all_namespaces!(self, it => it.ancestors().iter().for_each(&mut f));
620
+ pub fn remove_descendant(&mut self, descendant_id: DeclarationId) {
621
+ all_namespaces!(self, it => it.namespace_store.remove_descendant(descendant_id));
560
622
  }
561
623
 
562
624
  pub fn for_each_descendant<F>(&self, mut f: F)
563
625
  where
564
626
  F: FnMut(&DeclarationId),
565
627
  {
566
- all_namespaces!(self, it => it.descendants().iter().for_each(&mut f));
628
+ all_namespaces!(self, it => it.namespace_store.descendants().iter().for_each(&mut f));
567
629
  }
568
630
 
569
631
  pub fn clear_ancestors(&mut self) {
570
- all_namespaces!(self, it => it.set_ancestors(Ancestors::Partial(vec![])));
632
+ all_namespaces!(self, it => it.namespace_store.set_ancestors(Ancestors::Partial(vec![])));
571
633
  }
572
634
 
573
635
  pub fn clear_descendants(&mut self) {
574
- all_namespaces!(self, it => it.clear_descendants());
636
+ all_namespaces!(self, it => it.namespace_store.clear_descendants());
575
637
  }
576
638
 
577
639
  #[must_use]
578
640
  pub fn member(&self, str_id: &StringId) -> Option<&DeclarationId> {
579
- all_namespaces!(self, it => it.member(str_id))
641
+ all_namespaces!(self, it => it.namespace_store.member(str_id))
642
+ }
643
+
644
+ pub fn add_member(&mut self, string_id: StringId, declaration_id: DeclarationId) {
645
+ all_namespaces!(self, it => it.namespace_store.add_member(string_id, declaration_id));
580
646
  }
581
647
 
582
648
  pub fn remove_member(&mut self, str_id: &StringId) -> Option<DeclarationId> {
583
- all_namespaces!(self, it => it.remove_member(str_id))
649
+ all_namespaces!(self, it => it.namespace_store.remove_member(str_id))
584
650
  }
585
651
 
586
652
  #[must_use]
587
653
  pub fn singleton_class(&self) -> Option<&DeclarationId> {
588
- all_namespaces!(self, it => it.singleton_class_id())
654
+ all_namespaces!(self, it => it.namespace_store.singleton_class_id())
589
655
  }
590
656
 
591
657
  pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
592
- all_namespaces!(self, it => it.set_singleton_class_id(declaration_id));
658
+ all_namespaces!(self, it => it.namespace_store.set_singleton_class_id(declaration_id));
593
659
  }
594
660
 
595
661
  pub fn clear_singleton_class_id(&mut self) {
596
- all_namespaces!(self, it => it.clear_singleton_class_id());
662
+ all_namespaces!(self, it => it.namespace_store.clear_singleton_class_id());
597
663
  }
598
664
 
599
665
  #[must_use]
600
666
  pub fn owner_id(&self) -> &DeclarationId {
601
- all_namespaces!(self, it => &it.owner_id)
667
+ all_namespaces!(self, it => &it.core.owner_id)
602
668
  }
603
669
 
604
670
  #[must_use]
605
671
  pub fn name(&self) -> &str {
606
- all_namespaces!(self, it => &it.name)
672
+ all_namespaces!(self, it => &it.core.name())
607
673
  }
608
674
  }
609
675
 
@@ -615,17 +681,23 @@ namespace_declaration!(SingletonClass, SingletonClassDeclaration);
615
681
  assert_mem_size!(SingletonClassDeclaration, 184);
616
682
  namespace_declaration!(Todo, TodoDeclaration);
617
683
  assert_mem_size!(TodoDeclaration, 184);
618
- simple_declaration!(ConstantDeclaration, ConstantReferenceId);
684
+
685
+ pub type ConstantDeclaration = DeclarationCore<ConstantReferenceId>;
619
686
  assert_mem_size!(ConstantDeclaration, 80);
620
- simple_declaration!(MethodDeclaration, MethodReferenceId);
687
+
688
+ pub type MethodDeclaration = DeclarationCore<MethodReferenceId>;
621
689
  assert_mem_size!(MethodDeclaration, 80);
622
- simple_declaration!(GlobalVariableDeclaration, GlobalVariableReferenceId);
690
+
691
+ pub type GlobalVariableDeclaration = DeclarationCore<GlobalVariableReferenceId>;
623
692
  assert_mem_size!(GlobalVariableDeclaration, 80);
624
- simple_declaration!(InstanceVariableDeclaration, InstanceVariableReferenceId);
693
+
694
+ pub type InstanceVariableDeclaration = DeclarationCore<InstanceVariableReferenceId>;
625
695
  assert_mem_size!(InstanceVariableDeclaration, 80);
626
- simple_declaration!(ClassVariableDeclaration, ClassVariableReferenceId);
696
+
697
+ pub type ClassVariableDeclaration = DeclarationCore<ClassVariableReferenceId>;
627
698
  assert_mem_size!(ClassVariableDeclaration, 80);
628
- simple_declaration!(ConstantAliasDeclaration, ConstantReferenceId);
699
+
700
+ pub type ConstantAliasDeclaration = DeclarationCore<ConstantReferenceId>;
629
701
  assert_mem_size!(ConstantAliasDeclaration, 80);
630
702
 
631
703
  #[cfg(test)]
@@ -655,15 +727,15 @@ mod tests {
655
727
  let member_name_id = StringId::from("Bar");
656
728
  let member_decl_id = DeclarationId::from("Foo::Bar");
657
729
 
658
- let Declaration::Namespace(Namespace::Class(mut class)) = decl else {
659
- panic!("Expected a class declaration");
730
+ let Declaration::Namespace(mut namespace) = decl else {
731
+ panic!("Expected a namespace declaration");
660
732
  };
661
- class.add_member(member_name_id, member_decl_id);
662
- assert_eq!(class.members.len(), 1);
733
+ namespace.add_member(member_name_id, member_decl_id);
734
+ assert_eq!(namespace.members().len(), 1);
663
735
 
664
- let removed = class.remove_member(&member_name_id);
736
+ let removed = namespace.remove_member(&member_name_id);
665
737
  assert_eq!(removed, Some(member_decl_id));
666
- assert_eq!(class.members.len(), 0);
738
+ assert_eq!(namespace.members().len(), 0);
667
739
  }
668
740
 
669
741
  #[test]