]> git.lizzy.rs Git - rust.git/blob - src/librustc/ich/caching_codemap_view.rs
Add invalid unary operator usage error code
[rust.git] / src / librustc / ich / caching_codemap_view.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use dep_graph::{DepGraph, DepNode};
12 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
13 use rustc_data_structures::bitvec::BitVector;
14 use std::rc::Rc;
15 use std::sync::Arc;
16 use syntax::codemap::CodeMap;
17 use syntax_pos::{BytePos, FileMap};
18 use ty::TyCtxt;
19
20 #[derive(Clone)]
21 struct CacheEntry {
22     time_stamp: usize,
23     line_number: usize,
24     line_start: BytePos,
25     line_end: BytePos,
26     file: Rc<FileMap>,
27     file_index: usize,
28 }
29
30 pub struct CachingCodemapView<'tcx> {
31     codemap: &'tcx CodeMap,
32     line_cache: [CacheEntry; 3],
33     time_stamp: usize,
34     dep_graph: DepGraph,
35     dep_tracking_reads: BitVector,
36 }
37
38 impl<'tcx> CachingCodemapView<'tcx> {
39     pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> {
40         let codemap = tcx.sess.codemap();
41         let files = codemap.files_untracked();
42         let first_file = files[0].clone();
43         let entry = CacheEntry {
44             time_stamp: 0,
45             line_number: 0,
46             line_start: BytePos(0),
47             line_end: BytePos(0),
48             file: first_file,
49             file_index: 0,
50         };
51
52         CachingCodemapView {
53             dep_graph: tcx.dep_graph.clone(),
54             codemap: codemap,
55             line_cache: [entry.clone(), entry.clone(), entry.clone()],
56             time_stamp: 0,
57             dep_tracking_reads: BitVector::new(files.len()),
58         }
59     }
60
61     pub fn byte_pos_to_line_and_col(&mut self,
62                                     pos: BytePos)
63                                     -> Option<(Rc<FileMap>, usize, BytePos)> {
64         self.time_stamp += 1;
65
66         // Check if the position is in one of the cached lines
67         for cache_entry in self.line_cache.iter_mut() {
68             if pos >= cache_entry.line_start && pos < cache_entry.line_end {
69                 cache_entry.time_stamp = self.time_stamp;
70                 if self.dep_tracking_reads.insert(cache_entry.file_index) {
71                     self.dep_graph.read(dep_node(cache_entry));
72                 }
73
74                 return Some((cache_entry.file.clone(),
75                              cache_entry.line_number,
76                              pos - cache_entry.line_start));
77             }
78         }
79
80         // No cache hit ...
81         let mut oldest = 0;
82         for index in 1 .. self.line_cache.len() {
83             if self.line_cache[index].time_stamp < self.line_cache[oldest].time_stamp {
84                 oldest = index;
85             }
86         }
87
88         let cache_entry = &mut self.line_cache[oldest];
89
90         // If the entry doesn't point to the correct file, fix it up
91         if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
92             let file_valid;
93             let files = self.codemap.files_untracked();
94
95             if files.len() > 0 {
96                 let file_index = self.codemap.lookup_filemap_idx(pos);
97                 let file = files[file_index].clone();
98
99                 if pos >= file.start_pos && pos < file.end_pos {
100                     cache_entry.file = file;
101                     cache_entry.file_index = file_index;
102                     file_valid = true;
103                 } else {
104                     file_valid = false;
105                 }
106             } else {
107                 file_valid = false;
108             }
109
110             if !file_valid {
111                 return None;
112             }
113         }
114
115         let line_index = cache_entry.file.lookup_line(pos).unwrap();
116         let line_bounds = cache_entry.file.line_bounds(line_index);
117
118         cache_entry.line_number = line_index + 1;
119         cache_entry.line_start = line_bounds.0;
120         cache_entry.line_end = line_bounds.1;
121         cache_entry.time_stamp = self.time_stamp;
122
123         if self.dep_tracking_reads.insert(cache_entry.file_index) {
124             self.dep_graph.read(dep_node(cache_entry));
125         }
126
127         return Some((cache_entry.file.clone(),
128                      cache_entry.line_number,
129                      pos - cache_entry.line_start));
130     }
131 }
132
133 fn dep_node(cache_entry: &CacheEntry) -> DepNode<DefId> {
134     let def_id = DefId {
135         krate: CrateNum::from_u32(cache_entry.file.crate_of_origin),
136         index: CRATE_DEF_INDEX,
137     };
138     let name = Arc::new(cache_entry.file.name.clone());
139     DepNode::FileMap(def_id, name)
140 }