@@ -7,9 +7,28 @@ use rustc_errors::Applicability;
77use rustc_hir:: { Expr , ExprKind } ;
88use rustc_lint:: { LateContext , LintContext } ;
99use rustc_span:: hygiene;
10+ use rustc_span:: source_map:: SourceMap ;
1011use rustc_span:: { BytePos , Pos , Span , SyntaxContext } ;
1112use std:: borrow:: Cow ;
1213
14+ /// Checks if the span starts with the given text. This will return false if the span crosses
15+ /// multiple files or if source is not available.
16+ ///
17+ /// This is used to check for proc macros giving unhelpful spans to things.
18+ pub fn span_starts_with < T : LintContext > ( cx : & T , span : Span , text : & str ) -> bool {
19+ fn helper ( sm : & SourceMap , span : Span , text : & str ) -> bool {
20+ let pos = sm. lookup_byte_offset ( span. lo ( ) ) ;
21+ let Some ( ref src) = pos. sf . src else {
22+ return false ;
23+ } ;
24+ let end = span. hi ( ) - pos. sf . start_pos ;
25+ src. get ( pos. pos . 0 as usize ..end. 0 as usize )
26+ // Expression spans can include wrapping parenthesis. Remove them first.
27+ . map_or ( false , |s| s. trim_start_matches ( '(' ) . starts_with ( text) )
28+ }
29+ helper ( cx. sess ( ) . source_map ( ) , span, text)
30+ }
31+
1332/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
1433/// Also takes an `Option<String>` which can be put inside the braces.
1534pub fn expr_block < ' a , T : LintContext > (
0 commit comments