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
|
//! FIXME: write short doc here
use std::{
path::{Path, PathBuf},
sync::Arc,
time::Instant,
};
use ra_db::{
salsa::{Database, Durability},
FileId, SourceDatabaseExt,
};
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol};
use crate::Result;
pub(crate) enum Op {
Highlight { path: PathBuf },
Complete { path: PathBuf, line: u32, column: u32 },
}
pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> {
let start = Instant::now();
eprint!("loading: ");
let (mut host, roots) = ra_batch::load_cargo(path)?;
let db = host.raw_database();
eprintln!("{:?}\n", start.elapsed());
let file_id = {
let path = match &op {
Op::Highlight { path } => path,
Op::Complete { path, .. } => path,
};
let path = std::env::current_dir()?.join(path).canonicalize()?;
roots
.iter()
.find_map(|(source_root_id, project_root)| {
if project_root.is_member() {
for file_id in db.source_root(*source_root_id).walk() {
let rel_path = db.file_relative_path(file_id);
let abs_path = rel_path.to_path(project_root.path());
if abs_path == path {
return Some(file_id);
}
}
}
None
})
.ok_or_else(|| format!("Can't find {:?}", path))?
};
match op {
Op::Highlight { .. } => {
let res = do_work(&mut host, file_id, |analysis| {
analysis.diagnostics(file_id).unwrap();
analysis.highlight_as_html(file_id, false).unwrap()
});
if verbose {
println!("\n{}", res);
}
}
Op::Complete { line, column, .. } => {
let offset = host
.analysis()
.file_line_index(file_id)?
.offset(LineCol { line, col_utf16: column });
let file_postion = FilePosition { file_id, offset };
let res = do_work(&mut host, file_id, |analysis| analysis.completions(file_postion));
if verbose {
println!("\n{:#?}", res);
}
}
}
Ok(())
}
fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, work: F) -> T {
{
let start = Instant::now();
eprint!("from scratch: ");
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("no change: ");
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("trivial change: ");
host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::LOW);
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("comment change: ");
{
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
text.push_str("\n/* Hello world */\n");
let mut change = AnalysisChange::new();
change.change_file(file_id, Arc::new(text));
host.apply_change(change);
}
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("const change: ");
host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::HIGH);
let res = work(&host.analysis());
eprintln!("{:?}", start.elapsed());
res
}
}
|