Skip to content

Commit f71cd5b

Browse files
committed
Automatically promote constants to namespaces
1 parent d204b1c commit f71cd5b

3 files changed

Lines changed: 311 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
@@ -76,8 +76,32 @@ impl Graph {
7676
where
7777
F: FnOnce() -> Declaration,
7878
{
79-
let declaration = self.declarations.entry(declaration_id).or_insert_with(constructor);
80-
declaration.add_definition(definition_id);
79+
match self.declarations.entry(declaration_id) {
80+
Entry::Occupied(mut occupied_entry) => {
81+
// If we already have a declaration created, we need to check if it needs to be promoted. For example,
82+
// if we thought this declaration was a constant due to meta-programming and then it gets re-opened with
83+
// the `class` keyword, then we must promote it to a class
84+
if matches!(occupied_entry.get(), Declaration::Constant(_))
85+
&& matches!(
86+
self.definitions.get(&definition_id).unwrap(),
87+
Definition::Class(_) | Definition::Module(_) | Definition::SingletonClass(_)
88+
)
89+
{
90+
let mut new_declaration = constructor();
91+
let removed_declaration = occupied_entry.remove();
92+
new_declaration.as_namespace_mut().unwrap().extend(removed_declaration);
93+
new_declaration.add_definition(definition_id);
94+
self.declarations.insert(declaration_id, new_declaration);
95+
} else {
96+
occupied_entry.get_mut().add_definition(definition_id);
97+
}
98+
}
99+
Entry::Vacant(vacant_entry) => {
100+
let mut declaration = constructor();
101+
declaration.add_definition(definition_id);
102+
vacant_entry.insert(declaration);
103+
}
104+
}
81105
}
82106

83107
/// # Panics
@@ -468,9 +492,6 @@ impl Graph {
468492
Declaration::Namespace(Namespace::SingletonClass(it)) => {
469493
it.add_member(member_str_id, member_declaration_id);
470494
}
471-
Declaration::Constant(_) => {
472-
// TODO: temporary hack to avoid crashing on `Struct.new`, `Class.new` and `Module.new`
473-
}
474495
_ => panic!("Tried to add member to a declaration that isn't a namespace"),
475496
}
476497
}

0 commit comments

Comments
 (0)