@@ -9,9 +9,13 @@ use chalk_ir::{FloatTy, Safety};
9
9
use itertools:: Itertools ;
10
10
use ra_ap_base_db:: { Crate , RootQueryDb } ;
11
11
use ra_ap_cfg:: CfgAtom ;
12
- use ra_ap_hir:: { DefMap , ModuleDefId , db:: HirDatabase } ;
12
+ use ra_ap_hir:: { DefMap , ModuleDefId , PathKind , db:: HirDatabase } ;
13
13
use 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
+ } ;
15
19
use ra_ap_hir_def:: { HasModule , visibility:: VisibilityExplicitness } ;
16
20
use ra_ap_hir_def:: { ModuleId , resolver:: HasResolver } ;
17
21
use ra_ap_hir_ty:: TraitRefExt ;
@@ -22,6 +26,7 @@ use ra_ap_hir_ty::{Binders, FnPointer};
22
26
use ra_ap_hir_ty:: { Interner , ProjectionTy } ;
23
27
use ra_ap_ide_db:: RootDatabase ;
24
28
use ra_ap_vfs:: { Vfs , VfsPath } ;
29
+
25
30
use std:: hash:: Hasher ;
26
31
use std:: { cmp:: Ordering , collections:: HashMap , path:: PathBuf } ;
27
32
use std:: { hash:: Hash , vec} ;
@@ -172,19 +177,116 @@ fn emit_module_children(
172
177
. collect ( )
173
178
}
174
179
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
+
175
268
fn emit_module_items (
176
269
db : & dyn HirDatabase ,
177
270
module : & ModuleData ,
178
271
trap : & mut TrapFile ,
179
272
) -> Vec < trap:: Label < generated:: Item > > {
180
273
let mut items = Vec :: new ( ) ;
274
+ let mut uses = HashMap :: new ( ) ;
181
275
let item_scope = & module. scope ;
182
276
for ( name, item) in item_scope. entries ( ) {
183
277
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
+ }
184
286
if let Some ( ra_ap_hir_def:: per_ns:: Item {
185
287
def : value,
186
288
vis,
187
- import : _ ,
289
+ import : None ,
188
290
} ) = def. values
189
291
{
190
292
match value {
@@ -203,10 +305,21 @@ fn emit_module_items(
203
305
_ => ( ) ,
204
306
}
205
307
}
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
+ }
206
319
if let Some ( ra_ap_hir_def:: per_ns:: Item {
207
320
def : type_id,
208
321
vis,
209
- import : _ ,
322
+ import : None ,
210
323
} ) = def. types
211
324
{
212
325
match type_id {
@@ -220,6 +333,7 @@ fn emit_module_items(
220
333
}
221
334
}
222
335
}
336
+ items. extend ( uses. values ( ) ) ;
223
337
items
224
338
}
225
339
0 commit comments