22
33use std:: { ops, sync:: Arc } ;
44
5+ use base_db:: CrateId ;
56use cfg:: { CfgExpr , CfgOptions } ;
67use either:: Either ;
78use hir_expand:: { hygiene:: Hygiene , AstId , InFile } ;
@@ -38,12 +39,16 @@ impl From<Documentation> for String {
3839 }
3940}
4041
42+ /// Syntactical attributes, without filtering of `cfg_attr`s.
4143#[ derive( Default , Debug , Clone , PartialEq , Eq ) ]
42- pub struct Attrs {
44+ pub struct RawAttrs {
4345 entries : Option < Arc < [ Attr ] > > ,
4446}
4547
46- impl ops:: Deref for Attrs {
48+ #[ derive( Default , Debug , Clone , PartialEq , Eq ) ]
49+ pub struct Attrs ( RawAttrs ) ;
50+
51+ impl ops:: Deref for RawAttrs {
4752 type Target = [ Attr ] ;
4853
4954 fn deref ( & self ) -> & [ Attr ] {
@@ -54,19 +59,88 @@ impl ops::Deref for Attrs {
5459 }
5560}
5661
62+ impl ops:: Deref for Attrs {
63+ type Target = [ Attr ] ;
64+
65+ fn deref ( & self ) -> & [ Attr ] {
66+ match & self . 0 . entries {
67+ Some ( it) => & * it,
68+ None => & [ ] ,
69+ }
70+ }
71+ }
72+
73+ impl RawAttrs {
74+ pub const EMPTY : Self = Self { entries : None } ;
75+
76+ pub ( crate ) fn new ( owner : & dyn AttrsOwner , hygiene : & Hygiene ) -> Self {
77+ let ( inner_attrs, inner_docs) = inner_attributes ( owner. syntax ( ) )
78+ . map_or ( ( None , None ) , |( attrs, docs) | ( ( Some ( attrs) , Some ( docs) ) ) ) ;
79+
80+ let outer_attrs = owner. attrs ( ) . filter ( |attr| attr. excl_token ( ) . is_none ( ) ) ;
81+ let attrs = outer_attrs
82+ . chain ( inner_attrs. into_iter ( ) . flatten ( ) )
83+ . map ( |attr| ( attr. syntax ( ) . text_range ( ) . start ( ) , Attr :: from_src ( attr, hygiene) ) ) ;
84+
85+ let outer_docs =
86+ ast:: CommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( ast:: Comment :: is_outer) ;
87+ let docs = outer_docs. chain ( inner_docs. into_iter ( ) . flatten ( ) ) . map ( |docs_text| {
88+ (
89+ docs_text. syntax ( ) . text_range ( ) . start ( ) ,
90+ docs_text. doc_comment ( ) . map ( |doc| Attr {
91+ input : Some ( AttrInput :: Literal ( SmolStr :: new ( doc) ) ) ,
92+ path : ModPath :: from ( hir_expand:: name!( doc) ) ,
93+ } ) ,
94+ )
95+ } ) ;
96+ // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
97+ let attrs: Vec < _ > = docs. chain ( attrs) . sorted_by_key ( |& ( offset, _) | offset) . collect ( ) ;
98+ let entries = if attrs. is_empty ( ) {
99+ // Avoid heap allocation
100+ None
101+ } else {
102+ Some ( attrs. into_iter ( ) . flat_map ( |( _, attr) | attr) . collect ( ) )
103+ } ;
104+ Self { entries }
105+ }
106+
107+ fn from_attrs_owner ( db : & dyn DefDatabase , owner : InFile < & dyn AttrsOwner > ) -> Self {
108+ let hygiene = Hygiene :: new ( db. upcast ( ) , owner. file_id ) ;
109+ Self :: new ( owner. value , & hygiene)
110+ }
111+
112+ pub ( crate ) fn merge ( & self , other : Self ) -> Self {
113+ match ( & self . entries , & other. entries ) {
114+ ( None , None ) => Self :: EMPTY ,
115+ ( Some ( entries) , None ) | ( None , Some ( entries) ) => {
116+ Self { entries : Some ( entries. clone ( ) ) }
117+ }
118+ ( Some ( a) , Some ( b) ) => {
119+ Self { entries : Some ( a. iter ( ) . chain ( b. iter ( ) ) . cloned ( ) . collect ( ) ) }
120+ }
121+ }
122+ }
123+
124+ /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
125+ pub ( crate ) fn filter ( self , _db : & dyn DefDatabase , _krate : CrateId ) -> Attrs {
126+ // FIXME actually implement this
127+ Attrs ( self )
128+ }
129+ }
130+
57131impl Attrs {
58- pub const EMPTY : Attrs = Attrs { entries : None } ;
132+ pub const EMPTY : Self = Self ( RawAttrs :: EMPTY ) ;
59133
60134 pub ( crate ) fn attrs_query ( db : & dyn DefDatabase , def : AttrDefId ) -> Attrs {
61- match def {
135+ let raw_attrs = match def {
62136 AttrDefId :: ModuleId ( module) => {
63137 let def_map = db. crate_def_map ( module. krate ) ;
64138 let mod_data = & def_map[ module. local_id ] ;
65139 match mod_data. declaration_source ( db) {
66140 Some ( it) => {
67- Attrs :: from_attrs_owner ( db, it. as_ref ( ) . map ( |it| it as & dyn AttrsOwner ) )
141+ RawAttrs :: from_attrs_owner ( db, it. as_ref ( ) . map ( |it| it as & dyn AttrsOwner ) )
68142 }
69- None => Attrs :: from_attrs_owner (
143+ None => RawAttrs :: from_attrs_owner (
70144 db,
71145 mod_data. definition_source ( db) . as_ref ( ) . map ( |src| match src {
72146 ModuleSource :: SourceFile ( file) => file as & dyn AttrsOwner ,
@@ -78,14 +152,14 @@ impl Attrs {
78152 AttrDefId :: FieldId ( it) => {
79153 let src = it. parent . child_source ( db) ;
80154 match & src. value [ it. local_id ] {
81- Either :: Left ( _tuple) => Attrs :: default ( ) ,
82- Either :: Right ( record) => Attrs :: from_attrs_owner ( db, src. with_value ( record) ) ,
155+ Either :: Left ( _tuple) => RawAttrs :: default ( ) ,
156+ Either :: Right ( record) => RawAttrs :: from_attrs_owner ( db, src. with_value ( record) ) ,
83157 }
84158 }
85159 AttrDefId :: EnumVariantId ( var_id) => {
86160 let src = var_id. parent . child_source ( db) ;
87161 let src = src. as_ref ( ) . map ( |it| & it[ var_id. local_id ] ) ;
88- Attrs :: from_attrs_owner ( db, src. map ( |it| it as & dyn AttrsOwner ) )
162+ RawAttrs :: from_attrs_owner ( db, src. map ( |it| it as & dyn AttrsOwner ) )
89163 }
90164 AttrDefId :: AdtId ( it) => match it {
91165 AdtId :: StructId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
@@ -101,53 +175,19 @@ impl Attrs {
101175 AttrDefId :: StaticId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
102176 AttrDefId :: FunctionId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
103177 AttrDefId :: TypeAliasId ( it) => attrs_from_item_tree ( it. lookup ( db) . id , db) ,
104- }
105- }
106-
107- fn from_attrs_owner ( db : & dyn DefDatabase , owner : InFile < & dyn AttrsOwner > ) -> Attrs {
108- let hygiene = Hygiene :: new ( db. upcast ( ) , owner. file_id ) ;
109- Attrs :: new ( owner. value , & hygiene)
110- }
111-
112- pub ( crate ) fn new ( owner : & dyn AttrsOwner , hygiene : & Hygiene ) -> Attrs {
113- let ( inner_attrs, inner_docs) = inner_attributes ( owner. syntax ( ) )
114- . map_or ( ( None , None ) , |( attrs, docs) | ( ( Some ( attrs) , Some ( docs) ) ) ) ;
115-
116- let outer_attrs = owner. attrs ( ) . filter ( |attr| attr. excl_token ( ) . is_none ( ) ) ;
117- let attrs = outer_attrs
118- . chain ( inner_attrs. into_iter ( ) . flatten ( ) )
119- . map ( |attr| ( attr. syntax ( ) . text_range ( ) . start ( ) , Attr :: from_src ( attr, hygiene) ) ) ;
120-
121- let outer_docs =
122- ast:: CommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( ast:: Comment :: is_outer) ;
123- let docs = outer_docs. chain ( inner_docs. into_iter ( ) . flatten ( ) ) . map ( |docs_text| {
124- (
125- docs_text. syntax ( ) . text_range ( ) . start ( ) ,
126- docs_text. doc_comment ( ) . map ( |doc| Attr {
127- input : Some ( AttrInput :: Literal ( SmolStr :: new ( doc) ) ) ,
128- path : ModPath :: from ( hir_expand:: name!( doc) ) ,
129- } ) ,
130- )
131- } ) ;
132- // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
133- let attrs: Vec < _ > = docs. chain ( attrs) . sorted_by_key ( |& ( offset, _) | offset) . collect ( ) ;
134- let entries = if attrs. is_empty ( ) {
135- // Avoid heap allocation
136- None
137- } else {
138- Some ( attrs. into_iter ( ) . flat_map ( |( _, attr) | attr) . collect ( ) )
139178 } ;
140- Attrs { entries }
179+
180+ raw_attrs. filter ( db, def. krate ( db) )
141181 }
142182
143183 pub fn merge ( & self , other : Attrs ) -> Attrs {
144- match ( & self . entries , & other. entries ) {
145- ( None , None ) => Attrs { entries : None } ,
184+ match ( & self . 0 . entries , & other. 0 . entries ) {
185+ ( None , None ) => Attrs :: EMPTY ,
146186 ( Some ( entries) , None ) | ( None , Some ( entries) ) => {
147- Attrs { entries : Some ( entries. clone ( ) ) }
187+ Attrs ( RawAttrs { entries : Some ( entries. clone ( ) ) } )
148188 }
149189 ( Some ( a) , Some ( b) ) => {
150- Attrs { entries : Some ( a. iter ( ) . chain ( b. iter ( ) ) . cloned ( ) . collect ( ) ) }
190+ Attrs ( RawAttrs { entries : Some ( a. iter ( ) . chain ( b. iter ( ) ) . cloned ( ) . collect ( ) ) } )
151191 }
152192 }
153193 }
@@ -291,16 +331,16 @@ impl<'a> AttrQuery<'a> {
291331 }
292332}
293333
294- fn attrs_from_ast < N > ( src : AstId < N > , db : & dyn DefDatabase ) -> Attrs
334+ fn attrs_from_ast < N > ( src : AstId < N > , db : & dyn DefDatabase ) -> RawAttrs
295335where
296336 N : ast:: AttrsOwner ,
297337{
298338 let src = InFile :: new ( src. file_id , src. to_node ( db. upcast ( ) ) ) ;
299- Attrs :: from_attrs_owner ( db, src. as_ref ( ) . map ( |it| it as & dyn AttrsOwner ) )
339+ RawAttrs :: from_attrs_owner ( db, src. as_ref ( ) . map ( |it| it as & dyn AttrsOwner ) )
300340}
301341
302- fn attrs_from_item_tree < N : ItemTreeNode > ( id : ItemTreeId < N > , db : & dyn DefDatabase ) -> Attrs {
342+ fn attrs_from_item_tree < N : ItemTreeNode > ( id : ItemTreeId < N > , db : & dyn DefDatabase ) -> RawAttrs {
303343 let tree = db. item_tree ( id. file_id ) ;
304344 let mod_item = N :: id_to_mod_item ( id. value ) ;
305- tree. attrs ( mod_item. into ( ) ) . clone ( )
345+ tree. raw_attrs ( mod_item. into ( ) ) . clone ( )
306346}
0 commit comments