Skip to content

Commit 236f30f

Browse files
committed
Automatically promote constants to namespaces
1 parent 7ff5bbf commit 236f30f

3 files changed

Lines changed: 292 additions & 79 deletions

File tree

rust/rubydex/src/model/declaration.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,14 @@ macro_rules! namespace_declaration {
123123
}
124124
}
125125

126-
pub fn extend(&mut self, mut other: Namespace) {
126+
pub fn extend(&mut self, mut other: Declaration) {
127127
self.definition_ids.extend(other.definitions());
128128
self.references.extend(other.references());
129-
self.members.extend(other.members());
130129
self.diagnostics.extend(other.take_diagnostics());
130+
131+
if let Declaration::Namespace(namespace) = other {
132+
self.members.extend(namespace.members());
133+
}
131134
}
132135

133136
pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
@@ -408,6 +411,10 @@ impl Namespace {
408411
all_namespaces!(self, it => std::mem::take(&mut it.diagnostics))
409412
}
410413

414+
pub fn extend(&mut self, other: Declaration) {
415+
all_namespaces!(self, it => it.extend(other));
416+
}
417+
411418
/// # Panics
412419
///
413420
/// Panics if the declaration is not a namespace or a constant
@@ -468,6 +475,11 @@ impl Namespace {
468475
pub fn set_singleton_class_id(&mut self, declaration_id: DeclarationId) {
469476
all_namespaces!(self, it => it.set_singleton_class_id(declaration_id));
470477
}
478+
479+
#[must_use]
480+
pub fn name(&self) -> &str {
481+
all_namespaces!(self, it => &it.name)
482+
}
471483
}
472484

473485
namespace_declaration!(Class, ClassDeclaration);

rust/rubydex/src/model/graph.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,32 @@ impl Graph {
8181
{
8282
self.definitions_to_declarations.insert(definition_id, declaration_id);
8383

84-
let declaration = self.declarations.entry(declaration_id).or_insert_with(constructor);
85-
declaration.add_definition(definition_id);
84+
match self.declarations.entry(declaration_id) {
85+
Entry::Occupied(mut occupied_entry) => {
86+
// If we already have a declaration created, we need to check if it needs to be promoted. For example,
87+
// if we thought this declaration was a constant due to meta-programming and then it gets re-opened with
88+
// the `class` keyword, then we must promote it to a class
89+
if matches!(occupied_entry.get(), Declaration::Constant(_))
90+
&& matches!(
91+
self.definitions.get(&definition_id).unwrap(),
92+
Definition::Class(_) | Definition::Module(_) | Definition::SingletonClass(_)
93+
)
94+
{
95+
let mut new_declaration = constructor();
96+
let removed_declaration = occupied_entry.remove();
97+
new_declaration.as_namespace_mut().unwrap().extend(removed_declaration);
98+
new_declaration.add_definition(definition_id);
99+
self.declarations.insert(declaration_id, new_declaration);
100+
} else {
101+
occupied_entry.get_mut().add_definition(definition_id);
102+
}
103+
}
104+
Entry::Vacant(vacant_entry) => {
105+
let mut declaration = constructor();
106+
declaration.add_definition(definition_id);
107+
vacant_entry.insert(declaration);
108+
}
109+
}
86110
}
87111

88112
/// # Panics
@@ -382,9 +406,6 @@ impl Graph {
382406
Declaration::Namespace(Namespace::SingletonClass(it)) => {
383407
it.add_member(member_str_id, member_declaration_id);
384408
}
385-
Declaration::Constant(_) => {
386-
// TODO: temporary hack to avoid crashing on `Struct.new`, `Class.new` and `Module.new`
387-
}
388409
_ => panic!("Tried to add member to a declaration that isn't a namespace"),
389410
}
390411
}

0 commit comments

Comments
 (0)