@@ -7,7 +7,7 @@ use cfg::{CfgExpr, CfgOptions};
7
7
use either:: Either ;
8
8
use hir_expand:: { hygiene:: Hygiene , name:: AsName , HirFileId , InFile } ;
9
9
use itertools:: Itertools ;
10
- use la_arena:: ArenaMap ;
10
+ use la_arena:: { ArenaMap , Idx , RawIdx } ;
11
11
use mbe:: { syntax_node_to_token_tree, DelimiterKind , Punct } ;
12
12
use smallvec:: { smallvec, SmallVec } ;
13
13
use syntax:: {
@@ -19,12 +19,12 @@ use tt::Subtree;
19
19
use crate :: {
20
20
db:: DefDatabase ,
21
21
intern:: Interned ,
22
- item_tree:: { ItemTreeId , ItemTreeNode } ,
23
- nameres:: ModuleSource ,
22
+ item_tree:: { AttrOwner , Fields , ItemTreeId , ItemTreeNode } ,
23
+ nameres:: { ModuleOrigin , ModuleSource } ,
24
24
path:: { ModPath , PathKind } ,
25
25
src:: { HasChildSource , HasSource } ,
26
- AdtId , AttrDefId , EnumId , GenericParamId , HasModule , LocalEnumVariantId , LocalFieldId , Lookup ,
27
- MacroId , VariantId ,
26
+ AdtId , AttrDefId , EnumId , GenericParamId , LocalEnumVariantId , LocalFieldId , Lookup , MacroId ,
27
+ VariantId ,
28
28
} ;
29
29
30
30
/// Holds documentation
@@ -201,15 +201,23 @@ impl Attrs {
201
201
db : & dyn DefDatabase ,
202
202
e : EnumId ,
203
203
) -> Arc < ArenaMap < LocalEnumVariantId , Attrs > > {
204
- let krate = e. lookup ( db) . container . krate ;
205
- let src = e. child_source ( db) ;
204
+ // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
206
205
let mut res = ArenaMap :: default ( ) ;
207
206
208
- for ( id, var) in src. value . iter ( ) {
209
- let attrs = RawAttrs :: from_attrs_owner ( db, src. with_value ( var as & dyn ast:: HasAttrs ) )
210
- . filter ( db, krate) ;
211
-
212
- res. insert ( id, attrs)
207
+ let loc = e. lookup ( db) ;
208
+ let krate = loc. container . krate ;
209
+ let item_tree = loc. id . item_tree ( db) ;
210
+ let enum_ = & item_tree[ loc. id . value ] ;
211
+ let crate_graph = db. crate_graph ( ) ;
212
+ let cfg_options = & crate_graph[ krate] . cfg_options ;
213
+
214
+ let mut idx = 0 ;
215
+ for variant in enum_. variants . clone ( ) {
216
+ let attrs = item_tree. attrs ( db, krate, variant. into ( ) ) ;
217
+ if attrs. is_cfg_enabled ( cfg_options) {
218
+ res. insert ( Idx :: from_raw ( RawIdx :: from ( idx) ) , attrs) ;
219
+ idx += 1 ;
220
+ }
213
221
}
214
222
215
223
Arc :: new ( res)
@@ -219,18 +227,64 @@ impl Attrs {
219
227
db : & dyn DefDatabase ,
220
228
v : VariantId ,
221
229
) -> Arc < ArenaMap < LocalFieldId , Attrs > > {
222
- let krate = v. module ( db) . krate ;
223
- let src = v. child_source ( db) ;
230
+ // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
224
231
let mut res = ArenaMap :: default ( ) ;
225
232
226
- for ( id, fld) in src. value . iter ( ) {
227
- let owner: & dyn HasAttrs = match fld {
228
- Either :: Left ( tuple) => tuple,
229
- Either :: Right ( record) => record,
230
- } ;
231
- let attrs = RawAttrs :: from_attrs_owner ( db, src. with_value ( owner) ) . filter ( db, krate) ;
233
+ let crate_graph = db. crate_graph ( ) ;
234
+ let ( fields, item_tree, krate) = match v {
235
+ VariantId :: EnumVariantId ( it) => {
236
+ let e = it. parent ;
237
+ let loc = e. lookup ( db) ;
238
+ let krate = loc. container . krate ;
239
+ let item_tree = loc. id . item_tree ( db) ;
240
+ let enum_ = & item_tree[ loc. id . value ] ;
241
+
242
+ let cfg_options = & crate_graph[ krate] . cfg_options ;
243
+ let variant = ' tri: loop {
244
+ let mut idx = 0 ;
245
+ for variant in enum_. variants . clone ( ) {
246
+ let attrs = item_tree. attrs ( db, krate, variant. into ( ) ) ;
247
+ if attrs. is_cfg_enabled ( cfg_options) {
248
+ if it. local_id == Idx :: from_raw ( RawIdx :: from ( idx) ) {
249
+ break ' tri variant;
250
+ }
251
+ idx += 1 ;
252
+ }
253
+ }
254
+ return Arc :: new ( res) ;
255
+ } ;
256
+ ( item_tree[ variant] . fields . clone ( ) , item_tree, krate)
257
+ }
258
+ VariantId :: StructId ( it) => {
259
+ let loc = it. lookup ( db) ;
260
+ let krate = loc. container . krate ;
261
+ let item_tree = loc. id . item_tree ( db) ;
262
+ let struct_ = & item_tree[ loc. id . value ] ;
263
+ ( struct_. fields . clone ( ) , item_tree, krate)
264
+ }
265
+ VariantId :: UnionId ( it) => {
266
+ let loc = it. lookup ( db) ;
267
+ let krate = loc. container . krate ;
268
+ let item_tree = loc. id . item_tree ( db) ;
269
+ let union_ = & item_tree[ loc. id . value ] ;
270
+ ( union_. fields . clone ( ) , item_tree, krate)
271
+ }
272
+ } ;
232
273
233
- res. insert ( id, attrs) ;
274
+ let fields = match fields {
275
+ Fields :: Record ( fields) | Fields :: Tuple ( fields) => fields,
276
+ Fields :: Unit => return Arc :: new ( res) ,
277
+ } ;
278
+
279
+ let cfg_options = & crate_graph[ krate] . cfg_options ;
280
+
281
+ let mut idx = 0 ;
282
+ for field in fields {
283
+ let attrs = item_tree. attrs ( db, krate, field. into ( ) ) ;
284
+ if attrs. is_cfg_enabled ( cfg_options) {
285
+ res. insert ( Idx :: from_raw ( RawIdx :: from ( idx) ) , attrs) ;
286
+ idx += 1 ;
287
+ }
234
288
}
235
289
236
290
Arc :: new ( res)
@@ -243,11 +297,14 @@ impl Attrs {
243
297
244
298
impl Attrs {
245
299
pub fn cfg ( & self ) -> Option < CfgExpr > {
246
- let mut cfgs = self . by_key ( "cfg" ) . tt_values ( ) . map ( CfgExpr :: parse) . collect :: < Vec < _ > > ( ) ;
247
- match cfgs. len ( ) {
248
- 0 => None ,
249
- 1 => Some ( cfgs. pop ( ) . unwrap ( ) ) ,
250
- _ => Some ( CfgExpr :: All ( cfgs) ) ,
300
+ let mut cfgs = self . by_key ( "cfg" ) . tt_values ( ) . map ( CfgExpr :: parse) ;
301
+ let first = cfgs. next ( ) ?;
302
+ match cfgs. next ( ) {
303
+ Some ( second) => {
304
+ let cfgs = [ first, second] . into_iter ( ) . chain ( cfgs) ;
305
+ Some ( CfgExpr :: All ( cfgs. collect ( ) ) )
306
+ }
307
+ None => Some ( first) ,
251
308
}
252
309
}
253
310
pub ( crate ) fn is_cfg_enabled ( & self , cfg_options : & CfgOptions ) -> bool {
@@ -315,25 +372,30 @@ impl AttrsWithOwner {
315
372
AttrDefId :: ModuleId ( module) => {
316
373
let def_map = module. def_map ( db) ;
317
374
let mod_data = & def_map[ module. local_id ] ;
318
- match mod_data. declaration_source ( db) {
319
- Some ( it) => {
320
- let raw_attrs = RawAttrs :: from_attrs_owner (
321
- db,
322
- it. as_ref ( ) . map ( |it| it as & dyn ast:: HasAttrs ) ,
323
- ) ;
324
- match mod_data. definition_source ( db) {
325
- InFile { file_id, value : ModuleSource :: SourceFile ( file) } => raw_attrs
326
- . merge ( RawAttrs :: from_attrs_owner ( db, InFile :: new ( file_id, & file) ) ) ,
327
- _ => raw_attrs,
328
- }
375
+
376
+ match mod_data. origin {
377
+ ModuleOrigin :: File { definition, declaration_tree_id, .. } => {
378
+ let decl_attrs = declaration_tree_id
379
+ . item_tree ( db)
380
+ . raw_attrs ( AttrOwner :: ModItem ( declaration_tree_id. value . into ( ) ) )
381
+ . clone ( ) ;
382
+ let tree = db. file_item_tree ( definition. into ( ) ) ;
383
+ let def_attrs = tree. raw_attrs ( AttrOwner :: TopLevel ) . clone ( ) ;
384
+ decl_attrs. merge ( def_attrs)
385
+ }
386
+ ModuleOrigin :: CrateRoot { definition } => {
387
+ let tree = db. file_item_tree ( definition. into ( ) ) ;
388
+ tree. raw_attrs ( AttrOwner :: TopLevel ) . clone ( )
329
389
}
330
- None => RawAttrs :: from_attrs_owner (
390
+ ModuleOrigin :: Inline { definition_tree_id, .. } => definition_tree_id
391
+ . item_tree ( db)
392
+ . raw_attrs ( AttrOwner :: ModItem ( definition_tree_id. value . into ( ) ) )
393
+ . clone ( ) ,
394
+ ModuleOrigin :: BlockExpr { block } => RawAttrs :: from_attrs_owner (
331
395
db,
332
- mod_data. definition_source ( db) . as_ref ( ) . map ( |src| match src {
333
- ModuleSource :: SourceFile ( file) => file as & dyn ast:: HasAttrs ,
334
- ModuleSource :: Module ( module) => module as & dyn ast:: HasAttrs ,
335
- ModuleSource :: BlockExpr ( block) => block as & dyn ast:: HasAttrs ,
336
- } ) ,
396
+ InFile :: new ( block. file_id , block. to_node ( db. upcast ( ) ) )
397
+ . as_ref ( )
398
+ . map ( |it| it as & dyn ast:: HasAttrs ) ,
337
399
) ,
338
400
}
339
401
}
0 commit comments