@@ -9,9 +9,13 @@ use chalk_ir::{FloatTy, Safety};
99use itertools:: Itertools ;
1010use ra_ap_base_db:: { Crate , RootQueryDb } ;
1111use ra_ap_cfg:: CfgAtom ;
12- use ra_ap_hir:: { DefMap , ModuleDefId , db:: HirDatabase } ;
12+ use ra_ap_hir:: { DefMap , ModuleDefId , PathKind , db:: HirDatabase } ;
1313use ra_ap_hir:: { VariantId , Visibility , db:: DefDatabase } ;
14- use ra_ap_hir_def:: { AssocItemId , LocalModuleId , data:: adt:: VariantData , nameres:: ModuleData } ;
14+ use ra_ap_hir_def:: Lookup ;
15+ use ra_ap_hir_def:: {
16+ AssocItemId , LocalModuleId , data:: adt:: VariantData , item_scope:: ImportOrGlob ,
17+ item_tree:: ImportKind , nameres:: ModuleData , path:: ImportAlias ,
18+ } ;
1519use ra_ap_hir_def:: { HasModule , visibility:: VisibilityExplicitness } ;
1620use ra_ap_hir_def:: { ModuleId , resolver:: HasResolver } ;
1721use ra_ap_hir_ty:: TraitRefExt ;
@@ -22,6 +26,7 @@ use ra_ap_hir_ty::{Binders, FnPointer};
2226use ra_ap_hir_ty:: { Interner , ProjectionTy } ;
2327use ra_ap_ide_db:: RootDatabase ;
2428use ra_ap_vfs:: { Vfs , VfsPath } ;
29+
2530use std:: hash:: Hasher ;
2631use std:: { cmp:: Ordering , collections:: HashMap , path:: PathBuf } ;
2732use std:: { hash:: Hash , vec} ;
@@ -172,19 +177,116 @@ fn emit_module_children(
172177 . collect ( )
173178}
174179
180+ fn emit_reexport (
181+ db : & dyn HirDatabase ,
182+ trap : & mut TrapFile ,
183+ uses : & mut HashMap < String , trap:: Label < generated:: Item > > ,
184+ import : ImportOrGlob ,
185+ name : & str ,
186+ ) {
187+ let ( use_, idx) = match import {
188+ ImportOrGlob :: Glob ( import) => ( import. use_ , import. idx ) ,
189+ ImportOrGlob :: Import ( import) => ( import. use_ , import. idx ) ,
190+ } ;
191+ let def_db = db. upcast ( ) ;
192+ let loc = use_. lookup ( def_db) ;
193+ let use_ = & loc. id . item_tree ( def_db) [ loc. id . value ] ;
194+
195+ use_. use_tree . expand ( |id, path, kind, alias| {
196+ if id == idx {
197+ let mut path_components = Vec :: new ( ) ;
198+ match path. kind {
199+ PathKind :: Plain => ( ) ,
200+ PathKind :: Super ( 0 ) => path_components. push ( "self" . to_owned ( ) ) ,
201+ PathKind :: Super ( n) => {
202+ path_components. extend ( std:: iter:: repeat_n ( "super" . to_owned ( ) , n. into ( ) ) ) ;
203+ }
204+ PathKind :: Crate => path_components. push ( "crate" . to_owned ( ) ) ,
205+ PathKind :: Abs => path_components. push ( "" . to_owned ( ) ) ,
206+ PathKind :: DollarCrate ( crate_id) => {
207+ let crate_extra = crate_id. extra_data ( db) ;
208+ let crate_name = crate_extra
209+ . display_name
210+ . as_ref ( )
211+ . map ( |x| x. canonical_name ( ) . to_string ( ) ) ;
212+ path_components. push ( crate_name. unwrap_or ( "crate" . to_owned ( ) ) ) ;
213+ }
214+ }
215+ path_components. extend ( path. segments ( ) . iter ( ) . map ( |x| x. as_str ( ) . to_owned ( ) ) ) ;
216+ match kind {
217+ ImportKind :: Plain => ( ) ,
218+ ImportKind :: Glob => path_components. push ( name. to_owned ( ) ) ,
219+ ImportKind :: TypeOnly => path_components. push ( "self" . to_owned ( ) ) ,
220+ } ;
221+
222+ let alias = alias. map ( |alias| match alias {
223+ ImportAlias :: Underscore => "_" . to_owned ( ) ,
224+ ImportAlias :: Alias ( name) => name. as_str ( ) . to_owned ( ) ,
225+ } ) ;
226+ let key = format ! (
227+ "{} as {}" ,
228+ path_components. join( "::" ) ,
229+ alias. as_ref( ) . unwrap_or( & "" . to_owned( ) )
230+ ) ;
231+ // prevent duplicate imports
232+ if uses. contains_key ( & key) {
233+ return ;
234+ }
235+ let rename = alias. map ( |name| {
236+ let name = Some ( trap. emit ( generated:: Name {
237+ id : trap:: TrapId :: Star ,
238+ text : Some ( name) ,
239+ } ) ) ;
240+ trap. emit ( generated:: Rename {
241+ id : trap:: TrapId :: Star ,
242+ name,
243+ } )
244+ } ) ;
245+ let path = make_qualified_path ( trap, path_components) ;
246+ let use_tree = trap. emit ( generated:: UseTree {
247+ id : trap:: TrapId :: Star ,
248+ is_glob : false ,
249+ path,
250+ rename,
251+ use_tree_list : None ,
252+ } ) ;
253+ let visibility = emit_visibility ( db, trap, Visibility :: Public ) ;
254+ uses. insert (
255+ key,
256+ trap. emit ( generated:: Use {
257+ id : trap:: TrapId :: Star ,
258+ attrs : vec ! [ ] ,
259+ use_tree : Some ( use_tree) ,
260+ visibility,
261+ } )
262+ . into ( ) ,
263+ ) ;
264+ }
265+ } ) ;
266+ }
267+
175268fn emit_module_items (
176269 db : & dyn HirDatabase ,
177270 module : & ModuleData ,
178271 trap : & mut TrapFile ,
179272) -> Vec < trap:: Label < generated:: Item > > {
180273 let mut items = Vec :: new ( ) ;
274+ let mut uses = HashMap :: new ( ) ;
181275 let item_scope = & module. scope ;
182276 for ( name, item) in item_scope. entries ( ) {
183277 let def = item. filter_visibility ( |x| matches ! ( x, ra_ap_hir:: Visibility :: Public ) ) ;
278+ if let Some ( ra_ap_hir_def:: per_ns:: Item {
279+ def : _,
280+ vis : _,
281+ import : Some ( import) ,
282+ } ) = def. values
283+ {
284+ emit_reexport ( db, trap, & mut uses, import, name. as_str ( ) ) ;
285+ }
184286 if let Some ( ra_ap_hir_def:: per_ns:: Item {
185287 def : value,
186288 vis,
187- import : _ ,
289+ import : None ,
188290 } ) = def. values
189291 {
190292 match value {
@@ -203,10 +305,21 @@ fn emit_module_items(
203305 _ => ( ) ,
204306 }
205307 }
308+ if let Some ( ra_ap_hir_def:: per_ns:: Item {
309+ def : _,
310+ vis : _,
311+ import : Some ( import) ,
312+ } ) = def. types
313+ {
314+ // TODO: handle ExternCrate as well?
315+ if let Some ( import) = import. import_or_glob ( ) {
316+ emit_reexport ( db, trap, & mut uses, import, name. as_str ( ) ) ;
317+ }
318+ }
206319 if let Some ( ra_ap_hir_def:: per_ns:: Item {
207320 def : type_id,
208321 vis,
209- import : _ ,
322+ import : None ,
210323 } ) = def. types
211324 {
212325 match type_id {
@@ -220,6 +333,7 @@ fn emit_module_items(
220333 }
221334 }
222335 }
336+ items. extend ( uses. values ( ) ) ;
223337 items
224338}
225339
0 commit comments