@@ -210,7 +210,7 @@ pub struct Tokenizer<'a> {
210
210
/// Counted in bytes, not code points. From 0.
211
211
position : usize ,
212
212
/// Cache for `source_location()`
213
- last_known_line_break : Cell < ( usize , usize ) > ,
213
+ last_known_source_location : Cell < ( SourcePosition , SourceLocation ) > ,
214
214
var_functions : SeenStatus ,
215
215
viewport_percentages : SeenStatus ,
216
216
}
@@ -229,7 +229,8 @@ impl<'a> Tokenizer<'a> {
229
229
Tokenizer {
230
230
input : input,
231
231
position : 0 ,
232
- last_known_line_break : Cell :: new ( ( 1 , 0 ) ) ,
232
+ last_known_source_location : Cell :: new ( ( SourcePosition ( 0 ) ,
233
+ SourceLocation { line : 1 , column : 1 } ) ) ,
233
234
var_functions : SeenStatus :: DontCare ,
234
235
viewport_percentages : SeenStatus :: DontCare ,
235
236
}
@@ -292,37 +293,33 @@ impl<'a> Tokenizer<'a> {
292
293
293
294
pub fn source_location ( & self , position : SourcePosition ) -> SourceLocation {
294
295
let target = position. 0 ;
295
- let mut line_number ;
296
+ let mut location ;
296
297
let mut position;
297
- let ( last_known_line_number , position_after_last_known_newline ) =
298
- self . last_known_line_break . get ( ) ;
299
- if target >= position_after_last_known_newline {
300
- position = position_after_last_known_newline ;
301
- line_number = last_known_line_number ;
298
+ let ( SourcePosition ( last_known_position ) , last_known_location ) =
299
+ self . last_known_source_location . get ( ) ;
300
+ if target >= last_known_position {
301
+ position = last_known_position ;
302
+ location = last_known_location ;
302
303
} else {
304
+ // For now we’re only traversing the source *forwards* to count newlines.
305
+ // So if the requested position is before the last known one,
306
+ // start over from the beginning.
303
307
position = 0 ;
304
- line_number = 1 ;
308
+ location = SourceLocation { line : 1 , column : 1 } ;
305
309
}
306
310
let mut source = & self . input [ position..target] ;
307
- while let Some ( newline_position) = source. find ( & [ '\n' , '\r' , '\x0C' ] [ .. ] ) {
311
+ while let Some ( newline_position) = source. find ( |c| matches ! ( c , '\n' | '\r' | '\x0C' ) ) {
308
312
let offset = newline_position +
309
- if source[ newline_position..] . starts_with ( "\r \n " ) {
310
- 2
311
- } else {
312
- 1
313
- } ;
313
+ if source[ newline_position..] . starts_with ( "\r \n " ) { 2 } else { 1 } ;
314
314
source = & source[ offset..] ;
315
315
position += offset;
316
- line_number += 1 ;
316
+ location. line += 1 ;
317
+ location. column = 1 ;
317
318
}
318
319
debug_assert ! ( position <= target) ;
319
- self . last_known_line_break . set ( ( line_number, position) ) ;
320
- SourceLocation {
321
- line : line_number,
322
- // `target == position` when `target` is at the beginning of the line,
323
- // so add 1 so that the column numbers start at 1.
324
- column : target - position + 1 ,
325
- }
320
+ location. column += target - position;
321
+ self . last_known_source_location . set ( ( SourcePosition ( target) , location) ) ;
322
+ location
326
323
}
327
324
328
325
#[ inline]
@@ -385,7 +382,7 @@ pub struct SourceLocation {
385
382
/// The line number, starting at 1 for the first line.
386
383
pub line : usize ,
387
384
388
- /// The column number within a line, starting at 1 for the character of the line.
385
+ /// The column number within a line, starting at 1 for first the character of the line.
389
386
pub column : usize ,
390
387
}
391
388
0 commit comments