@@ -4,9 +4,9 @@ use rustc_hash::FxHashMap;
44
55use crate :: {
66 code_model:: src:: HasSource ,
7- ids:: { DefWithBodyId , FunctionId , ItemDefinitionId , Lookup , StructId , TypeAliasId } ,
7+ ids:: { DefWithBodyId , FunctionId , ImplId , ItemDefinitionId , Lookup , StructId , TypeAliasId } ,
88 item_scope:: ItemScope ,
9- DefDatabase , HirDatabase , InFile ,
9+ AssocItemId , DefDatabase , HirDatabase , InFile ,
1010} ;
1111
1212pub ( super ) type SourceToDefCache = FxHashMap < SourceToDefContainer , SourceToDefMap > ;
@@ -24,25 +24,33 @@ impl SourceToDefContext<'_, '_> {
2424 & mut self ,
2525 src : InFile < & SyntaxNode > ,
2626 ) -> Option < SourceToDefContainer > {
27- for container in std:: iter:: successors ( Some ( src. cloned ( ) ) , move |node| {
27+ let mut ancestors = std:: iter:: successors ( Some ( src. cloned ( ) ) , move |node| {
2828 node. value . parent ( ) . map ( |parent| node. with_value ( parent) )
2929 } )
30- . skip ( 1 )
31- {
32- let res: SourceToDefContainer = match_ast ! {
33- match ( container. value) {
34- ast:: FunctionDef ( it) => {
35- let def = self . fn_to_def( container. with_value( it) ) ?;
36- DefWithBodyId :: from( def) . into( )
37- } ,
38- _ => continue ,
39- }
40- } ;
41- return Some ( res) ;
42- }
30+ . skip ( 1 ) ;
4331
44- let def = self . file_to_def ( src. file_id ) ?;
45- Some ( def. into ( ) )
32+ ancestors. find_map ( |node| self . container_to_def ( node) )
33+ }
34+
35+ /// Find the container associated with the given ast node.
36+ fn container_to_def ( & mut self , container : InFile < SyntaxNode > ) -> Option < SourceToDefContainer > {
37+ Some ( match_ast ! {
38+ match ( container. value) {
39+ ast:: FunctionDef ( it) => {
40+ let def = self . fn_to_def( container. with_value( it) ) ?;
41+ SourceToDefContainer :: DefWithBodyId ( def. into( ) )
42+ } ,
43+ ast:: Impl ( it) => {
44+ let def = self . impl_to_def( container. with_value( it) ) ?;
45+ SourceToDefContainer :: Impl ( def)
46+ } ,
47+ ast:: SourceFile ( _) => {
48+ let def = self . file_to_def( container. file_id) ?;
49+ SourceToDefContainer :: ModuleId ( def)
50+ } ,
51+ _ => return None ,
52+ }
53+ } )
4654 }
4755
4856 /// Find the `FunctionId` associated with the specified syntax tree node.
@@ -56,22 +64,30 @@ impl SourceToDefContext<'_, '_> {
5664 def_map. functions . get ( & src) . copied ( )
5765 }
5866
67+ /// Find the `ImplId` associated with the specified syntax tree node.
68+ fn impl_to_def ( & mut self , src : InFile < ast:: Impl > ) -> Option < ImplId > {
69+ let container = self . find_container ( src. as_ref ( ) . map ( AstNode :: syntax) ) ?;
70+ let db = self . db ;
71+ let def_map = & * self
72+ . cache
73+ . entry ( container)
74+ . or_insert_with ( || container. source_to_def_map ( db) ) ;
75+ def_map. impls . get ( & src) . copied ( )
76+ }
77+
5978 /// Finds the `ModuleId` associated with the specified `file`
6079 fn file_to_def ( & self , file_id : FileId ) -> Option < ModuleId > {
6180 let source_root_id = self . db . file_source_root ( file_id) ;
6281 let packages = self . db . packages ( ) ;
63- let result = packages
82+ let package_id = packages
6483 . iter ( )
65- . filter ( |package_id| packages[ * package_id] . source_root == source_root_id)
66- . find_map ( |package_id| {
67- let module_tree = self . db . module_tree ( package_id) ;
68- let module_id = module_tree. module_for_file ( file_id) ?;
69- Some ( ModuleId {
70- package : package_id,
71- local_id : module_id,
72- } )
73- } ) ;
74- result
84+ . find ( |package_id| packages[ * package_id] . source_root == source_root_id) ?;
85+ let module_tree = self . db . module_tree ( package_id) ;
86+ let module_id = module_tree. module_for_file ( file_id) ?;
87+ Some ( ModuleId {
88+ package : package_id,
89+ local_id : module_id,
90+ } )
7591 }
7692}
7793
@@ -80,6 +96,7 @@ impl SourceToDefContext<'_, '_> {
8096pub ( crate ) enum SourceToDefContainer {
8197 DefWithBodyId ( DefWithBodyId ) ,
8298 ModuleId ( ModuleId ) ,
99+ Impl ( ImplId ) ,
83100}
84101
85102impl From < DefWithBodyId > for SourceToDefContainer {
@@ -99,6 +116,7 @@ impl SourceToDefContainer {
99116 match self {
100117 SourceToDefContainer :: DefWithBodyId ( id) => id. source_to_def_map ( db) ,
101118 SourceToDefContainer :: ModuleId ( id) => id. source_to_def_map ( db) ,
119+ SourceToDefContainer :: Impl ( id) => id. source_to_def_map ( db) ,
102120 }
103121 }
104122}
@@ -148,6 +166,27 @@ impl SourceToDef for ItemScope {
148166 self . declarations ( )
149167 . for_each ( |item| add_module_def ( db. upcast ( ) , & mut result, item) ) ;
150168
169+ self . impls ( ) . for_each ( |id| {
170+ let src = id. lookup ( db. upcast ( ) ) . source ( db. upcast ( ) ) ;
171+ result. impls . insert ( src, id) ;
172+ } ) ;
173+
174+ result
175+ }
176+ }
177+
178+ impl SourceToDef for ImplId {
179+ fn source_to_def_map ( & self , db : & dyn HirDatabase ) -> SourceToDefMap {
180+ let mut result = SourceToDefMap :: default ( ) ;
181+ let impl_items = db. impl_data ( * self ) ;
182+ for & assoc_item in & impl_items. items {
183+ match assoc_item {
184+ AssocItemId :: FunctionId ( id) => {
185+ let src = id. lookup ( db. upcast ( ) ) . source ( db. upcast ( ) ) ;
186+ result. functions . insert ( src, id) ;
187+ }
188+ }
189+ }
151190 result
152191 }
153192}
@@ -156,6 +195,7 @@ impl SourceToDef for ItemScope {
156195#[ derive( Default ) ]
157196pub ( crate ) struct SourceToDefMap {
158197 functions : FxHashMap < InFile < ast:: FunctionDef > , FunctionId > ,
198+ impls : FxHashMap < InFile < ast:: Impl > , ImplId > ,
159199 structs : FxHashMap < InFile < ast:: StructDef > , StructId > ,
160200 type_aliases : FxHashMap < InFile < ast:: TypeAliasDef > , TypeAliasId > ,
161201}
0 commit comments