@@ -9,7 +9,7 @@ use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
99use smallvec:: { smallvec, SmallVec } ;
1010use span:: { Span , SyntaxContextId } ;
1111use syntax:: { ast, format_smolstr, match_ast, AstNode , AstToken , SmolStr , SyntaxNode } ;
12- use triomphe:: Arc ;
12+ use triomphe:: ThinArc ;
1313
1414use crate :: {
1515 db:: ExpandDatabase ,
@@ -22,16 +22,15 @@ use crate::{
2222/// Syntactical attributes, without filtering of `cfg_attr`s.
2323#[ derive( Default , Debug , Clone , PartialEq , Eq ) ]
2424pub struct RawAttrs {
25- // FIXME: Make this a ThinArc
26- entries : Option < Arc < [ Attr ] > > ,
25+ entries : Option < ThinArc < ( ) , Attr > > ,
2726}
2827
2928impl ops:: Deref for RawAttrs {
3029 type Target = [ Attr ] ;
3130
3231 fn deref ( & self ) -> & [ Attr ] {
3332 match & self . entries {
34- Some ( it) => it ,
33+ Some ( it) => & it . slice ,
3534 None => & [ ] ,
3635 }
3736 }
@@ -45,27 +44,34 @@ impl RawAttrs {
4544 owner : & dyn ast:: HasAttrs ,
4645 span_map : SpanMapRef < ' _ > ,
4746 ) -> Self {
48- let entries = collect_attrs ( owner) . filter_map ( |( id, attr) | match attr {
49- Either :: Left ( attr) => {
50- attr. meta ( ) . and_then ( |meta| Attr :: from_src ( db, meta, span_map, id) )
51- }
52- Either :: Right ( comment) => comment. doc_comment ( ) . map ( |doc| {
53- let span = span_map. span_for_range ( comment. syntax ( ) . text_range ( ) ) ;
54- Attr {
55- id,
56- input : Some ( Interned :: new ( AttrInput :: Literal ( tt:: Literal {
57- // FIXME: Escape quotes from comment content
58- text : SmolStr :: new ( format_smolstr ! ( "\" {doc}\" " , ) ) ,
59- span,
60- } ) ) ) ,
61- path : Interned :: new ( ModPath :: from ( crate :: name!( doc) ) ) ,
62- ctxt : span. ctx ,
47+ let entries: Vec < _ > = collect_attrs ( owner)
48+ . filter_map ( |( id, attr) | match attr {
49+ Either :: Left ( attr) => {
50+ attr. meta ( ) . and_then ( |meta| Attr :: from_src ( db, meta, span_map, id) )
6351 }
64- } ) ,
65- } ) ;
66- let entries: Arc < [ Attr ] > = Arc :: from_iter ( entries) ;
52+ Either :: Right ( comment) => comment. doc_comment ( ) . map ( |doc| {
53+ let span = span_map. span_for_range ( comment. syntax ( ) . text_range ( ) ) ;
54+ Attr {
55+ id,
56+ input : Some ( Interned :: new ( AttrInput :: Literal ( tt:: Literal {
57+ // FIXME: Escape quotes from comment content
58+ text : SmolStr :: new ( format_smolstr ! ( "\" {doc}\" " , ) ) ,
59+ span,
60+ } ) ) ) ,
61+ path : Interned :: new ( ModPath :: from ( crate :: name!( doc) ) ) ,
62+ ctxt : span. ctx ,
63+ }
64+ } ) ,
65+ } )
66+ . collect ( ) ;
6767
68- Self { entries : if entries. is_empty ( ) { None } else { Some ( entries) } }
68+ let entries = if entries. is_empty ( ) {
69+ None
70+ } else {
71+ Some ( ThinArc :: from_header_and_iter ( ( ) , entries. into_iter ( ) ) )
72+ } ;
73+
74+ RawAttrs { entries }
6975 }
7076
7177 pub fn from_attrs_owner (
@@ -82,16 +88,20 @@ impl RawAttrs {
8288 ( None , entries @ Some ( _) ) => Self { entries } ,
8389 ( Some ( entries) , None ) => Self { entries : Some ( entries. clone ( ) ) } ,
8490 ( Some ( a) , Some ( b) ) => {
85- let last_ast_index = a. last ( ) . map_or ( 0 , |it| it. id . ast_index ( ) + 1 ) as u32 ;
86- Self {
87- entries : Some ( Arc :: from_iter ( a. iter ( ) . cloned ( ) . chain ( b. iter ( ) . map ( |it| {
91+ let last_ast_index = a. slice . last ( ) . map_or ( 0 , |it| it. id . ast_index ( ) + 1 ) as u32 ;
92+ let items = a
93+ . slice
94+ . iter ( )
95+ . cloned ( )
96+ . chain ( b. slice . iter ( ) . map ( |it| {
8897 let mut it = it. clone ( ) ;
8998 it. id . id = ( it. id . ast_index ( ) as u32 + last_ast_index)
9099 | ( it. id . cfg_attr_index ( ) . unwrap_or ( 0 ) as u32 )
91100 << AttrId :: AST_INDEX_BITS ;
92101 it
93- } ) ) ) ) ,
94- }
102+ } ) )
103+ . collect :: < Vec < _ > > ( ) ;
104+ Self { entries : Some ( ThinArc :: from_header_and_iter ( ( ) , items. into_iter ( ) ) ) }
95105 }
96106 }
97107 }
@@ -107,41 +117,47 @@ impl RawAttrs {
107117 }
108118
109119 let crate_graph = db. crate_graph ( ) ;
110- let new_attrs = Arc :: from_iter ( self . iter ( ) . flat_map ( |attr| -> SmallVec < [ _ ; 1 ] > {
111- let is_cfg_attr =
112- attr. path . as_ident ( ) . map_or ( false , |name| * name == crate :: name![ cfg_attr] ) ;
113- if !is_cfg_attr {
114- return smallvec ! [ attr. clone( ) ] ;
115- }
116-
117- let subtree = match attr. token_tree_value ( ) {
118- Some ( it) => it,
119- _ => return smallvec ! [ attr. clone( ) ] ,
120- } ;
121-
122- let ( cfg, parts) = match parse_cfg_attr_input ( subtree) {
123- Some ( it) => it,
124- None => return smallvec ! [ attr. clone( ) ] ,
125- } ;
126- let index = attr. id ;
127- let attrs = parts
128- . enumerate ( )
129- . take ( 1 << AttrId :: CFG_ATTR_BITS )
130- . filter_map ( |( idx, attr) | Attr :: from_tt ( db, attr, index. with_cfg_attr ( idx) ) ) ;
131-
132- let cfg_options = & crate_graph[ krate] . cfg_options ;
133- let cfg = Subtree { delimiter : subtree. delimiter , token_trees : Box :: from ( cfg) } ;
134- let cfg = CfgExpr :: parse ( & cfg) ;
135- if cfg_options. check ( & cfg) == Some ( false ) {
136- smallvec ! [ ]
137- } else {
138- cov_mark:: hit!( cfg_attr_active) ;
139-
140- attrs. collect ( )
141- }
142- } ) ) ;
120+ let new_attrs =
121+ self . iter ( )
122+ . flat_map ( |attr| -> SmallVec < [ _ ; 1 ] > {
123+ let is_cfg_attr =
124+ attr. path . as_ident ( ) . map_or ( false , |name| * name == crate :: name![ cfg_attr] ) ;
125+ if !is_cfg_attr {
126+ return smallvec ! [ attr. clone( ) ] ;
127+ }
143128
144- RawAttrs { entries : Some ( new_attrs) }
129+ let subtree = match attr. token_tree_value ( ) {
130+ Some ( it) => it,
131+ _ => return smallvec ! [ attr. clone( ) ] ,
132+ } ;
133+
134+ let ( cfg, parts) = match parse_cfg_attr_input ( subtree) {
135+ Some ( it) => it,
136+ None => return smallvec ! [ attr. clone( ) ] ,
137+ } ;
138+ let index = attr. id ;
139+ let attrs = parts. enumerate ( ) . take ( 1 << AttrId :: CFG_ATTR_BITS ) . filter_map (
140+ |( idx, attr) | Attr :: from_tt ( db, attr, index. with_cfg_attr ( idx) ) ,
141+ ) ;
142+
143+ let cfg_options = & crate_graph[ krate] . cfg_options ;
144+ let cfg = Subtree { delimiter : subtree. delimiter , token_trees : Box :: from ( cfg) } ;
145+ let cfg = CfgExpr :: parse ( & cfg) ;
146+ if cfg_options. check ( & cfg) == Some ( false ) {
147+ smallvec ! [ ]
148+ } else {
149+ cov_mark:: hit!( cfg_attr_active) ;
150+
151+ attrs. collect ( )
152+ }
153+ } )
154+ . collect :: < Vec < _ > > ( ) ;
155+ let entries = if new_attrs. is_empty ( ) {
156+ None
157+ } else {
158+ Some ( ThinArc :: from_header_and_iter ( ( ) , new_attrs. into_iter ( ) ) )
159+ } ;
160+ RawAttrs { entries }
145161 }
146162}
147163
0 commit comments