@@ -73,8 +73,8 @@ impl ops::Deref for RawAttrs {
7373 }
7474}
7575impl Attrs {
76- pub fn get ( & self , AttrId { ast_index , .. } : AttrId ) -> Option < & Attr > {
77- ( * * self ) . get ( ast_index as usize )
76+ pub fn get ( & self , id : AttrId ) -> Option < & Attr > {
77+ ( * * self ) . iter ( ) . find ( |attr| attr . id == id )
7878 }
7979}
8080
@@ -89,14 +89,6 @@ impl ops::Deref for Attrs {
8989 }
9090}
9191
92- impl ops:: Index < AttrId > for Attrs {
93- type Output = Attr ;
94-
95- fn index ( & self , AttrId { ast_index, .. } : AttrId ) -> & Self :: Output {
96- & ( * * self ) [ ast_index as usize ]
97- }
98- }
99-
10092impl ops:: Deref for AttrsWithOwner {
10193 type Target = Attrs ;
10294
@@ -110,7 +102,7 @@ impl RawAttrs {
110102
111103 pub ( crate ) fn new ( db : & dyn DefDatabase , owner : & dyn ast:: HasAttrs , hygiene : & Hygiene ) -> Self {
112104 let entries = collect_attrs ( owner)
113- . flat_map ( |( id, attr) | match attr {
105+ . filter_map ( |( id, attr) | match attr {
114106 Either :: Left ( attr) => {
115107 attr. meta ( ) . and_then ( |meta| Attr :: from_src ( db, meta, hygiene, id) )
116108 }
@@ -525,38 +517,36 @@ impl AttrsWithOwner {
525517
526518fn inner_attributes (
527519 syntax : & SyntaxNode ,
528- ) -> Option < ( impl Iterator < Item = ast:: Attr > , impl Iterator < Item = ast:: Comment > ) > {
529- let ( attrs , docs ) = match_ast ! {
520+ ) -> Option < impl Iterator < Item = Either < ast:: Attr , ast:: Comment > > > {
521+ let node = match_ast ! {
530522 match syntax {
531- ast:: SourceFile ( it ) => ( it . attrs ( ) , ast :: DocCommentIter :: from_syntax_node ( it . syntax ( ) ) ) ,
532- ast:: ExternBlock ( it) => {
533- let extern_item_list = it. extern_item_list ( ) ?;
534- ( extern_item_list . attrs ( ) , ast :: DocCommentIter :: from_syntax_node ( extern_item_list . syntax( ) ) )
535- } ,
536- ast:: Fn ( it) => {
537- let body = it . body ( ) ? ;
538- let stmt_list = body . stmt_list ( ) ? ;
539- ( stmt_list . attrs ( ) , ast :: DocCommentIter :: from_syntax_node ( body . syntax ( ) ) )
540- } ,
541- ast :: Impl ( it ) => {
542- let assoc_item_list = it . assoc_item_list ( ) ? ;
543- ( assoc_item_list . attrs ( ) , ast :: DocCommentIter :: from_syntax_node ( assoc_item_list . syntax ( ) ) )
544- } ,
545- ast :: Module ( it ) => {
546- let item_list = it . item_list ( ) ? ;
547- ( item_list . attrs ( ) , ast :: DocCommentIter :: from_syntax_node ( item_list . syntax ( ) ) )
523+ ast:: SourceFile ( _ ) => syntax . clone ( ) ,
524+ ast:: ExternBlock ( it) => it . extern_item_list ( ) ? . syntax ( ) . clone ( ) ,
525+ ast :: Fn ( it ) => it. body ( ) ?. stmt_list ( ) ? . syntax ( ) . clone ( ) ,
526+ ast :: Impl ( it ) => it . assoc_item_list ( ) ? . syntax( ) . clone ( ) ,
527+ ast :: Module ( it ) => it . item_list ( ) ? . syntax ( ) . clone ( ) ,
528+ ast:: BlockExpr ( it) => {
529+ use syntax :: SyntaxKind :: { BLOCK_EXPR , EXPR_STMT } ;
530+ // Block expressions accept outer and inner attributes, but only when they are the outer
531+ // expression of an expression statement or the final expression of another block expression.
532+ let may_carry_attributes = matches! (
533+ it . syntax ( ) . parent ( ) . map ( |it| it . kind ( ) ) ,
534+ Some ( BLOCK_EXPR | EXPR_STMT )
535+ ) ;
536+ if !may_carry_attributes {
537+ return None
538+ }
539+ syntax . clone ( )
548540 } ,
549- // FIXME: BlockExpr's only accept inner attributes in specific cases
550- // Excerpt from the reference:
551- // Block expressions accept outer and inner attributes, but only when they are the outer
552- // expression of an expression statement or the final expression of another block expression.
553- ast:: BlockExpr ( _it) => return None ,
554541 _ => return None ,
555542 }
556543 } ;
557- let attrs = attrs. filter ( |attr| attr. kind ( ) . is_inner ( ) ) ;
558- let docs = docs. filter ( |doc| doc. is_inner ( ) ) ;
559- Some ( ( attrs, docs) )
544+
545+ let attrs = ast:: AttrDocCommentIter :: from_syntax_node ( & node) . filter ( |el| match el {
546+ Either :: Left ( attr) => attr. kind ( ) . is_inner ( ) ,
547+ Either :: Right ( comment) => comment. is_inner ( ) ,
548+ } ) ;
549+ Some ( attrs)
560550}
561551
562552#[ derive( Debug ) ]
@@ -833,24 +823,16 @@ fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase
833823fn collect_attrs (
834824 owner : & dyn ast:: HasAttrs ,
835825) -> impl Iterator < Item = ( AttrId , Either < ast:: Attr , ast:: Comment > ) > {
836- let ( inner_attrs, inner_docs) = inner_attributes ( owner. syntax ( ) )
837- . map_or ( ( None , None ) , |( attrs, docs) | ( Some ( attrs) , Some ( docs) ) ) ;
838-
839- let outer_attrs = owner. attrs ( ) . filter ( |attr| attr. kind ( ) . is_outer ( ) ) ;
840- let attrs = outer_attrs
841- . chain ( inner_attrs. into_iter ( ) . flatten ( ) )
842- . map ( |attr| ( attr. syntax ( ) . text_range ( ) . start ( ) , Either :: Left ( attr) ) ) ;
843-
844- let outer_docs =
845- ast:: DocCommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( ast:: Comment :: is_outer) ;
846- let docs = outer_docs
847- . chain ( inner_docs. into_iter ( ) . flatten ( ) )
848- . map ( |docs_text| ( docs_text. syntax ( ) . text_range ( ) . start ( ) , Either :: Right ( docs_text) ) ) ;
849- // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
850- docs. chain ( attrs)
851- . sorted_by_key ( |& ( offset, _) | offset)
826+ let inner_attrs = inner_attributes ( owner. syntax ( ) ) . into_iter ( ) . flatten ( ) ;
827+ let outer_attrs =
828+ ast:: AttrDocCommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( |el| match el {
829+ Either :: Left ( attr) => attr. kind ( ) . is_outer ( ) ,
830+ Either :: Right ( comment) => comment. is_outer ( ) ,
831+ } ) ;
832+ outer_attrs
833+ . chain ( inner_attrs)
852834 . enumerate ( )
853- . map ( |( id, ( _ , attr) ) | ( AttrId { ast_index : id as u32 } , attr) )
835+ . map ( |( id, attr) | ( AttrId { ast_index : id as u32 } , attr) )
854836}
855837
856838pub ( crate ) fn variants_attrs_source_map (
0 commit comments