1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
use std::{
collections::HashMap,
time::Instant,
sync::Arc,
panic,
};
use once_cell::sync::OnceCell;
use rayon::prelude::*;
use libeditor::LineIndex;
use libsyntax2::File;
use {
FileId,
module_map::{ModuleMap, ChangeKind},
symbol_index::FileSymbols,
};
#[derive(Clone, Default, Debug)]
pub(crate) struct SourceRoot {
file_map: HashMap<FileId, Arc<(FileData, OnceCell<FileSymbols>)>>,
module_map: ModuleMap,
}
impl SourceRoot {
pub fn update(&mut self, file_id: FileId, text: Option<String>) {
let change_kind = if self.file_map.remove(&file_id).is_some() {
if text.is_some() {
ChangeKind::Update
} else {
ChangeKind::Delete
}
} else {
ChangeKind::Insert
};
self.module_map.update_file(file_id, change_kind);
self.file_map.remove(&file_id);
if let Some(text) = text {
let file_data = FileData::new(text);
self.file_map.insert(file_id, Arc::new((file_data, Default::default())));
}
}
pub fn module_map(&self) -> &ModuleMap {
&self.module_map
}
pub fn lines(&self, file_id: FileId) -> &LineIndex {
let data = self.data(file_id);
data.lines.get_or_init(|| LineIndex::new(&data.text))
}
pub fn syntax(&self, file_id: FileId) -> &File {
let data = self.data(file_id);
let text = &data.text;
let syntax = &data.syntax;
match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) {
Ok(file) => file,
Err(err) => {
error!("Parser paniced on:\n------\n{}\n------\n", &data.text);
panic::resume_unwind(err)
}
}
}
pub(crate) fn symbols(&self) -> Vec<&FileSymbols> {
self.file_map
.iter()
.map(|(&file_id, data)| symbols(file_id, data))
.collect()
}
pub fn reindex(&self) {
let now = Instant::now();
self.file_map
.par_iter()
.for_each(|(&file_id, data)| {
symbols(file_id, data);
});
info!("parallel indexing took {:?}", now.elapsed());
}
fn data(&self, file_id: FileId) -> &FileData {
match self.file_map.get(&file_id) {
Some(data) => &data.0,
None => panic!("unknown file: {:?}", file_id),
}
}
}
fn symbols(file_id: FileId, (data, symbols): &(FileData, OnceCell<FileSymbols>)) -> &FileSymbols {
let syntax = data.syntax_transient();
symbols.get_or_init(|| FileSymbols::new(file_id, &syntax))
}
#[derive(Debug)]
struct FileData {
text: String,
lines: OnceCell<LineIndex>,
syntax: OnceCell<File>,
}
impl FileData {
fn new(text: String) -> FileData {
FileData {
text,
syntax: OnceCell::new(),
lines: OnceCell::new(),
}
}
fn syntax_transient(&self) -> File {
self.syntax.get().map(|s| s.clone())
.unwrap_or_else(|| File::parse(&self.text))
}
}
// #[derive(Clone, Default, Debug)]
// pub(crate) struct ReadonlySourceRoot {
// data: Arc<ReadonlySourceRoot>
// }
// #[derive(Clone, Default, Debug)]
// pub(crate) struct ReadonlySourceRootInner {
// file_map: HashMap<FileId, FileData>,
// module_map: ModuleMap,
// }
|