]> git.proxmox.com Git - rustc.git/blob - src/libsyntax_pos/caching_source_map_view.rs
New upstream version 1.41.1+dfsg1
[rustc.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 }