aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_cli/src')
-rw-r--r--crates/ra_cli/src/analysis_bench.rs4
-rw-r--r--crates/ra_cli/src/analysis_stats.rs9
-rw-r--r--crates/ra_cli/src/help.rs75
-rw-r--r--crates/ra_cli/src/load_cargo.rs153
-rw-r--r--crates/ra_cli/src/main.rs116
5 files changed, 258 insertions, 99 deletions
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
index 4835a68ce..3f10ed400 100644
--- a/crates/ra_cli/src/analysis_bench.rs
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -13,7 +13,7 @@ use ra_db::{
13}; 13};
14use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; 14use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol};
15 15
16use crate::Result; 16use crate::{load_cargo::load_cargo, Result};
17 17
18pub(crate) struct Position { 18pub(crate) struct Position {
19 path: PathBuf, 19 path: PathBuf,
@@ -46,7 +46,7 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> {
46 46
47 let start = Instant::now(); 47 let start = Instant::now();
48 eprint!("loading: "); 48 eprint!("loading: ");
49 let (mut host, roots) = ra_batch::load_cargo(path)?; 49 let (mut host, roots) = load_cargo(path)?;
50 let db = host.raw_database(); 50 let db = host.raw_database();
51 eprintln!("{:?}\n", start.elapsed()); 51 eprintln!("{:?}\n", start.elapsed());
52 52
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 6d2dd34c6..d40f04391 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -2,19 +2,18 @@
2 2
3use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; 3use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
4 4
5use itertools::Itertools;
6use rand::{seq::SliceRandom, thread_rng};
7
8use hir::{ 5use hir::{
9 db::{DefDatabase, HirDatabase}, 6 db::{DefDatabase, HirDatabase},
10 AssocItem, Crate, HasSource, HirDisplay, ModuleDef, 7 AssocItem, Crate, HasSource, HirDisplay, ModuleDef,
11}; 8};
12use hir_def::FunctionId; 9use hir_def::FunctionId;
13use hir_ty::{Ty, TypeWalk}; 10use hir_ty::{Ty, TypeWalk};
11use itertools::Itertools;
14use ra_db::SourceDatabaseExt; 12use ra_db::SourceDatabaseExt;
15use ra_syntax::AstNode; 13use ra_syntax::AstNode;
14use rand::{seq::SliceRandom, thread_rng};
16 15
17use crate::{progress_report::ProgressReport, Result, Verbosity}; 16use crate::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity};
18 17
19pub fn run( 18pub fn run(
20 verbosity: Verbosity, 19 verbosity: Verbosity,
@@ -25,7 +24,7 @@ pub fn run(
25 randomize: bool, 24 randomize: bool,
26) -> Result<()> { 25) -> Result<()> {
27 let db_load_time = Instant::now(); 26 let db_load_time = Instant::now();
28 let (mut host, roots) = ra_batch::load_cargo(path)?; 27 let (mut host, roots) = load_cargo(path)?;
29 let db = host.raw_database(); 28 let db = host.raw_database();
30 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); 29 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
31 let analysis_time = Instant::now(); 30 let analysis_time = Instant::now();
diff --git a/crates/ra_cli/src/help.rs b/crates/ra_cli/src/help.rs
deleted file mode 100644
index d3c4c7d0b..000000000
--- a/crates/ra_cli/src/help.rs
+++ /dev/null
@@ -1,75 +0,0 @@
1//! FIXME: write short doc here
2
3pub const GLOBAL_HELP: &str = "ra-cli
4
5USAGE:
6 ra_cli <SUBCOMMAND>
7
8FLAGS:
9 -h, --help Prints help information
10
11SUBCOMMANDS:
12 analysis-bench
13 analysis-stats
14 highlight
15 parse
16 symbols";
17
18pub const ANALYSIS_BENCH_HELP: &str = "ra_cli-analysis-bench
19
20USAGE:
21 ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH]
22
23FLAGS:
24 -h, --help Prints help information
25 -v, --verbose
26
27OPTIONS:
28 --complete <PATH:LINE:COLUMN> Compute completions at this location
29 --highlight <PATH> Hightlight this file
30
31ARGS:
32 <PATH> Project to analyse";
33
34pub const ANALYSIS_STATS_HELP: &str = "ra-cli-analysis-stats
35
36USAGE:
37 ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH]
38
39FLAGS:
40 -h, --help Prints help information
41 --memory-usage
42 -v, --verbose
43 -q, --quiet
44
45OPTIONS:
46 -o <ONLY>
47
48ARGS:
49 <PATH>";
50
51pub const HIGHLIGHT_HELP: &str = "ra-cli-highlight
52
53USAGE:
54 ra_cli highlight [FLAGS]
55
56FLAGS:
57 -h, --help Prints help information
58 -r, --rainbow";
59
60pub const SYMBOLS_HELP: &str = "ra-cli-symbols
61
62USAGE:
63 ra_cli highlight [FLAGS]
64
65FLAGS:
66 -h, --help Prints help inforamtion";
67
68pub const PARSE_HELP: &str = "ra-cli-parse
69
70USAGE:
71 ra_cli parse [FLAGS]
72
73FLAGS:
74 -h, --help Prints help inforamtion
75 --no-dump";
diff --git a/crates/ra_cli/src/load_cargo.rs b/crates/ra_cli/src/load_cargo.rs
new file mode 100644
index 000000000..2d6433f18
--- /dev/null
+++ b/crates/ra_cli/src/load_cargo.rs
@@ -0,0 +1,153 @@
1//! FIXME: write short doc here
2
3use std::{collections::HashSet, error::Error, path::Path};
4
5use rustc_hash::FxHashMap;
6
7use crossbeam_channel::{unbounded, Receiver};
8use ra_db::{CrateGraph, FileId, SourceRootId};
9use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags};
10use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
12use ra_vfs_glob::RustPackageFilterBuilder;
13
14type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
15
16fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
17 FileId(f.0)
18}
19fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
20 SourceRootId(r.0)
21}
22
23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
24 let root = std::env::current_dir()?.join(root);
25 let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
26 let project_roots = ws.to_roots();
27 let (sender, receiver) = unbounded();
28 let sender = Box::new(move |t| sender.send(t).unwrap());
29 let (mut vfs, roots) = Vfs::new(
30 project_roots
31 .iter()
32 .map(|pkg_root| {
33 RootEntry::new(
34 pkg_root.path().clone(),
35 RustPackageFilterBuilder::default()
36 .set_member(pkg_root.is_member())
37 .into_vfs_filter(),
38 )
39 })
40 .collect(),
41 sender,
42 Watch(false),
43 );
44
45 // FIXME: cfg options?
46 let default_cfg_options = {
47 let mut opts = get_rustc_cfg_options();
48 opts.insert_atom("test".into());
49 opts.insert_atom("debug_assertion".into());
50 opts
51 };
52
53 let (crate_graph, _crate_names) =
54 ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| {
55 let vfs_file = vfs.load(path);
56 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
57 vfs_file.map(vfs_file_to_id)
58 });
59 log::debug!("crate graph: {:?}", crate_graph);
60
61 let source_roots = roots
62 .iter()
63 .map(|&vfs_root| {
64 let source_root_id = vfs_root_to_id(vfs_root);
65 let project_root = project_roots
66 .iter()
67 .find(|it| it.path() == &vfs.root2path(vfs_root))
68 .unwrap()
69 .clone();
70 (source_root_id, project_root)
71 })
72 .collect::<FxHashMap<_, _>>();
73 let host = load(&source_roots, crate_graph, &mut vfs, receiver);
74 Ok((host, source_roots))
75}
76
77pub fn load(
78 source_roots: &FxHashMap<SourceRootId, PackageRoot>,
79 crate_graph: CrateGraph,
80 vfs: &mut Vfs,
81 receiver: Receiver<VfsTask>,
82) -> AnalysisHost {
83 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
84 let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
85 let mut analysis_change = AnalysisChange::new();
86 analysis_change.set_crate_graph(crate_graph);
87
88 // wait until Vfs has loaded all roots
89 let mut roots_loaded = HashSet::new();
90 for task in receiver {
91 vfs.handle_task(task);
92 let mut done = false;
93 for change in vfs.commit_changes() {
94 match change {
95 VfsChange::AddRoot { root, files } => {
96 let source_root_id = vfs_root_to_id(root);
97 let is_local = source_roots[&source_root_id].is_member();
98 log::debug!(
99 "loaded source root {:?} with path {:?}",
100 source_root_id,
101 vfs.root2path(root)
102 );
103 analysis_change.add_root(source_root_id, is_local);
104 analysis_change.set_debug_root_path(
105 source_root_id,
106 source_roots[&source_root_id].path().display().to_string(),
107 );
108
109 let mut file_map = FxHashMap::default();
110 for (vfs_file, path, text) in files {
111 let file_id = vfs_file_to_id(vfs_file);
112 analysis_change.add_file(source_root_id, file_id, path.clone(), text);
113 file_map.insert(path, file_id);
114 }
115 roots_loaded.insert(source_root_id);
116 if roots_loaded.len() == vfs.n_roots() {
117 done = true;
118 }
119 }
120 VfsChange::AddFile { root, file, path, text } => {
121 let source_root_id = vfs_root_to_id(root);
122 let file_id = vfs_file_to_id(file);
123 analysis_change.add_file(source_root_id, file_id, path, text);
124 }
125 VfsChange::RemoveFile { .. } | VfsChange::ChangeFile { .. } => {
126 // We just need the first scan, so just ignore these
127 }
128 }
129 }
130 if done {
131 break;
132 }
133 }
134
135 host.apply_change(analysis_change);
136 host
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 use hir::Crate;
144
145 #[test]
146 fn test_loading_rust_analyzer() {
147 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
148 let (host, _roots) = load_cargo(path).unwrap();
149 let n_crates = Crate::all(host.raw_database()).len();
150 // RA has quite a few crates, but the exact count doesn't matter
151 assert!(n_crates > 20);
152 }
153}
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 750cbab86..4a428faff 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -1,8 +1,8 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3mod load_cargo;
3mod analysis_stats; 4mod analysis_stats;
4mod analysis_bench; 5mod analysis_bench;
5mod help;
6mod progress_report; 6mod progress_report;
7 7
8use std::{error::Error, fmt::Write, io::Read}; 8use std::{error::Error, fmt::Write, io::Read};
@@ -40,21 +40,26 @@ impl Verbosity {
40fn main() -> Result<()> { 40fn main() -> Result<()> {
41 env_logger::try_init()?; 41 env_logger::try_init()?;
42 42
43 let subcommand = match std::env::args_os().nth(1) { 43 let mut matches = Arguments::from_env();
44 None => { 44 let subcommand = matches.subcommand()?.unwrap_or_default();
45 eprintln!("{}", help::GLOBAL_HELP);
46 return Ok(());
47 }
48 Some(s) => s,
49 };
50 let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect());
51 45
52 match &*subcommand.to_string_lossy() { 46 match subcommand.as_str() {
53 "parse" => { 47 "parse" => {
54 if matches.contains(["-h", "--help"]) { 48 if matches.contains(["-h", "--help"]) {
55 eprintln!("{}", help::PARSE_HELP); 49 eprintln!(
50 "\
51ra-cli-parse
52
53USAGE:
54 ra_cli parse [FLAGS]
55
56FLAGS:
57 -h, --help Prints help inforamtion
58 --no-dump"
59 );
56 return Ok(()); 60 return Ok(());
57 } 61 }
62
58 let no_dump = matches.contains("--no-dump"); 63 let no_dump = matches.contains("--no-dump");
59 matches.finish().or_else(handle_extra_flags)?; 64 matches.finish().or_else(handle_extra_flags)?;
60 65
@@ -67,10 +72,21 @@ fn main() -> Result<()> {
67 } 72 }
68 "symbols" => { 73 "symbols" => {
69 if matches.contains(["-h", "--help"]) { 74 if matches.contains(["-h", "--help"]) {
70 eprintln!("{}", help::SYMBOLS_HELP); 75 eprintln!(
76 "\
77ra-cli-symbols
78
79USAGE:
80 ra_cli highlight [FLAGS]
81
82FLAGS:
83 -h, --help Prints help inforamtion"
84 );
71 return Ok(()); 85 return Ok(());
72 } 86 }
87
73 matches.finish().or_else(handle_extra_flags)?; 88 matches.finish().or_else(handle_extra_flags)?;
89
74 let file = file()?; 90 let file = file()?;
75 for s in file_structure(&file) { 91 for s in file_structure(&file) {
76 println!("{:?}", s); 92 println!("{:?}", s);
@@ -78,20 +94,51 @@ fn main() -> Result<()> {
78 } 94 }
79 "highlight" => { 95 "highlight" => {
80 if matches.contains(["-h", "--help"]) { 96 if matches.contains(["-h", "--help"]) {
81 eprintln!("{}", help::HIGHLIGHT_HELP); 97 eprintln!(
98 "\
99ra-cli-highlight
100
101USAGE:
102 ra_cli highlight [FLAGS]
103
104FLAGS:
105 -h, --help Prints help information
106 -r, --rainbow"
107 );
82 return Ok(()); 108 return Ok(());
83 } 109 }
110
84 let rainbow_opt = matches.contains(["-r", "--rainbow"]); 111 let rainbow_opt = matches.contains(["-r", "--rainbow"]);
85 matches.finish().or_else(handle_extra_flags)?; 112 matches.finish().or_else(handle_extra_flags)?;
113
86 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); 114 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?);
87 let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap(); 115 let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap();
88 println!("{}", html); 116 println!("{}", html);
89 } 117 }
90 "analysis-stats" => { 118 "analysis-stats" => {
91 if matches.contains(["-h", "--help"]) { 119 if matches.contains(["-h", "--help"]) {
92 eprintln!("{}", help::ANALYSIS_STATS_HELP); 120 eprintln!(
121 "\
122ra-cli-analysis-stats
123
124USAGE:
125 ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH]
126
127FLAGS:
128 -h, --help Prints help information
129 --memory-usage
130 -v, --verbose
131 -q, --quiet
132
133OPTIONS:
134 -o <ONLY>
135
136ARGS:
137 <PATH>"
138 );
93 return Ok(()); 139 return Ok(());
94 } 140 }
141
95 let verbosity = match ( 142 let verbosity = match (
96 matches.contains(["-vv", "--spammy"]), 143 matches.contains(["-vv", "--spammy"]),
97 matches.contains(["-v", "--verbose"]), 144 matches.contains(["-v", "--verbose"]),
@@ -111,11 +158,11 @@ fn main() -> Result<()> {
111 let path = { 158 let path = {
112 let mut trailing = matches.free()?; 159 let mut trailing = matches.free()?;
113 if trailing.len() != 1 { 160 if trailing.len() != 1 {
114 eprintln!("{}", help::ANALYSIS_STATS_HELP);
115 Err("Invalid flags")?; 161 Err("Invalid flags")?;
116 } 162 }
117 trailing.pop().unwrap() 163 trailing.pop().unwrap()
118 }; 164 };
165
119 analysis_stats::run( 166 analysis_stats::run(
120 verbosity, 167 verbosity,
121 memory_usage, 168 memory_usage,
@@ -127,9 +174,27 @@ fn main() -> Result<()> {
127 } 174 }
128 "analysis-bench" => { 175 "analysis-bench" => {
129 if matches.contains(["-h", "--help"]) { 176 if matches.contains(["-h", "--help"]) {
130 eprintln!("{}", help::ANALYSIS_BENCH_HELP); 177 eprintln!(
178 "\
179ra_cli-analysis-bench
180
181USAGE:
182 ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH]
183
184FLAGS:
185 -h, --help Prints help information
186 -v, --verbose
187
188OPTIONS:
189 --complete <PATH:LINE:COLUMN> Compute completions at this location
190 --highlight <PATH> Hightlight this file
191
192ARGS:
193 <PATH> Project to analyse"
194 );
131 return Ok(()); 195 return Ok(());
132 } 196 }
197
133 let verbose = matches.contains(["-v", "--verbose"]); 198 let verbose = matches.contains(["-v", "--verbose"]);
134 let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default(); 199 let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default();
135 let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?; 200 let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?;
@@ -144,9 +209,26 @@ fn main() -> Result<()> {
144 ), 209 ),
145 }; 210 };
146 matches.finish().or_else(handle_extra_flags)?; 211 matches.finish().or_else(handle_extra_flags)?;
212
147 analysis_bench::run(verbose, path.as_ref(), op)?; 213 analysis_bench::run(verbose, path.as_ref(), op)?;
148 } 214 }
149 _ => eprintln!("{}", help::GLOBAL_HELP), 215 _ => eprintln!(
216 "\
217ra-cli
218
219USAGE:
220 ra_cli <SUBCOMMAND>
221
222FLAGS:
223 -h, --help Prints help information
224
225SUBCOMMANDS:
226 analysis-bench
227 analysis-stats
228 highlight
229 parse
230 symbols"
231 ),
150 } 232 }
151 Ok(()) 233 Ok(())
152} 234}