@@ -4,7 +4,7 @@ use crate::model::declaration::Declaration;
44use crate :: model:: definitions:: Definition ;
55use crate :: model:: document:: Document ;
66use crate :: model:: identity_maps:: IdentityHashMap ;
7- use crate :: model:: ids:: { DeclarationId , DefinitionId , NameId , UriId } ;
7+ use crate :: model:: ids:: { DeclarationId , DefinitionId , NameId , ReferenceId , UriId } ;
88use crate :: model:: integrity:: IntegrityChecker ;
99use crate :: model:: references:: { ResolvedReference , UnresolvedReference } ;
1010use crate :: stats;
@@ -28,8 +28,8 @@ pub struct Graph {
2828 definitions : IdentityHashMap < DefinitionId , Definition > ,
2929 // Map of unqualified names
3030 names : IdentityHashMap < NameId , String > ,
31- // List of references that still need to be resolved
32- unresolved_references : Vec < UnresolvedReference > ,
31+ // Map of references that still need to be resolved
32+ unresolved_references : IdentityHashMap < ReferenceId , UnresolvedReference > ,
3333 db : Db ,
3434}
3535
@@ -47,7 +47,7 @@ impl Graph {
4747 definitions : IdentityHashMap :: default ( ) ,
4848 documents : IdentityHashMap :: default ( ) ,
4949 names : IdentityHashMap :: default ( ) ,
50- unresolved_references : Vec :: new ( ) ,
50+ unresolved_references : IdentityHashMap :: default ( ) ,
5151 db : Db :: new ( ) ,
5252 }
5353 }
@@ -76,9 +76,9 @@ impl Graph {
7676 & self . documents
7777 }
7878
79- // Returns an immutable reference to the list of unresolved references
79+ // Returns an immutable reference to the unresolved references map
8080 #[ must_use]
81- pub fn unresolved_references ( & self ) -> & Vec < UnresolvedReference > {
81+ pub fn unresolved_references ( & self ) -> & IdentityHashMap < ReferenceId , UnresolvedReference > {
8282 & self . unresolved_references
8383 }
8484
@@ -182,8 +182,10 @@ impl Graph {
182182 }
183183
184184 // Register an unresolved reference to something (e.g.: constant, method, variable), which has to be resolved later
185- pub fn add_unresolved_reference ( & mut self , reference : UnresolvedReference ) {
186- self . unresolved_references . push ( reference) ;
185+ pub fn add_unresolved_reference ( & mut self , reference : UnresolvedReference ) -> ReferenceId {
186+ let reference_id = reference. id ( ) ;
187+ self . unresolved_references . insert ( reference_id, reference) ;
188+ reference_id
187189 }
188190
189191 /// Attempts to resolve a reference against the graph. Returns the fully qualified declaration ID that the reference
@@ -469,7 +471,7 @@ impl Graph {
469471 self . definitions = IdentityHashMap :: default ( ) ;
470472 self . documents = IdentityHashMap :: default ( ) ;
471473 self . names = IdentityHashMap :: default ( ) ;
472- self . unresolved_references = Vec :: new ( ) ;
474+ self . unresolved_references = IdentityHashMap :: default ( ) ;
473475 }
474476
475477 #[ allow( clippy:: cast_precision_loss) ]
@@ -539,7 +541,7 @@ impl Graph {
539541 pub fn resolve_references ( & mut self ) {
540542 let unresolved = std:: mem:: take ( & mut self . unresolved_references ) ;
541543
542- for reference in unresolved {
544+ for ( id , reference) in unresolved {
543545 match & reference {
544546 UnresolvedReference :: Constant ( _) => {
545547 if let Some ( declaration) = self . resolve_reference ( & reference) {
@@ -562,12 +564,12 @@ impl Graph {
562564 }
563565 } else {
564566 // Keep unresolved references
565- self . unresolved_references . push ( reference) ;
567+ self . unresolved_references . insert ( id , reference) ;
566568 }
567569 }
568570 UnresolvedReference :: Method ( _) => {
569571 // TODO: Implement method reference resolution
570- self . unresolved_references . push ( reference) ;
572+ self . unresolved_references . insert ( id , reference) ;
571573 }
572574 }
573575 }
@@ -594,7 +596,7 @@ impl Graph {
594596 // Count unresolved references by type
595597 let mut unresolved_constants = 0 ;
596598 let mut unresolved_methods = 0 ;
597- for reference in & self . unresolved_references {
599+ for reference in self . unresolved_references . values ( ) {
598600 match reference {
599601 UnresolvedReference :: Constant ( _) => unresolved_constants += 1 ,
600602 UnresolvedReference :: Method ( _) => unresolved_methods += 1 ,
@@ -705,7 +707,7 @@ mod tests {
705707 let constant = $context
706708 . graph
707709 . unresolved_references
708- . iter ( )
710+ . values ( )
709711 . filter_map( |r| {
710712 if let UnresolvedReference :: Constant ( c) = r {
711713 Some ( c)
@@ -975,6 +977,14 @@ mod tests {
975977 fn resolving_constants ( ) {
976978 let mut context = GraphTest :: new ( ) ;
977979
980+ context. index_uri ( "file:///bar.rb" , {
981+ r"
982+ class Bar
983+ ::Foo::Bar # should be resolved to Foo::Bar from file:///foo.rb
984+ end
985+ "
986+ } ) ;
987+
978988 context. index_uri ( "file:///foo.rb" , {
979989 r"
980990 module Foo
@@ -992,12 +1002,31 @@ mod tests {
9921002 "
9931003 } ) ;
9941004
995- context. index_uri ( "file:///bar.rb" , {
996- r"
997- class Bar
998- ::Foo::Bar # should be resolved to Foo::Bar from file:///foo.rb
999- end
1000- "
1005+ let mut unresolved_references = context. graph . unresolved_references ( ) . values ( ) . collect :: < Vec < _ > > ( ) ;
1006+
1007+ unresolved_references. sort_by_key ( |r| match r {
1008+ UnresolvedReference :: Constant ( constant) => (
1009+ context
1010+ . graph
1011+ . documents ( )
1012+ . get ( & constant. uri_id ( ) )
1013+ . unwrap ( )
1014+ . uri ( )
1015+ . to_string ( ) ,
1016+ constant. offset ( ) . start ( ) ,
1017+ constant. offset ( ) . end ( ) ,
1018+ ) ,
1019+ UnresolvedReference :: Method ( method) => (
1020+ context
1021+ . graph
1022+ . documents ( )
1023+ . get ( & method. uri_id ( ) )
1024+ . unwrap ( )
1025+ . uri ( )
1026+ . to_string ( ) ,
1027+ method. offset ( ) . start ( ) ,
1028+ method. offset ( ) . end ( ) ,
1029+ ) ,
10011030 } ) ;
10021031
10031032 context. graph . resolve_references ( ) ;
0 commit comments