aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cli
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_cli')
-rw-r--r--crates/ra_cli/src/analysis_bench.rs92
-rw-r--r--crates/ra_cli/src/analysis_stats.rs19
-rw-r--r--crates/ra_cli/src/main.rs47
3 files changed, 149 insertions, 9 deletions
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
new file mode 100644
index 000000000..33d472838
--- /dev/null
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -0,0 +1,92 @@
1use std::{
2 path::{PathBuf, Path},
3 time::Instant,
4};
5
6use ra_db::{SourceDatabase, salsa::Database};
7use ra_ide_api::{AnalysisHost, Analysis, LineCol, FilePosition};
8
9use crate::Result;
10
11pub(crate) enum Op {
12 Highlight { path: PathBuf },
13 Complete { path: PathBuf, line: u32, column: u32 },
14}
15
16pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> {
17 let start = Instant::now();
18 eprint!("loading: ");
19 let (host, roots) = ra_batch::load_cargo(path)?;
20 let db = host.raw_database();
21 eprintln!("{:?}\n", start.elapsed());
22
23 let file_id = {
24 let path = match &op {
25 Op::Highlight { path } => path,
26 Op::Complete { path, .. } => path,
27 };
28 let path = std::env::current_dir()?.join(path).canonicalize()?;
29 roots
30 .iter()
31 .find_map(|(source_root_id, project_root)| {
32 if project_root.is_member() {
33 for (rel_path, file_id) in &db.source_root(*source_root_id).files {
34 let abs_path = rel_path.to_path(project_root.path());
35 if abs_path == path {
36 return Some(*file_id);
37 }
38 }
39 }
40 None
41 })
42 .ok_or_else(|| format!("Can't find {:?}", path))?
43 };
44
45 match op {
46 Op::Highlight { .. } => {
47 let res = do_work(&host, |analysis| {
48 analysis.diagnostics(file_id).unwrap();
49 analysis.highlight_as_html(file_id, false).unwrap()
50 });
51 if verbose {
52 println!("\n{}", res);
53 }
54 }
55 Op::Complete { line, column, .. } => {
56 let offset = host
57 .analysis()
58 .file_line_index(file_id)
59 .offset(LineCol { line, col_utf16: column });
60 let file_postion = FilePosition { file_id, offset };
61
62 let res = do_work(&host, |analysis| analysis.completions(file_postion));
63 if verbose {
64 println!("\n{:#?}", res);
65 }
66 }
67 }
68 Ok(())
69}
70
71fn do_work<F: Fn(&Analysis) -> T, T>(host: &AnalysisHost, work: F) -> T {
72 {
73 let start = Instant::now();
74 eprint!("from scratch: ");
75 work(&host.analysis());
76 eprintln!("{:?}", start.elapsed());
77 }
78 {
79 let start = Instant::now();
80 eprint!("no change: ");
81 work(&host.analysis());
82 eprintln!("{:?}", start.elapsed());
83 }
84 {
85 let start = Instant::now();
86 eprint!("trivial change: ");
87 host.raw_database().salsa_runtime().next_revision();
88 let res = work(&host.analysis());
89 eprintln!("{:?}", start.elapsed());
90 res
91 }
92}
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index d76c37d84..ed98fc7f6 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -1,4 +1,4 @@
1use std::{collections::HashSet, time::Instant, fmt::Write}; 1use std::{collections::HashSet, time::Instant, fmt::Write, path::Path};
2 2
3use ra_db::SourceDatabase; 3use ra_db::SourceDatabase;
4use ra_hir::{Crate, ModuleDef, Ty, ImplItem, HasSource}; 4use ra_hir::{Crate, ModuleDef, Ty, ImplItem, HasSource};
@@ -6,20 +6,23 @@ use ra_syntax::AstNode;
6 6
7use crate::Result; 7use crate::Result;
8 8
9pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> { 9pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> {
10 let db_load_time = Instant::now(); 10 let db_load_time = Instant::now();
11 let (host, roots) = ra_batch::load_cargo(path.as_ref())?; 11 let (host, roots) = ra_batch::load_cargo(path)?;
12 let db = host.raw_database(); 12 let db = host.raw_database();
13 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); 13 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
14 let analysis_time = Instant::now(); 14 let analysis_time = Instant::now();
15 let mut num_crates = 0; 15 let mut num_crates = 0;
16 let mut visited_modules = HashSet::new(); 16 let mut visited_modules = HashSet::new();
17 let mut visit_queue = Vec::new(); 17 let mut visit_queue = Vec::new();
18 for root in roots { 18 for (source_root_id, project_root) in roots {
19 for krate in Crate::source_root_crates(db, root) { 19 if project_root.is_member() {
20 num_crates += 1; 20 for krate in Crate::source_root_crates(db, source_root_id) {
21 let module = krate.root_module(db).expect("crate in source root without root module"); 21 num_crates += 1;
22 visit_queue.push(module); 22 let module =
23 krate.root_module(db).expect("crate in source root without root module");
24 visit_queue.push(module);
25 }
23 } 26 }
24 } 27 }
25 println!("Crates in this dir: {}", num_crates); 28 println!("Crates in this dir: {}", num_crates);
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 1db98aec1..5adf8b096 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -1,4 +1,5 @@
1mod analysis_stats; 1mod analysis_stats;
2mod analysis_bench;
2 3
3use std::{io::Read, error::Error}; 4use std::{io::Read, error::Error};
4 5
@@ -26,6 +27,27 @@ fn main() -> Result<()> {
26 .arg(Arg::with_name("only").short("o").takes_value(true)) 27 .arg(Arg::with_name("only").short("o").takes_value(true))
27 .arg(Arg::with_name("path")), 28 .arg(Arg::with_name("path")),
28 ) 29 )
30 .subcommand(
31 SubCommand::with_name("analysis-bench")
32 .arg(Arg::with_name("verbose").short("v").long("verbose"))
33 .arg(
34 Arg::with_name("highlight")
35 .long("highlight")
36 .takes_value(true)
37 .conflicts_with("complete")
38 .value_name("PATH")
39 .help("highlight this file"),
40 )
41 .arg(
42 Arg::with_name("complete")
43 .long("complete")
44 .takes_value(true)
45 .conflicts_with("highlight")
46 .value_name("PATH:LINE:COLUMN")
47 .help("compute completions at this location"),
48 )
49 .arg(Arg::with_name("path").value_name("PATH").help("project to analyze")),
50 )
29 .get_matches(); 51 .get_matches();
30 match matches.subcommand() { 52 match matches.subcommand() {
31 ("parse", Some(matches)) => { 53 ("parse", Some(matches)) => {
@@ -51,7 +73,25 @@ fn main() -> Result<()> {
51 let verbose = matches.is_present("verbose"); 73 let verbose = matches.is_present("verbose");
52 let path = matches.value_of("path").unwrap_or(""); 74 let path = matches.value_of("path").unwrap_or("");
53 let only = matches.value_of("only"); 75 let only = matches.value_of("only");
54 analysis_stats::run(verbose, path, only)?; 76 analysis_stats::run(verbose, path.as_ref(), only)?;
77 }
78 ("analysis-bench", Some(matches)) => {
79 let verbose = matches.is_present("verbose");
80 let path = matches.value_of("path").unwrap_or("");
81 let op = if let Some(path) = matches.value_of("highlight") {
82 analysis_bench::Op::Highlight { path: path.into() }
83 } else if let Some(path_line_col) = matches.value_of("complete") {
84 let (path_line, column) = rsplit_at_char(path_line_col, ':')?;
85 let (path, line) = rsplit_at_char(path_line, ':')?;
86 analysis_bench::Op::Complete {
87 path: path.into(),
88 line: line.parse()?,
89 column: column.parse()?,
90 }
91 } else {
92 panic!("either --highlight or --complete must be set")
93 };
94 analysis_bench::run(verbose, path.as_ref(), op)?;
55 } 95 }
56 _ => unreachable!(), 96 _ => unreachable!(),
57 } 97 }
@@ -68,3 +108,8 @@ fn read_stdin() -> Result<String> {
68 std::io::stdin().read_to_string(&mut buff)?; 108 std::io::stdin().read_to_string(&mut buff)?;
69 Ok(buff) 109 Ok(buff)
70} 110}
111
112fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> {
113 let idx = s.rfind(":").ok_or_else(|| format!("no `{}` in {}", c, s))?;
114 Ok((&s[..idx], &s[idx + 1..]))
115}