@@ -16,9 +16,8 @@ pub fn compile_error_msg(py: Python, error: PyErr, tokens: TokenStream) -> Token
16
16
let line: Option < usize > = value. getattr ( "lineno" ) . ok ( ) . and_then ( |x| x. extract ( ) . ok ( ) ) ;
17
17
let msg: Option < String > = value. getattr ( "msg" ) . ok ( ) . and_then ( |x| x. extract ( ) . ok ( ) ) ;
18
18
if let ( Some ( line) , Some ( msg) ) = ( line, msg) {
19
- if let Some ( span) = span_for_line ( tokens. clone ( ) , line) {
20
- let error = format ! ( "python: {}" , msg) ;
21
- return quote_spanned ! ( span. into( ) => compile_error!{ #error} ) ;
19
+ if let Some ( spans) = spans_for_line ( tokens. clone ( ) , line) {
20
+ return compile_error ( spans, format ! ( "python: {msg}" ) ) ;
22
21
}
23
22
}
24
23
}
@@ -27,9 +26,8 @@ pub fn compile_error_msg(py: Python, error: PyErr, tokens: TokenStream) -> Token
27
26
if let Ok ( ( file, line) ) = get_traceback_info ( tb) {
28
27
if file == Span :: call_site ( ) . file ( ) {
29
28
if let Ok ( msg) = value. str ( ) {
30
- if let Some ( span) = span_for_line ( tokens, line) {
31
- let error = format ! ( "python: {}" , msg) ;
32
- return quote_spanned ! ( span. into( ) => compile_error!{ #error} ) ;
29
+ if let Some ( spans) = spans_for_line ( tokens, line) {
30
+ return compile_error ( spans, format ! ( "python: {msg}" ) ) ;
33
31
}
34
32
}
35
33
}
@@ -48,21 +46,22 @@ fn get_traceback_info(tb: &Bound<'_, PyTraceback>) -> PyResult<(String, usize)>
48
46
Ok ( ( file, line) )
49
47
}
50
48
51
- /// Get a span for a specific line of input from a TokenStream.
52
- fn span_for_line ( input : TokenStream , line : usize ) -> Option < Span > {
49
+ /// Get the first and last span for a specific line of input from a TokenStream.
50
+ fn spans_for_line ( input : TokenStream , line : usize ) -> Option < ( Span , Span ) > {
53
51
let mut spans = input
54
52
. into_iter ( )
55
53
. map ( |x| x. span ( ) . unwrap ( ) )
56
54
. skip_while ( |span| span. start ( ) . line ( ) < line)
57
55
. take_while ( |span| span. start ( ) . line ( ) == line) ;
58
56
59
- let mut result = spans. next ( ) ?;
60
- for span in spans {
61
- result = match result. join ( span) {
62
- None => return Some ( result) ,
63
- Some ( span) => span,
64
- }
65
- }
57
+ let first = spans. next ( ) ?;
58
+ let last = spans. last ( ) . unwrap_or ( first) ;
59
+
60
+ Some ( ( first, last) )
61
+ }
66
62
67
- Some ( result)
63
+ /// Create a compile_error!{} using two spans that mark the start and end of the error.
64
+ fn compile_error ( spans : ( Span , Span ) , error : String ) -> TokenStream {
65
+ let path = quote_spanned ! ( spans. 0 . into( ) => :: core:: compile_error) ;
66
+ quote_spanned ! ( spans. 1 . into( ) => #path!{ #error} )
68
67
}
0 commit comments