]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_pos/caching_source_map_view.rs
Remove unchecked inline attribute, remove unused functions, make chache mod private...
[rust.git] / src / libsyntax_pos / caching_source_map_view.rs
1 use rustc_data_structures::sync::Lrc;
2 use crate::source_map::SourceMap;
3 use crate::{BytePos, SourceFile};
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(&mut self,
43                                     pos: BytePos)
44                                     -> Option<(Lrc<SourceFile>, usize, BytePos)> {
45         self.time_stamp += 1;
46
47         // Check if the position is in one of the cached lines
48         for cache_entry in self.line_cache.iter_mut() {
49             if pos >= cache_entry.line_start && pos < cache_entry.line_end {
50                 cache_entry.time_stamp = self.time_stamp;
51
52                 return Some((cache_entry.file.clone(),
53                              cache_entry.line_number,
54                              pos - cache_entry.line_start));
55             }
56         }
57
58         // No cache hit ...
59         let mut oldest = 0;
60         for index in 1 .. self.line_cache.len() {
61             if self.line_cache[index].time_stamp < self.line_cache[oldest].time_stamp {
62                 oldest = index;
63             }
64         }
65
66         let cache_entry = &mut self.line_cache[oldest];
67
68         // If the entry doesn't point to the correct file, fix it up
69         if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
70             let file_valid;
71             if self.source_map.files().len() > 0 {
72                 let file_index = self.source_map.lookup_source_file_idx(pos);
73                 let file = self.source_map.files()[file_index].clone();
74
75                 if pos >= file.start_pos && pos < file.end_pos {
76                     cache_entry.file = file;
77                     cache_entry.file_index = file_index;
78                     file_valid = true;
79                 } else {
80                     file_valid = false;
81                 }
82             } else {
83                 file_valid = false;
84             }
85
86             if !file_valid {
87                 return None;
88             }
89         }
90
91         let line_index = cache_entry.file.lookup_line(pos).unwrap();
92         let line_bounds = cache_entry.file.line_bounds(line_index);
93
94         cache_entry.line_number = line_index + 1;
95         cache_entry.line_start = line_bounds.0;
96         cache_entry.line_end = line_bounds.1;
97         cache_entry.time_stamp = self.time_stamp;
98
99         return Some((cache_entry.file.clone(),
100                      cache_entry.line_number,
101                      pos - cache_entry.line_start));
102     }
103 }