@@ -140,55 +140,59 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &hir::Block<'_>) -> boo
140140}
141141
142142/// Checks if the lines immediately preceding the item contain a safety comment.
143+ #[ allow( clippy:: collapsible_match) ]
143144fn item_has_safety_comment ( cx : & LateContext < ' _ > , item : & hir:: Item < ' _ > ) -> bool {
144145 if span_from_macro_expansion_has_safety_comment ( cx, item. span ) || span_in_body_has_safety_comment ( cx, item. span ) {
145146 return true ;
146147 }
147148
148149 if item. span . ctxt ( ) == SyntaxContext :: root ( ) {
149150 if let Some ( parent_node) = get_parent_node ( cx. tcx , item. hir_id ( ) ) {
150- let mut span_before_item = None ;
151- let mut hi = false ;
152- if let Node :: Item ( parent_item) = parent_node {
153- if let ItemKind :: Mod ( parent_mod) = & parent_item. kind {
154- for ( idx, item_id) in parent_mod. item_ids . iter ( ) . enumerate ( ) {
155- if * item_id == item. item_id ( ) {
156- if idx == 0 {
157- // mod A { /* comment */ unsafe impl T {} ... }
158- // ^------------------------------------------^ gets this span
159- // ^---------------------^ finally checks the text in this range
160- hi = false ;
161- span_before_item = Some ( parent_item. span ) ;
162- } else {
163- let prev_item = cx. tcx . hir ( ) . item ( parent_mod. item_ids [ idx - 1 ] ) ;
164- // some_item /* comment */ unsafe impl T {}
165- // ^-------^ gets this span
166- // ^---------------^ finally checks the text in this range
167- hi = true ;
168- span_before_item = Some ( prev_item. span ) ;
169- }
170- break ;
151+ let comment_start;
152+ match parent_node {
153+ Node :: Crate ( parent_mod) => {
154+ comment_start = comment_start_before_impl_in_mod ( cx, parent_mod, parent_mod. spans . inner_span , item) ;
155+ } ,
156+ Node :: Item ( parent_item) => {
157+ if let ItemKind :: Mod ( parent_mod) = & parent_item. kind {
158+ comment_start = comment_start_before_impl_in_mod ( cx, parent_mod, parent_item. span , item) ;
159+ } else {
160+ // Doesn't support impls in this position. Pretend a comment was found.
161+ return true ;
162+ }
163+ } ,
164+ Node :: Stmt ( stmt) => {
165+ if let Some ( stmt_parent) = get_parent_node ( cx. tcx , stmt. hir_id ) {
166+ match stmt_parent {
167+ Node :: Block ( block) => {
168+ comment_start = walk_span_to_context ( block. span , SyntaxContext :: root ( ) ) . map ( Span :: lo) ;
169+ } ,
170+ _ => {
171+ // Doesn't support impls in this position. Pretend a comment was found.
172+ return true ;
173+ } ,
171174 }
175+ } else {
176+ // Doesn't support impls in this position. Pretend a comment was found.
177+ return true ;
172178 }
173- }
179+ } ,
180+ _ => {
181+ // Doesn't support impls in this position. Pretend a comment was found.
182+ return true ;
183+ } ,
174184 }
175- let span_before_item = span_before_item. unwrap ( ) ;
176185
177186 let source_map = cx. sess ( ) . source_map ( ) ;
178- if let Some ( item_span) = walk_span_to_context ( item. span , SyntaxContext :: root ( ) )
179- && let Some ( span_before_item) = walk_span_to_context ( span_before_item, SyntaxContext :: root ( ) )
180- && let Ok ( unsafe_line) = source_map. lookup_line ( item_span. lo ( ) )
181- && let Ok ( line_before_unsafe) = source_map. lookup_line ( if hi {
182- span_before_item. hi ( )
183- } else {
184- span_before_item. lo ( )
185- } )
186- && Lrc :: ptr_eq ( & unsafe_line. sf , & line_before_unsafe. sf )
187+ if let Some ( comment_start) = comment_start
188+ && let Ok ( unsafe_line) = source_map. lookup_line ( item. span . lo ( ) )
189+ && let Ok ( comment_start_line) = source_map. lookup_line ( comment_start)
190+ && Lrc :: ptr_eq ( & unsafe_line. sf , & comment_start_line. sf )
187191 && let Some ( src) = unsafe_line. sf . src . as_deref ( )
188192 {
189- line_before_unsafe . line < unsafe_line. line && text_has_safety_comment (
193+ comment_start_line . line < unsafe_line. line && text_has_safety_comment (
190194 src,
191- & unsafe_line. sf . lines [ line_before_unsafe . line + 1 ..=unsafe_line. line ] ,
195+ & unsafe_line. sf . lines [ comment_start_line . line + 1 ..=unsafe_line. line ] ,
192196 unsafe_line. sf . start_pos . to_usize ( ) ,
193197 )
194198 } else {
@@ -204,6 +208,35 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> bool {
204208 }
205209}
206210
211+ fn comment_start_before_impl_in_mod (
212+ cx : & LateContext < ' _ > ,
213+ parent_mod : & hir:: Mod < ' _ > ,
214+ parent_mod_span : Span ,
215+ imple : & hir:: Item < ' _ > ,
216+ ) -> Option < BytePos > {
217+ parent_mod. item_ids . iter ( ) . enumerate ( ) . find_map ( |( idx, item_id) | {
218+ if * item_id == imple. item_id ( ) {
219+ if idx == 0 {
220+ // mod A { /* comment */ unsafe impl T {} ... }
221+ // ^------------------------------------------^ returns the start of this span
222+ // ^---------------^ finally checks comments in this range
223+ if let Some ( sp) = walk_span_to_context ( parent_mod_span, SyntaxContext :: root ( ) ) {
224+ return Some ( sp. lo ( ) ) ;
225+ }
226+ } else {
227+ // some_item /* comment */ unsafe impl T {}
228+ // ^-------^ returns the end of this span
229+ // ^---------------^ finally checks comments in this range
230+ let prev_item = cx. tcx . hir ( ) . item ( parent_mod. item_ids [ idx - 1 ] ) ;
231+ if let Some ( sp) = walk_span_to_context ( prev_item. span , SyntaxContext :: root ( ) ) {
232+ return Some ( sp. hi ( ) ) ;
233+ }
234+ }
235+ }
236+ None
237+ } )
238+ }
239+
207240fn span_from_macro_expansion_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> bool {
208241 let source_map = cx. sess ( ) . source_map ( ) ;
209242 let ctxt = span. ctxt ( ) ;
0 commit comments