@@ -7,7 +7,7 @@ use cfg::{CfgExpr, CfgOptions};
77use either:: Either ;
88use hir_expand:: { hygiene:: Hygiene , name:: AsName , HirFileId , InFile } ;
99use itertools:: Itertools ;
10- use la_arena:: ArenaMap ;
10+ use la_arena:: { ArenaMap , Idx , RawIdx } ;
1111use mbe:: { syntax_node_to_token_tree, DelimiterKind , Punct } ;
1212use smallvec:: { smallvec, SmallVec } ;
1313use syntax:: {
@@ -19,12 +19,12 @@ use tt::Subtree;
1919use crate :: {
2020 db:: DefDatabase ,
2121 intern:: Interned ,
22- item_tree:: { ItemTreeId , ItemTreeNode } ,
23- nameres:: ModuleSource ,
22+ item_tree:: { AttrOwner , Fields , ItemTreeId , ItemTreeNode } ,
23+ nameres:: { ModuleOrigin , ModuleSource } ,
2424 path:: { ModPath , PathKind } ,
2525 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 ,
2828} ;
2929
3030/// Holds documentation
@@ -201,15 +201,23 @@ impl Attrs {
201201 db : & dyn DefDatabase ,
202202 e : EnumId ,
203203 ) -> 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
206205 let mut res = ArenaMap :: default ( ) ;
207206
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+ }
213221 }
214222
215223 Arc :: new ( res)
@@ -219,18 +227,64 @@ impl Attrs {
219227 db : & dyn DefDatabase ,
220228 v : VariantId ,
221229 ) -> 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
224231 let mut res = ArenaMap :: default ( ) ;
225232
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+ } ;
232273
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+ }
234288 }
235289
236290 Arc :: new ( res)
@@ -243,11 +297,14 @@ impl Attrs {
243297
244298impl Attrs {
245299 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) ,
251308 }
252309 }
253310 pub ( crate ) fn is_cfg_enabled ( & self , cfg_options : & CfgOptions ) -> bool {
@@ -315,25 +372,30 @@ impl AttrsWithOwner {
315372 AttrDefId :: ModuleId ( module) => {
316373 let def_map = module. def_map ( db) ;
317374 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 ( )
329389 }
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 (
331395 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 ) ,
337399 ) ,
338400 }
339401 }
0 commit comments