@@ -5,7 +5,7 @@ use std::{fmt, hash::Hash, ops, sync::Arc};
5
5
use base_db:: CrateId ;
6
6
use cfg:: { CfgExpr , CfgOptions } ;
7
7
use either:: Either ;
8
- use hir_expand:: { hygiene:: Hygiene , name:: AsName , AstId , InFile } ;
8
+ use hir_expand:: { hygiene:: Hygiene , name:: AsName , AstId , HirFileId , InFile } ;
9
9
use itertools:: Itertools ;
10
10
use la_arena:: ArenaMap ;
11
11
use mbe:: { syntax_node_to_token_tree, DelimiterKind , Punct } ;
@@ -84,6 +84,14 @@ impl ops::Deref for Attrs {
84
84
}
85
85
}
86
86
87
+ impl ops:: Index < AttrId > for Attrs {
88
+ type Output = Attr ;
89
+
90
+ fn index ( & self , AttrId { ast_index, .. } : AttrId ) -> & Self :: Output {
91
+ & ( * * self ) [ ast_index as usize ]
92
+ }
93
+ }
94
+
87
95
impl ops:: Deref for AttrsWithOwner {
88
96
type Target = Attrs ;
89
97
@@ -509,23 +517,23 @@ fn inner_attributes(
509
517
) -> Option < ( impl Iterator < Item = ast:: Attr > , impl Iterator < Item = ast:: Comment > ) > {
510
518
let ( attrs, docs) = match_ast ! {
511
519
match syntax {
512
- ast:: SourceFile ( it) => ( it. attrs( ) , ast:: CommentIter :: from_syntax_node( it. syntax( ) ) ) ,
520
+ ast:: SourceFile ( it) => ( it. attrs( ) , ast:: DocCommentIter :: from_syntax_node( it. syntax( ) ) ) ,
513
521
ast:: ExternBlock ( it) => {
514
522
let extern_item_list = it. extern_item_list( ) ?;
515
- ( extern_item_list. attrs( ) , ast:: CommentIter :: from_syntax_node( extern_item_list. syntax( ) ) )
523
+ ( extern_item_list. attrs( ) , ast:: DocCommentIter :: from_syntax_node( extern_item_list. syntax( ) ) )
516
524
} ,
517
525
ast:: Fn ( it) => {
518
526
let body = it. body( ) ?;
519
527
let stmt_list = body. stmt_list( ) ?;
520
- ( stmt_list. attrs( ) , ast:: CommentIter :: from_syntax_node( body. syntax( ) ) )
528
+ ( stmt_list. attrs( ) , ast:: DocCommentIter :: from_syntax_node( body. syntax( ) ) )
521
529
} ,
522
530
ast:: Impl ( it) => {
523
531
let assoc_item_list = it. assoc_item_list( ) ?;
524
- ( assoc_item_list. attrs( ) , ast:: CommentIter :: from_syntax_node( assoc_item_list. syntax( ) ) )
532
+ ( assoc_item_list. attrs( ) , ast:: DocCommentIter :: from_syntax_node( assoc_item_list. syntax( ) ) )
525
533
} ,
526
534
ast:: Module ( it) => {
527
535
let item_list = it. item_list( ) ?;
528
- ( item_list. attrs( ) , ast:: CommentIter :: from_syntax_node( item_list. syntax( ) ) )
536
+ ( item_list. attrs( ) , ast:: DocCommentIter :: from_syntax_node( item_list. syntax( ) ) )
529
537
} ,
530
538
// FIXME: BlockExpr's only accept inner attributes in specific cases
531
539
// Excerpt from the reference:
@@ -542,27 +550,20 @@ fn inner_attributes(
542
550
543
551
#[ derive( Debug ) ]
544
552
pub struct AttrSourceMap {
545
- attrs : Vec < InFile < ast:: Attr > > ,
546
- doc_comments : Vec < InFile < ast :: Comment > > ,
553
+ source : Vec < Either < ast:: Attr , ast :: Comment > > ,
554
+ file_id : HirFileId ,
547
555
}
548
556
549
557
impl AttrSourceMap {
550
558
fn new ( owner : InFile < & dyn ast:: HasAttrs > ) -> Self {
551
- let mut attrs = Vec :: new ( ) ;
552
- let mut doc_comments = Vec :: new ( ) ;
553
- for ( _, attr) in collect_attrs ( owner. value ) {
554
- match attr {
555
- Either :: Left ( attr) => attrs. push ( owner. with_value ( attr) ) ,
556
- Either :: Right ( comment) => doc_comments. push ( owner. with_value ( comment) ) ,
557
- }
559
+ Self {
560
+ source : collect_attrs ( owner. value ) . map ( |( _, it) | it) . collect ( ) ,
561
+ file_id : owner. file_id ,
558
562
}
559
-
560
- Self { attrs, doc_comments }
561
563
}
562
564
563
565
fn merge ( & mut self , other : Self ) {
564
- self . attrs . extend ( other. attrs ) ;
565
- self . doc_comments . extend ( other. doc_comments ) ;
566
+ self . source . extend ( other. source ) ;
566
567
}
567
568
568
569
/// Maps the lowered `Attr` back to its original syntax node.
@@ -571,24 +572,15 @@ impl AttrSourceMap {
571
572
///
572
573
/// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
573
574
/// the attribute represented by `Attr`.
574
- pub fn source_of ( & self , attr : & Attr ) -> InFile < Either < ast:: Attr , ast:: Comment > > {
575
+ pub fn source_of ( & self , attr : & Attr ) -> InFile < & Either < ast:: Attr , ast:: Comment > > {
575
576
self . source_of_id ( attr. id )
576
577
}
577
578
578
- fn source_of_id ( & self , id : AttrId ) -> InFile < Either < ast:: Attr , ast:: Comment > > {
579
- if id. is_doc_comment {
580
- self . doc_comments
581
- . get ( id. ast_index as usize )
582
- . unwrap_or_else ( || panic ! ( "cannot find doc comment at index {:?}" , id) )
583
- . clone ( )
584
- . map ( Either :: Right )
585
- } else {
586
- self . attrs
587
- . get ( id. ast_index as usize )
588
- . unwrap_or_else ( || panic ! ( "cannot find `Attr` at index {:?}" , id) )
589
- . clone ( )
590
- . map ( Either :: Left )
591
- }
579
+ fn source_of_id ( & self , id : AttrId ) -> InFile < & Either < ast:: Attr , ast:: Comment > > {
580
+ self . source
581
+ . get ( id. ast_index as usize )
582
+ . map ( |it| InFile :: new ( self . file_id , it) )
583
+ . unwrap_or_else ( || panic ! ( "cannot find attr at index {:?}" , id) )
592
584
}
593
585
}
594
586
@@ -656,8 +648,7 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
656
648
}
657
649
658
650
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
659
- pub ( crate ) struct AttrId {
660
- is_doc_comment : bool ,
651
+ pub struct AttrId {
661
652
pub ( crate ) ast_index : u32 ,
662
653
}
663
654
@@ -816,27 +807,20 @@ fn collect_attrs(
816
807
. map_or ( ( None , None ) , |( attrs, docs) | ( Some ( attrs) , Some ( docs) ) ) ;
817
808
818
809
let outer_attrs = owner. attrs ( ) . filter ( |attr| attr. kind ( ) . is_outer ( ) ) ;
819
- let attrs =
820
- outer_attrs. chain ( inner_attrs. into_iter ( ) . flatten ( ) ) . enumerate ( ) . map ( |( idx, attr) | {
821
- (
822
- AttrId { ast_index : idx as u32 , is_doc_comment : false } ,
823
- attr. syntax ( ) . text_range ( ) . start ( ) ,
824
- Either :: Left ( attr) ,
825
- )
826
- } ) ;
810
+ let attrs = outer_attrs
811
+ . chain ( inner_attrs. into_iter ( ) . flatten ( ) )
812
+ . map ( |attr| ( attr. syntax ( ) . text_range ( ) . start ( ) , Either :: Left ( attr) ) ) ;
827
813
828
814
let outer_docs =
829
- ast:: CommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( ast:: Comment :: is_outer) ;
830
- let docs =
831
- outer_docs. chain ( inner_docs. into_iter ( ) . flatten ( ) ) . enumerate ( ) . map ( |( idx, docs_text) | {
832
- (
833
- AttrId { ast_index : idx as u32 , is_doc_comment : true } ,
834
- docs_text. syntax ( ) . text_range ( ) . start ( ) ,
835
- Either :: Right ( docs_text) ,
836
- )
837
- } ) ;
815
+ ast:: DocCommentIter :: from_syntax_node ( owner. syntax ( ) ) . filter ( ast:: Comment :: is_outer) ;
816
+ let docs = outer_docs
817
+ . chain ( inner_docs. into_iter ( ) . flatten ( ) )
818
+ . map ( |docs_text| ( docs_text. syntax ( ) . text_range ( ) . start ( ) , Either :: Right ( docs_text) ) ) ;
838
819
// sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
839
- docs. chain ( attrs) . sorted_by_key ( |& ( _, offset, _) | offset) . map ( |( id, _, attr) | ( id, attr) )
820
+ docs. chain ( attrs)
821
+ . sorted_by_key ( |& ( offset, _) | offset)
822
+ . enumerate ( )
823
+ . map ( |( id, ( _, attr) ) | ( AttrId { ast_index : id as u32 } , attr) )
840
824
}
841
825
842
826
pub ( crate ) fn variants_attrs_source_map (
0 commit comments