@@ -21,7 +21,7 @@ use crate::{
2121 item_tree:: { ItemTreeId , ItemTreeNode } ,
2222 nameres:: ModuleSource ,
2323 path:: { ModPath , PathKind } ,
24- src:: HasChildSource ,
24+ src:: { HasChildSource , HasSource } ,
2525 AdtId , AttrDefId , EnumId , GenericParamId , HasModule , LocalEnumVariantId , LocalFieldId , Lookup ,
2626 VariantId ,
2727} ;
@@ -51,6 +51,12 @@ pub(crate) struct RawAttrs {
5151#[ derive( Default , Debug , Clone , PartialEq , Eq ) ]
5252pub struct Attrs ( RawAttrs ) ;
5353
54+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
55+ pub struct AttrsWithOwner {
56+ attrs : Attrs ,
57+ owner : AttrDefId ,
58+ }
59+
5460impl ops:: Deref for RawAttrs {
5561 type Target = [ Attr ] ;
5662
@@ -73,6 +79,14 @@ impl ops::Deref for Attrs {
7379 }
7480}
7581
82+ impl ops:: Deref for AttrsWithOwner {
83+ type Target = Attrs ;
84+
85+ fn deref ( & self ) -> & Attrs {
86+ & self . attrs
87+ }
88+ }
89+
7690impl RawAttrs {
7791 pub ( crate ) const EMPTY : Self = Self { entries : None } ;
7892
@@ -169,78 +183,6 @@ impl RawAttrs {
169183impl Attrs {
170184 pub const EMPTY : Self = Self ( RawAttrs :: EMPTY ) ;
171185
172- pub ( crate ) fn attrs_query ( db : & dyn DefDatabase , def : AttrDefId ) -> Attrs {
173- let raw_attrs = match def {
174- AttrDefId :: ModuleId ( module) => {
175- let def_map = module. def_map ( db) ;
176- let mod_data = & def_map[ module. local_id ] ;
177- match mod_data. declaration_source ( db) {
178- Some ( it) => {
179- let raw_attrs = RawAttrs :: from_attrs_owner (
180- db,
181- it. as_ref ( ) . map ( |it| it as & dyn ast:: AttrsOwner ) ,
182- ) ;
183- match mod_data. definition_source ( db) {
184- InFile { file_id, value : ModuleSource :: SourceFile ( file) } => raw_attrs
185- . merge ( RawAttrs :: from_attrs_owner ( db, InFile :: new ( file_id, & file) ) ) ,
186- _ => raw_attrs,
187- }
188- }
189- None => RawAttrs :: from_attrs_owner (
190- db,
191- mod_data. definition_source ( db) . as_ref ( ) . map ( |src| match src {
192- ModuleSource :: SourceFile ( file) => file as & dyn ast:: AttrsOwner ,
193- ModuleSource :: Module ( module) => module as & dyn ast:: AttrsOwner ,
194- ModuleSource :: BlockExpr ( block) => block as & dyn ast:: AttrsOwner ,
195- } ) ,
196- ) ,
197- }
198- }
199- AttrDefId :: FieldId ( it) => {
200- return db. fields_attrs ( it. parent ) [ it. local_id ] . clone ( ) ;
201- }
202- AttrDefId :: EnumVariantId ( it) => {
203- return db. variants_attrs ( it. parent ) [ it. local_id ] . clone ( ) ;
204- }
205- AttrDefId :: AdtId ( it) => match it {
206- AdtId :: StructId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
207- AdtId :: EnumId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
208- AdtId :: UnionId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
209- } ,
210- AttrDefId :: TraitId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
211- AttrDefId :: MacroDefId ( it) => it
212- . ast_id ( )
213- . left ( )
214- . map_or_else ( Default :: default, |ast_id| attrs_from_ast ( ast_id, db) ) ,
215- AttrDefId :: ImplId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
216- AttrDefId :: ConstId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
217- AttrDefId :: StaticId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
218- AttrDefId :: FunctionId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
219- AttrDefId :: TypeAliasId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
220- AttrDefId :: GenericParamId ( it) => match it {
221- GenericParamId :: TypeParamId ( it) => {
222- let src = it. parent . child_source ( db) ;
223- RawAttrs :: from_attrs_owner (
224- db,
225- src. with_value (
226- src. value [ it. local_id ] . as_ref ( ) . either ( |it| it as _ , |it| it as _ ) ,
227- ) ,
228- )
229- }
230- GenericParamId :: LifetimeParamId ( it) => {
231- let src = it. parent . child_source ( db) ;
232- RawAttrs :: from_attrs_owner ( db, src. with_value ( & src. value [ it. local_id ] ) )
233- }
234- GenericParamId :: ConstParamId ( it) => {
235- let src = it. parent . child_source ( db) ;
236- RawAttrs :: from_attrs_owner ( db, src. with_value ( & src. value [ it. local_id ] ) )
237- }
238- } ,
239- } ;
240-
241- raw_attrs. filter ( db, def. krate ( db) )
242- }
243-
244186 pub ( crate ) fn variants_attrs_query (
245187 db : & dyn DefDatabase ,
246188 e : EnumId ,
@@ -281,56 +223,6 @@ impl Attrs {
281223 Arc :: new ( res)
282224 }
283225
284- /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes.
285- ///
286- /// `owner` must be the original owner of the attributes.
287- // FIXME: figure out a better api that doesnt require the for_module hack
288- pub fn source_map ( & self , owner : InFile < & dyn ast:: AttrsOwner > ) -> AttrSourceMap {
289- // FIXME: This doesn't work correctly for modules, as the attributes there can have up to
290- // two different owners
291- AttrSourceMap {
292- attrs : collect_attrs ( owner. value )
293- . map ( |attr| InFile :: new ( owner. file_id , attr) )
294- . collect ( ) ,
295- }
296- }
297-
298- pub fn source_map_for_module (
299- & self ,
300- db : & dyn DefDatabase ,
301- module : crate :: ModuleId ,
302- ) -> AttrSourceMap {
303- let def_map = module. def_map ( db) ;
304- let mod_data = & def_map[ module. local_id ] ;
305- let attrs = match mod_data. declaration_source ( db) {
306- Some ( it) => {
307- let mut attrs: Vec < _ > = collect_attrs ( & it. value as & dyn ast:: AttrsOwner )
308- . map ( |attr| InFile :: new ( it. file_id , attr) )
309- . collect ( ) ;
310- if let InFile { file_id, value : ModuleSource :: SourceFile ( file) } =
311- mod_data. definition_source ( db)
312- {
313- attrs. extend (
314- collect_attrs ( & file as & dyn ast:: AttrsOwner )
315- . map ( |attr| InFile :: new ( file_id, attr) ) ,
316- )
317- }
318- attrs
319- }
320- None => {
321- let InFile { file_id, value } = mod_data. definition_source ( db) ;
322- match & value {
323- ModuleSource :: SourceFile ( file) => collect_attrs ( file as & dyn ast:: AttrsOwner ) ,
324- ModuleSource :: Module ( module) => collect_attrs ( module as & dyn ast:: AttrsOwner ) ,
325- ModuleSource :: BlockExpr ( block) => collect_attrs ( block as & dyn ast:: AttrsOwner ) ,
326- }
327- . map ( |attr| InFile :: new ( file_id, attr) )
328- . collect ( )
329- }
330- } ;
331- AttrSourceMap { attrs }
332- }
333-
334226 pub fn by_key ( & self , key : & ' static str ) -> AttrQuery < ' _ > {
335227 AttrQuery { attrs : self , key }
336228 }
@@ -387,6 +279,180 @@ impl Attrs {
387279 }
388280}
389281
282+ impl AttrsWithOwner {
283+ pub ( crate ) fn attrs_query ( db : & dyn DefDatabase , def : AttrDefId ) -> Self {
284+ // FIXME: this should use `Trace` to avoid duplication in `source_map` below
285+ let raw_attrs = match def {
286+ AttrDefId :: ModuleId ( module) => {
287+ let def_map = module. def_map ( db) ;
288+ let mod_data = & def_map[ module. local_id ] ;
289+ match mod_data. declaration_source ( db) {
290+ Some ( it) => {
291+ let raw_attrs = RawAttrs :: from_attrs_owner (
292+ db,
293+ it. as_ref ( ) . map ( |it| it as & dyn ast:: AttrsOwner ) ,
294+ ) ;
295+ match mod_data. definition_source ( db) {
296+ InFile { file_id, value : ModuleSource :: SourceFile ( file) } => raw_attrs
297+ . merge ( RawAttrs :: from_attrs_owner ( db, InFile :: new ( file_id, & file) ) ) ,
298+ _ => raw_attrs,
299+ }
300+ }
301+ None => RawAttrs :: from_attrs_owner (
302+ db,
303+ mod_data. definition_source ( db) . as_ref ( ) . map ( |src| match src {
304+ ModuleSource :: SourceFile ( file) => file as & dyn ast:: AttrsOwner ,
305+ ModuleSource :: Module ( module) => module as & dyn ast:: AttrsOwner ,
306+ ModuleSource :: BlockExpr ( block) => block as & dyn ast:: AttrsOwner ,
307+ } ) ,
308+ ) ,
309+ }
310+ }
311+ AttrDefId :: FieldId ( it) => {
312+ return Self { attrs : db. fields_attrs ( it. parent ) [ it. local_id ] . clone ( ) , owner : def } ;
313+ }
314+ AttrDefId :: EnumVariantId ( it) => {
315+ return Self {
316+ attrs : db. variants_attrs ( it. parent ) [ it. local_id ] . clone ( ) ,
317+ owner : def,
318+ } ;
319+ }
320+ AttrDefId :: AdtId ( it) => match it {
321+ AdtId :: StructId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
322+ AdtId :: EnumId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
323+ AdtId :: UnionId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
324+ } ,
325+ AttrDefId :: TraitId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
326+ AttrDefId :: MacroDefId ( it) => it
327+ . ast_id ( )
328+ . left ( )
329+ . map_or_else ( Default :: default, |ast_id| attrs_from_ast ( ast_id, db) ) ,
330+ AttrDefId :: ImplId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
331+ AttrDefId :: ConstId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
332+ AttrDefId :: StaticId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
333+ AttrDefId :: FunctionId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
334+ AttrDefId :: TypeAliasId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
335+ AttrDefId :: GenericParamId ( it) => match it {
336+ GenericParamId :: TypeParamId ( it) => {
337+ let src = it. parent . child_source ( db) ;
338+ RawAttrs :: from_attrs_owner (
339+ db,
340+ src. with_value (
341+ src. value [ it. local_id ] . as_ref ( ) . either ( |it| it as _ , |it| it as _ ) ,
342+ ) ,
343+ )
344+ }
345+ GenericParamId :: LifetimeParamId ( it) => {
346+ let src = it. parent . child_source ( db) ;
347+ RawAttrs :: from_attrs_owner ( db, src. with_value ( & src. value [ it. local_id ] ) )
348+ }
349+ GenericParamId :: ConstParamId ( it) => {
350+ let src = it. parent . child_source ( db) ;
351+ RawAttrs :: from_attrs_owner ( db, src. with_value ( & src. value [ it. local_id ] ) )
352+ }
353+ } ,
354+ } ;
355+
356+ let attrs = raw_attrs. filter ( db, def. krate ( db) ) ;
357+ Self { attrs, owner : def }
358+ }
359+
360+ pub fn source_map ( & self , db : & dyn DefDatabase ) -> AttrSourceMap {
361+ let owner = match self . owner {
362+ AttrDefId :: ModuleId ( module) => {
363+ // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself).
364+
365+ let def_map = module. def_map ( db) ;
366+ let mod_data = & def_map[ module. local_id ] ;
367+ let attrs = match mod_data. declaration_source ( db) {
368+ Some ( it) => {
369+ let mut attrs: Vec < _ > = collect_attrs ( & it. value as & dyn ast:: AttrsOwner )
370+ . map ( |attr| InFile :: new ( it. file_id , attr) )
371+ . collect ( ) ;
372+ if let InFile { file_id, value : ModuleSource :: SourceFile ( file) } =
373+ mod_data. definition_source ( db)
374+ {
375+ attrs. extend (
376+ collect_attrs ( & file as & dyn ast:: AttrsOwner )
377+ . map ( |attr| InFile :: new ( file_id, attr) ) ,
378+ )
379+ }
380+ attrs
381+ }
382+ None => {
383+ let InFile { file_id, value } = mod_data. definition_source ( db) ;
384+ match & value {
385+ ModuleSource :: SourceFile ( file) => {
386+ collect_attrs ( file as & dyn ast:: AttrsOwner )
387+ }
388+ ModuleSource :: Module ( module) => {
389+ collect_attrs ( module as & dyn ast:: AttrsOwner )
390+ }
391+ ModuleSource :: BlockExpr ( block) => {
392+ collect_attrs ( block as & dyn ast:: AttrsOwner )
393+ }
394+ }
395+ . map ( |attr| InFile :: new ( file_id, attr) )
396+ . collect ( )
397+ }
398+ } ;
399+ return AttrSourceMap { attrs } ;
400+ }
401+ AttrDefId :: FieldId ( id) => {
402+ id. parent . child_source ( db) . map ( |source| match & source[ id. local_id ] {
403+ Either :: Left ( field) => ast:: AttrsOwnerNode :: new ( field. clone ( ) ) ,
404+ Either :: Right ( field) => ast:: AttrsOwnerNode :: new ( field. clone ( ) ) ,
405+ } )
406+ }
407+ AttrDefId :: AdtId ( adt) => match adt {
408+ AdtId :: StructId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
409+ AdtId :: UnionId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
410+ AdtId :: EnumId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
411+ } ,
412+ AttrDefId :: FunctionId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
413+ AttrDefId :: EnumVariantId ( id) => id
414+ . parent
415+ . child_source ( db)
416+ . map ( |source| ast:: AttrsOwnerNode :: new ( source[ id. local_id ] . clone ( ) ) ) ,
417+ AttrDefId :: StaticId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
418+ AttrDefId :: ConstId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
419+ AttrDefId :: TraitId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
420+ AttrDefId :: TypeAliasId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
421+ AttrDefId :: MacroDefId ( id) => match id. ast_id ( ) {
422+ Either :: Left ( it) => {
423+ it. with_value ( ast:: AttrsOwnerNode :: new ( it. to_node ( db. upcast ( ) ) ) )
424+ }
425+ Either :: Right ( it) => {
426+ it. with_value ( ast:: AttrsOwnerNode :: new ( it. to_node ( db. upcast ( ) ) ) )
427+ }
428+ } ,
429+ AttrDefId :: ImplId ( id) => id. lookup ( db) . source ( db) . map ( ast:: AttrsOwnerNode :: new) ,
430+ AttrDefId :: GenericParamId ( id) => match id {
431+ GenericParamId :: TypeParamId ( id) => {
432+ id. parent . child_source ( db) . map ( |source| match & source[ id. local_id ] {
433+ Either :: Left ( id) => ast:: AttrsOwnerNode :: new ( id. clone ( ) ) ,
434+ Either :: Right ( id) => ast:: AttrsOwnerNode :: new ( id. clone ( ) ) ,
435+ } )
436+ }
437+ GenericParamId :: LifetimeParamId ( id) => id
438+ . parent
439+ . child_source ( db)
440+ . map ( |source| ast:: AttrsOwnerNode :: new ( source[ id. local_id ] . clone ( ) ) ) ,
441+ GenericParamId :: ConstParamId ( id) => id
442+ . parent
443+ . child_source ( db)
444+ . map ( |source| ast:: AttrsOwnerNode :: new ( source[ id. local_id ] . clone ( ) ) ) ,
445+ } ,
446+ } ;
447+
448+ AttrSourceMap {
449+ attrs : collect_attrs ( & owner. value )
450+ . map ( |attr| InFile :: new ( owner. file_id , attr) )
451+ . collect ( ) ,
452+ }
453+ }
454+ }
455+
390456fn inner_attributes (
391457 syntax : & SyntaxNode ,
392458) -> Option < ( impl Iterator < Item = ast:: Attr > , impl Iterator < Item = ast:: Comment > ) > {
0 commit comments