@@ -110,7 +110,17 @@ impl Attrs {
110
110
}
111
111
112
112
pub ( crate ) fn new ( owner : & dyn AttrsOwner , hygiene : & Hygiene ) -> Attrs {
113
- let outer_docs = ast:: CommentIter :: from_syntax_node ( owner. syntax ( ) ) . map ( |docs_text| {
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| {
114
124
(
115
125
docs_text. syntax ( ) . text_range ( ) . start ( ) ,
116
126
docs_text. doc_comment ( ) . map ( |doc| Attr {
@@ -119,13 +129,8 @@ impl Attrs {
119
129
} ) ,
120
130
)
121
131
} ) ;
122
- let outer_attrs = owner. attrs ( ) . filter ( |attr| attr. excl_token ( ) . is_none ( ) ) ;
123
- let inner_attrs = inner_attributes ( owner. syntax ( ) ) . into_iter ( ) . flatten ( ) ;
124
- let attrs = outer_attrs
125
- . chain ( inner_attrs)
126
- . map ( |attr| ( attr. syntax ( ) . text_range ( ) . start ( ) , Attr :: from_src ( attr, hygiene) ) ) ;
127
132
// sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
128
- let attrs: Vec < _ > = outer_docs . chain ( attrs) . sorted_by_key ( |& ( offset, _) | offset) . collect ( ) ;
133
+ let attrs: Vec < _ > = docs . chain ( attrs) . sorted_by_key ( |& ( offset, _) | offset) . collect ( ) ;
129
134
let entries = if attrs. is_empty ( ) {
130
135
// Avoid heap allocation
131
136
None
@@ -186,36 +191,39 @@ impl Attrs {
186
191
}
187
192
}
188
193
189
- fn inner_attributes ( syntax : & SyntaxNode ) -> Option < impl Iterator < Item = ast:: Attr > > {
190
- let ( attrs, _docs) = match_ast ! {
194
+ fn inner_attributes (
195
+ syntax : & SyntaxNode ,
196
+ ) -> Option < ( impl Iterator < Item = ast:: Attr > , impl Iterator < Item = ast:: Comment > ) > {
197
+ let ( attrs, docs) = match_ast ! {
191
198
match syntax {
192
- ast:: SourceFile ( it) => ( it. attrs( ) , None :: <ast :: Comment > ) ,
199
+ ast:: SourceFile ( it) => ( it. attrs( ) , ast :: CommentIter :: from_syntax_node ( it . syntax ( ) ) ) ,
193
200
ast:: ExternBlock ( it) => {
194
201
let extern_item_list = it. extern_item_list( ) ?;
195
- ( extern_item_list. attrs( ) , None )
202
+ ( extern_item_list. attrs( ) , ast :: CommentIter :: from_syntax_node ( extern_item_list . syntax ( ) ) )
196
203
} ,
197
204
ast:: Fn ( it) => {
198
205
let body = it. body( ) ?;
199
- ( body. attrs( ) , None )
206
+ ( body. attrs( ) , ast :: CommentIter :: from_syntax_node ( body . syntax ( ) ) )
200
207
} ,
201
208
ast:: Impl ( it) => {
202
209
let assoc_item_list = it. assoc_item_list( ) ?;
203
- ( assoc_item_list. attrs( ) , None )
210
+ ( assoc_item_list. attrs( ) , ast :: CommentIter :: from_syntax_node ( assoc_item_list . syntax ( ) ) )
204
211
} ,
205
212
ast:: Module ( it) => {
206
213
let item_list = it. item_list( ) ?;
207
- ( item_list. attrs( ) , None )
214
+ ( item_list. attrs( ) , ast :: CommentIter :: from_syntax_node ( item_list . syntax ( ) ) )
208
215
} ,
209
216
// FIXME: BlockExpr's only accept inner attributes in specific cases
210
217
// Excerpt from the reference:
211
- // Block expressions accept outer and inner attributes, but only when they are the outer
212
- // expression of an expression statement or the final expression of another block expression.
218
+ // Block expressions accept outer and inner attributes, but only when they are the outer
219
+ // expression of an expression statement or the final expression of another block expression.
213
220
ast:: BlockExpr ( it) => return None ,
214
221
_ => return None ,
215
222
}
216
223
} ;
217
224
let attrs = attrs. filter ( |attr| attr. excl_token ( ) . is_some ( ) ) ;
218
- Some ( attrs)
225
+ let docs = docs. filter ( |doc| doc. is_inner ( ) ) ;
226
+ Some ( ( attrs, docs) )
219
227
}
220
228
221
229
#[ derive( Debug , Clone , PartialEq , Eq ) ]
0 commit comments