@@ -211,7 +211,6 @@ impl<'a> Resolver<'a> {
211211 }
212212 Outcome :: Unresolved ( None ) => {
213213 // We couldn't resolve this name. Emit a diagnostic
214- self . unit_queue . push_back ( unit_id) ;
215214 }
216215 Outcome :: Retry ( Some ( id_needing_linearization) ) | Outcome :: Unresolved ( Some ( id_needing_linearization) ) => {
217216 self . unit_queue . push_back ( unit_id) ;
@@ -1090,14 +1089,13 @@ impl<'a> Resolver<'a> {
10901089
10911090 let declaration_id = DeclarationId :: from ( & fully_qualified_name) ;
10921091
1093- if !self . graph . declarations ( ) . contains_key ( & declaration_id) {
1094- self . graph . declarations_mut ( ) . insert (
1095- declaration_id,
1096- Declaration :: Namespace ( Namespace :: Todo ( Box :: new ( TodoDeclaration :: new (
1097- fully_qualified_name,
1098- parent_owner_id,
1099- ) ) ) ) ,
1100- ) ;
1092+ if let std:: collections:: hash_map:: Entry :: Vacant ( e) =
1093+ self . graph . declarations_mut ( ) . entry ( declaration_id)
1094+ {
1095+ e. insert ( Declaration :: Namespace ( Namespace :: Todo ( Box :: new ( TodoDeclaration :: new (
1096+ fully_qualified_name,
1097+ parent_owner_id,
1098+ ) ) ) ) ) ;
11011099 self . graph . add_member ( & parent_owner_id, declaration_id, parent_str_id) ;
11021100 }
11031101
@@ -5332,4 +5330,88 @@ mod tests {
53325330 assert_members_eq ! ( context, "Foo::Bar" , vec![ "bar()" ] ) ;
53335331 assert_members_eq ! ( context, "Foo::Baz" , vec![ "baz()" ] ) ;
53345332 }
5333+
5334+ #[ test]
5335+ fn todo_declaration_promoted_to_real_namespace ( ) {
5336+ let mut context = GraphTest :: new ( ) ;
5337+ context. index_uri ( "file:///foo.rb" , {
5338+ r"
5339+ class Foo::Bar
5340+ def bar; end
5341+ end
5342+
5343+ class Foo
5344+ def foo; end
5345+ end
5346+ "
5347+ } ) ;
5348+ context. resolve ( ) ;
5349+
5350+ assert_no_diagnostics ! ( & context) ;
5351+
5352+ // Foo was initially created as a Todo (from class Foo::Bar), then promoted to Class
5353+ assert_declaration_kind_eq ! ( context, "Foo" , "Class" ) ;
5354+
5355+ assert_members_eq ! ( context, "Object" , vec![ "Foo" ] ) ;
5356+ assert_members_eq ! ( context, "Foo" , vec![ "Bar" , "foo()" ] ) ;
5357+ assert_members_eq ! ( context, "Foo::Bar" , vec![ "bar()" ] ) ;
5358+ }
5359+
5360+ #[ test]
5361+ fn todo_declaration_promoted_to_real_namespace_incrementally ( ) {
5362+ let mut context = GraphTest :: new ( ) ;
5363+ context. index_uri ( "file:///bar.rb" , {
5364+ r"
5365+ class Foo::Bar
5366+ def bar; end
5367+ end
5368+ "
5369+ } ) ;
5370+ context. resolve ( ) ;
5371+
5372+ assert_no_diagnostics ! ( & context) ;
5373+ assert_declaration_kind_eq ! ( context, "Foo" , "<TODO>" ) ;
5374+
5375+ context. index_uri ( "file:///foo.rb" , {
5376+ r"
5377+ class Foo
5378+ def foo; end
5379+ end
5380+ "
5381+ } ) ;
5382+ context. resolve ( ) ;
5383+
5384+ assert_no_diagnostics ! ( & context) ;
5385+
5386+ // Foo was promoted from Todo to Class after the second resolution
5387+ assert_declaration_kind_eq ! ( context, "Foo" , "Class" ) ;
5388+
5389+ assert_members_eq ! ( context, "Object" , vec![ "Foo" ] ) ;
5390+ assert_members_eq ! ( context, "Foo" , vec![ "Bar" , "foo()" ] ) ;
5391+ assert_members_eq ! ( context, "Foo::Bar" , vec![ "bar()" ] ) ;
5392+ }
5393+
5394+ #[ test]
5395+ fn qualified_name_inside_nesting_resolves_to_top_level ( ) {
5396+ let mut context = GraphTest :: new ( ) ;
5397+ context. index_uri ( "file:///foo.rb" , {
5398+ r"
5399+ module Foo
5400+ class Bar::Baz
5401+ def qux; end
5402+ end
5403+ end
5404+
5405+ module Bar
5406+ end
5407+ "
5408+ } ) ;
5409+ context. resolve ( ) ;
5410+
5411+ assert_no_diagnostics ! ( & context) ;
5412+ assert_declaration_kind_eq ! ( context, "Bar" , "Module" ) ;
5413+ assert_members_eq ! ( context, "Bar" , vec![ "Baz" ] ) ;
5414+ assert_declaration_exists ! ( context, "Bar::Baz" ) ;
5415+ assert_declaration_does_not_exist ! ( context, "Foo::Bar" ) ;
5416+ }
53355417}
0 commit comments