]> git.lizzy.rs Git - rust.git/blob - src/librustc_span/caching_source_map_view.rs
Rollup merge of #68421 - ehuss:update-cargo-books, r=alexcrichton
[rust.git] / src / librustc_span / caching_source_map_view.rs
1 use crate::source_map::SourceMap;
2 use crate::{BytePos, SourceFile};
3 use rustc_data_structures::sync::Lrc;
4
5 #[derive(Clone)]
6 struct CacheEntry {
7     time_stamp: usize,
8     line_number: usize,
9     line_start: BytePos,
10     line_end: BytePos,
11     file: Lrc<SourceFile>,
12     file_index: usize,
13 }
14
15 #[derive(Clone)]
16 pub struct CachingSourceMapView<'cm> {
17     source_map: &'cm SourceMap,
18     line_cache: [CacheEntry; 3],
19     time_stamp: usize,
20 }
21
22 impl<'cm> CachingSourceMapView<'cm> {
23     pub fn new(source_map: &'cm SourceMap) -> CachingSourceMapView<'cm> {
24         let files = source_map.files();
25         let first_file = files[0].clone();
26         let entry = CacheEntry {
27             time_stamp: 0,
28             line_number: 0,
29             line_start: BytePos(0),
30             line_end: BytePos(0),
31             file: first_file,
32             file_index: 0,
33         };
34
35         CachingSourceMapView {
36             source_map,
37             line_cache: [entry.clone(), entry.clone(), entry],
38             time_stamp: 0,
39         }
40     }
41
42     pub fn byte_pos_to_line_and_col(
43         &mut self,
44         pos: BytePos,
45     ) -> Option<(Lrc<SourceFile>, usize, BytePos)> {
46         self.time_stamp += 1;
47
48         // Check if the position is in one of the cached lines
49         for cache_entry in self.line_cache.iter_mut() {
50             if pos >= cache_entry.line_start && pos < cache_entry.line_end {
51                 cache_entry.time_stamp = self.time_stamp;
52
53                 return Some((
54                     cache_entry.file.clone(),
55                     cache_entry.line_number,
56                     pos - cache_entry.line_start,
57                 ));
58             }
59         }
60
61         // No cache hit ...
62         let mut oldest = 0;
63         for index in 1..self.line_cache.len() {
64             if self.line_cache[index].time_stamp < self.line_cache[oldest].time_stamp {
65                 oldest = index;
66             }
67         }
68
69         let cache_entry = &mut self.line_cache[oldest];
70
71         // If the entry doesn't point to the correct file, fix it up
72         if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
73             let file_valid;
74             if self.source_map.files().len() > 0 {
75                 let file_index = self.source_map.lookup_source_file_idx(pos);
76                 let file = self.source_map.files()[file_index].clone();
77
78                 if pos >= file.start_pos && pos < file.end_pos {
79                     cache_entry.file = file;
80                     cache_entry.file_index = file_index;
81                     file_valid = true;
82                 } else {
83                     file_valid = false;
84                 }
85             } else {
86                 file_valid = false;
87             }
88
89             if !file_valid {
90                 return None;
91             }
92         }
93
94         let line_index = cache_entry.file.lookup_line(pos).unwrap();
95         let line_bounds = cache_entry.file.line_bounds(line_index);
96
97         cache_entry.line_number = line_index + 1;
98         cache_entry.line_start = line_bounds.0;
99         cache_entry.line_end = line_bounds.1;
100         cache_entry.time_stamp = self.time_stamp;
101
102         return Some((
103             cache_entry.file.clone(),
104             cache_entry.line_number,
105             pos - cache_entry.line_start,
106         ));
107     }
108 }