diff options
Diffstat (limited to 'crates/ra_cli/src')
-rw-r--r-- | crates/ra_cli/src/analysis_bench.rs | 62 | ||||
-rw-r--r-- | crates/ra_cli/src/load_cargo.rs | 7 | ||||
-rw-r--r-- | crates/ra_cli/src/main.rs | 314 |
3 files changed, 215 insertions, 168 deletions
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs index 3f10ed400..91fc55fe2 100644 --- a/crates/ra_cli/src/analysis_bench.rs +++ b/crates/ra_cli/src/analysis_bench.rs | |||
@@ -1,47 +1,17 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{ | 3 | use std::{path::Path, sync::Arc, time::Instant}; |
4 | path::{Path, PathBuf}, | ||
5 | str::FromStr, | ||
6 | sync::Arc, | ||
7 | time::Instant, | ||
8 | }; | ||
9 | 4 | ||
5 | use anyhow::format_err; | ||
10 | use ra_db::{ | 6 | use ra_db::{ |
11 | salsa::{Database, Durability}, | 7 | salsa::{Database, Durability}, |
12 | FileId, SourceDatabaseExt, | 8 | FileId, SourceDatabaseExt, |
13 | }; | 9 | }; |
14 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; | 10 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; |
15 | 11 | ||
16 | use crate::{load_cargo::load_cargo, Result}; | 12 | use crate::{load_cargo::load_cargo, BenchWhat, Result, Verbosity}; |
17 | |||
18 | pub(crate) struct Position { | ||
19 | path: PathBuf, | ||
20 | line: u32, | ||
21 | column: u32, | ||
22 | } | ||
23 | |||
24 | impl FromStr for Position { | ||
25 | type Err = Box<dyn std::error::Error + Send + Sync>; | ||
26 | fn from_str(s: &str) -> Result<Self> { | ||
27 | let (path_line, column) = rsplit_at_char(s, ':')?; | ||
28 | let (path, line) = rsplit_at_char(path_line, ':')?; | ||
29 | Ok(Position { path: path.into(), line: line.parse()?, column: column.parse()? }) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> { | ||
34 | let idx = s.rfind(':').ok_or_else(|| format!("no `{}` in {}", c, s))?; | ||
35 | Ok((&s[..idx], &s[idx + 1..])) | ||
36 | } | ||
37 | |||
38 | pub(crate) enum Op { | ||
39 | Highlight { path: PathBuf }, | ||
40 | Complete(Position), | ||
41 | GotoDef(Position), | ||
42 | } | ||
43 | 13 | ||
44 | pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | 14 | pub(crate) fn run(verbosity: Verbosity, path: &Path, what: BenchWhat) -> Result<()> { |
45 | ra_prof::init(); | 15 | ra_prof::init(); |
46 | 16 | ||
47 | let start = Instant::now(); | 17 | let start = Instant::now(); |
@@ -51,9 +21,9 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
51 | eprintln!("{:?}\n", start.elapsed()); | 21 | eprintln!("{:?}\n", start.elapsed()); |
52 | 22 | ||
53 | let file_id = { | 23 | let file_id = { |
54 | let path = match &op { | 24 | let path = match &what { |
55 | Op::Highlight { path } => path, | 25 | BenchWhat::Highlight { path } => path, |
56 | Op::Complete(pos) | Op::GotoDef(pos) => &pos.path, | 26 | BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => &pos.path, |
57 | }; | 27 | }; |
58 | let path = std::env::current_dir()?.join(path).canonicalize()?; | 28 | let path = std::env::current_dir()?.join(path).canonicalize()?; |
59 | roots | 29 | roots |
@@ -70,22 +40,22 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
70 | } | 40 | } |
71 | None | 41 | None |
72 | }) | 42 | }) |
73 | .ok_or_else(|| format!("Can't find {:?}", path))? | 43 | .ok_or_else(|| format_err!("Can't find {}", path.display()))? |
74 | }; | 44 | }; |
75 | 45 | ||
76 | match &op { | 46 | match &what { |
77 | Op::Highlight { .. } => { | 47 | BenchWhat::Highlight { .. } => { |
78 | let res = do_work(&mut host, file_id, |analysis| { | 48 | let res = do_work(&mut host, file_id, |analysis| { |
79 | analysis.diagnostics(file_id).unwrap(); | 49 | analysis.diagnostics(file_id).unwrap(); |
80 | analysis.highlight_as_html(file_id, false).unwrap() | 50 | analysis.highlight_as_html(file_id, false).unwrap() |
81 | }); | 51 | }); |
82 | if verbose { | 52 | if verbosity.is_verbose() { |
83 | println!("\n{}", res); | 53 | println!("\n{}", res); |
84 | } | 54 | } |
85 | } | 55 | } |
86 | Op::Complete(pos) | Op::GotoDef(pos) => { | 56 | BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => { |
87 | let is_completion = match op { | 57 | let is_completion = match what { |
88 | Op::Complete(..) => true, | 58 | BenchWhat::Complete(..) => true, |
89 | _ => false, | 59 | _ => false, |
90 | }; | 60 | }; |
91 | 61 | ||
@@ -98,13 +68,13 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
98 | if is_completion { | 68 | if is_completion { |
99 | let res = | 69 | let res = |
100 | do_work(&mut host, file_id, |analysis| analysis.completions(file_postion)); | 70 | do_work(&mut host, file_id, |analysis| analysis.completions(file_postion)); |
101 | if verbose { | 71 | if verbosity.is_verbose() { |
102 | println!("\n{:#?}", res); | 72 | println!("\n{:#?}", res); |
103 | } | 73 | } |
104 | } else { | 74 | } else { |
105 | let res = | 75 | let res = |
106 | do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_postion)); | 76 | do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_postion)); |
107 | if verbose { | 77 | if verbosity.is_verbose() { |
108 | println!("\n{:#?}", res); | 78 | println!("\n{:#?}", res); |
109 | } | 79 | } |
110 | } | 80 | } |
diff --git a/crates/ra_cli/src/load_cargo.rs b/crates/ra_cli/src/load_cargo.rs index 2d6433f18..b9a4e6aba 100644 --- a/crates/ra_cli/src/load_cargo.rs +++ b/crates/ra_cli/src/load_cargo.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{collections::HashSet, error::Error, path::Path}; | 3 | use std::{collections::HashSet, path::Path}; |
4 | |||
5 | use rustc_hash::FxHashMap; | ||
6 | 4 | ||
7 | use crossbeam_channel::{unbounded, Receiver}; | 5 | use crossbeam_channel::{unbounded, Receiver}; |
8 | use ra_db::{CrateGraph, FileId, SourceRootId}; | 6 | use ra_db::{CrateGraph, FileId, SourceRootId}; |
@@ -10,8 +8,9 @@ use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags}; | |||
10 | use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; | 8 | use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; |
11 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; | 9 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; |
12 | use ra_vfs_glob::RustPackageFilterBuilder; | 10 | use ra_vfs_glob::RustPackageFilterBuilder; |
11 | use rustc_hash::FxHashMap; | ||
13 | 12 | ||
14 | type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; | 13 | use anyhow::Result; |
15 | 14 | ||
16 | fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { | 15 | fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { |
17 | FileId(f.0) | 16 | FileId(f.0) |
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 4a428faff..4cf062f47 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs | |||
@@ -5,14 +5,82 @@ mod analysis_stats; | |||
5 | mod analysis_bench; | 5 | mod analysis_bench; |
6 | mod progress_report; | 6 | mod progress_report; |
7 | 7 | ||
8 | use std::{error::Error, fmt::Write, io::Read}; | 8 | use std::{fmt::Write, io::Read, path::PathBuf, str::FromStr}; |
9 | 9 | ||
10 | use pico_args::Arguments; | 10 | use pico_args::Arguments; |
11 | use ra_ide::{file_structure, Analysis}; | 11 | use ra_ide::{file_structure, Analysis}; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{AstNode, SourceFile}; | 13 | use ra_syntax::{AstNode, SourceFile}; |
14 | 14 | ||
15 | type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; | 15 | use anyhow::{bail, format_err, Result}; |
16 | |||
17 | fn main() -> Result<()> { | ||
18 | env_logger::try_init()?; | ||
19 | |||
20 | let command = match Command::from_env_args()? { | ||
21 | Ok(it) => it, | ||
22 | Err(HelpPrinted) => return Ok(()), | ||
23 | }; | ||
24 | match command { | ||
25 | Command::Parse { no_dump } => { | ||
26 | let _p = profile("parsing"); | ||
27 | let file = file()?; | ||
28 | if !no_dump { | ||
29 | println!("{:#?}", file.syntax()); | ||
30 | } | ||
31 | std::mem::forget(file); | ||
32 | } | ||
33 | Command::Symbols => { | ||
34 | let file = file()?; | ||
35 | for s in file_structure(&file) { | ||
36 | println!("{:?}", s); | ||
37 | } | ||
38 | } | ||
39 | Command::Highlight { rainbow } => { | ||
40 | let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); | ||
41 | let html = analysis.highlight_as_html(file_id, rainbow).unwrap(); | ||
42 | println!("{}", html); | ||
43 | } | ||
44 | Command::Stats { verbosity, randomize, memory_usage, only, with_deps, path } => { | ||
45 | analysis_stats::run( | ||
46 | verbosity, | ||
47 | memory_usage, | ||
48 | path.as_ref(), | ||
49 | only.as_ref().map(String::as_ref), | ||
50 | with_deps, | ||
51 | randomize, | ||
52 | )?; | ||
53 | } | ||
54 | Command::Bench { verbosity, path, what } => { | ||
55 | analysis_bench::run(verbosity, path.as_ref(), what)?; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | Ok(()) | ||
60 | } | ||
61 | |||
62 | enum Command { | ||
63 | Parse { | ||
64 | no_dump: bool, | ||
65 | }, | ||
66 | Symbols, | ||
67 | Highlight { | ||
68 | rainbow: bool, | ||
69 | }, | ||
70 | Stats { | ||
71 | verbosity: Verbosity, | ||
72 | randomize: bool, | ||
73 | memory_usage: bool, | ||
74 | only: Option<String>, | ||
75 | with_deps: bool, | ||
76 | path: PathBuf, | ||
77 | }, | ||
78 | Bench { | ||
79 | verbosity: Verbosity, | ||
80 | path: PathBuf, | ||
81 | what: BenchWhat, | ||
82 | }, | ||
83 | } | ||
16 | 84 | ||
17 | #[derive(Clone, Copy)] | 85 | #[derive(Clone, Copy)] |
18 | pub enum Verbosity { | 86 | pub enum Verbosity { |
@@ -37,17 +105,57 @@ impl Verbosity { | |||
37 | } | 105 | } |
38 | } | 106 | } |
39 | 107 | ||
40 | fn main() -> Result<()> { | 108 | enum BenchWhat { |
41 | env_logger::try_init()?; | 109 | Highlight { path: PathBuf }, |
110 | Complete(Position), | ||
111 | GotoDef(Position), | ||
112 | } | ||
42 | 113 | ||
43 | let mut matches = Arguments::from_env(); | 114 | pub(crate) struct Position { |
44 | let subcommand = matches.subcommand()?.unwrap_or_default(); | 115 | path: PathBuf, |
116 | line: u32, | ||
117 | column: u32, | ||
118 | } | ||
45 | 119 | ||
46 | match subcommand.as_str() { | 120 | impl FromStr for Position { |
47 | "parse" => { | 121 | type Err = anyhow::Error; |
48 | if matches.contains(["-h", "--help"]) { | 122 | fn from_str(s: &str) -> Result<Self> { |
49 | eprintln!( | 123 | let (path_line, column) = rsplit_at_char(s, ':')?; |
50 | "\ | 124 | let (path, line) = rsplit_at_char(path_line, ':')?; |
125 | Ok(Position { path: path.into(), line: line.parse()?, column: column.parse()? }) | ||
126 | } | ||
127 | } | ||
128 | |||
129 | fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> { | ||
130 | let idx = s.rfind(c).ok_or_else(|| format_err!("no `{}` in {}", c, s))?; | ||
131 | Ok((&s[..idx], &s[idx + 1..])) | ||
132 | } | ||
133 | |||
134 | struct HelpPrinted; | ||
135 | |||
136 | impl Command { | ||
137 | fn from_env_args() -> Result<Result<Command, HelpPrinted>> { | ||
138 | let mut matches = Arguments::from_env(); | ||
139 | let subcommand = matches.subcommand()?.unwrap_or_default(); | ||
140 | |||
141 | let verbosity = match ( | ||
142 | matches.contains(["-vv", "--spammy"]), | ||
143 | matches.contains(["-v", "--verbose"]), | ||
144 | matches.contains(["-q", "--quiet"]), | ||
145 | ) { | ||
146 | (true, _, true) => bail!("Invalid flags: -q conflicts with -vv"), | ||
147 | (true, _, false) => Verbosity::Spammy, | ||
148 | (false, false, false) => Verbosity::Normal, | ||
149 | (false, false, true) => Verbosity::Quiet, | ||
150 | (false, true, false) => Verbosity::Verbose, | ||
151 | (false, true, true) => bail!("Invalid flags: -q conflicts with -v"), | ||
152 | }; | ||
153 | |||
154 | let command = match subcommand.as_str() { | ||
155 | "parse" => { | ||
156 | if matches.contains(["-h", "--help"]) { | ||
157 | eprintln!( | ||
158 | "\ | ||
51 | ra-cli-parse | 159 | ra-cli-parse |
52 | 160 | ||
53 | USAGE: | 161 | USAGE: |
@@ -56,24 +164,18 @@ USAGE: | |||
56 | FLAGS: | 164 | FLAGS: |
57 | -h, --help Prints help inforamtion | 165 | -h, --help Prints help inforamtion |
58 | --no-dump" | 166 | --no-dump" |
59 | ); | 167 | ); |
60 | return Ok(()); | 168 | return Ok(Err(HelpPrinted)); |
61 | } | 169 | } |
62 | |||
63 | let no_dump = matches.contains("--no-dump"); | ||
64 | matches.finish().or_else(handle_extra_flags)?; | ||
65 | 170 | ||
66 | let _p = profile("parsing"); | 171 | let no_dump = matches.contains("--no-dump"); |
67 | let file = file()?; | 172 | matches.finish().or_else(handle_extra_flags)?; |
68 | if !no_dump { | 173 | Command::Parse { no_dump } |
69 | println!("{:#?}", file.syntax()); | ||
70 | } | 174 | } |
71 | std::mem::forget(file); | 175 | "symbols" => { |
72 | } | 176 | if matches.contains(["-h", "--help"]) { |
73 | "symbols" => { | 177 | eprintln!( |
74 | if matches.contains(["-h", "--help"]) { | 178 | "\ |
75 | eprintln!( | ||
76 | "\ | ||
77 | ra-cli-symbols | 179 | ra-cli-symbols |
78 | 180 | ||
79 | USAGE: | 181 | USAGE: |
@@ -81,21 +183,18 @@ USAGE: | |||
81 | 183 | ||
82 | FLAGS: | 184 | FLAGS: |
83 | -h, --help Prints help inforamtion" | 185 | -h, --help Prints help inforamtion" |
84 | ); | 186 | ); |
85 | return Ok(()); | 187 | return Ok(Err(HelpPrinted)); |
86 | } | 188 | } |
87 | 189 | ||
88 | matches.finish().or_else(handle_extra_flags)?; | 190 | matches.finish().or_else(handle_extra_flags)?; |
89 | 191 | ||
90 | let file = file()?; | 192 | Command::Symbols |
91 | for s in file_structure(&file) { | ||
92 | println!("{:?}", s); | ||
93 | } | 193 | } |
94 | } | 194 | "highlight" => { |
95 | "highlight" => { | 195 | if matches.contains(["-h", "--help"]) { |
96 | if matches.contains(["-h", "--help"]) { | 196 | eprintln!( |
97 | eprintln!( | 197 | "\ |
98 | "\ | ||
99 | ra-cli-highlight | 198 | ra-cli-highlight |
100 | 199 | ||
101 | USAGE: | 200 | USAGE: |
@@ -104,21 +203,18 @@ USAGE: | |||
104 | FLAGS: | 203 | FLAGS: |
105 | -h, --help Prints help information | 204 | -h, --help Prints help information |
106 | -r, --rainbow" | 205 | -r, --rainbow" |
107 | ); | 206 | ); |
108 | return Ok(()); | 207 | return Ok(Err(HelpPrinted)); |
109 | } | 208 | } |
110 | |||
111 | let rainbow_opt = matches.contains(["-r", "--rainbow"]); | ||
112 | matches.finish().or_else(handle_extra_flags)?; | ||
113 | 209 | ||
114 | let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); | 210 | let rainbow = matches.contains(["-r", "--rainbow"]); |
115 | let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap(); | 211 | matches.finish().or_else(handle_extra_flags)?; |
116 | println!("{}", html); | 212 | Command::Highlight { rainbow } |
117 | } | 213 | } |
118 | "analysis-stats" => { | 214 | "analysis-stats" => { |
119 | if matches.contains(["-h", "--help"]) { | 215 | if matches.contains(["-h", "--help"]) { |
120 | eprintln!( | 216 | eprintln!( |
121 | "\ | 217 | "\ |
122 | ra-cli-analysis-stats | 218 | ra-cli-analysis-stats |
123 | 219 | ||
124 | USAGE: | 220 | USAGE: |
@@ -135,47 +231,28 @@ OPTIONS: | |||
135 | 231 | ||
136 | ARGS: | 232 | ARGS: |
137 | <PATH>" | 233 | <PATH>" |
138 | ); | 234 | ); |
139 | return Ok(()); | 235 | return Ok(Err(HelpPrinted)); |
140 | } | ||
141 | |||
142 | let verbosity = match ( | ||
143 | matches.contains(["-vv", "--spammy"]), | ||
144 | matches.contains(["-v", "--verbose"]), | ||
145 | matches.contains(["-q", "--quiet"]), | ||
146 | ) { | ||
147 | (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?, | ||
148 | (true, _, false) => Verbosity::Spammy, | ||
149 | (false, false, false) => Verbosity::Normal, | ||
150 | (false, false, true) => Verbosity::Quiet, | ||
151 | (false, true, false) => Verbosity::Verbose, | ||
152 | (false, true, true) => Err("Invalid flags: -q conflicts with -v")?, | ||
153 | }; | ||
154 | let randomize = matches.contains("--randomize"); | ||
155 | let memory_usage = matches.contains("--memory-usage"); | ||
156 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; | ||
157 | let with_deps: bool = matches.contains("--with-deps"); | ||
158 | let path = { | ||
159 | let mut trailing = matches.free()?; | ||
160 | if trailing.len() != 1 { | ||
161 | Err("Invalid flags")?; | ||
162 | } | 236 | } |
163 | trailing.pop().unwrap() | ||
164 | }; | ||
165 | 237 | ||
166 | analysis_stats::run( | 238 | let randomize = matches.contains("--randomize"); |
167 | verbosity, | 239 | let memory_usage = matches.contains("--memory-usage"); |
168 | memory_usage, | 240 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; |
169 | path.as_ref(), | 241 | let with_deps: bool = matches.contains("--with-deps"); |
170 | only.as_ref().map(String::as_ref), | 242 | let path = { |
171 | with_deps, | 243 | let mut trailing = matches.free()?; |
172 | randomize, | 244 | if trailing.len() != 1 { |
173 | )?; | 245 | bail!("Invalid flags"); |
174 | } | 246 | } |
175 | "analysis-bench" => { | 247 | trailing.pop().unwrap().into() |
176 | if matches.contains(["-h", "--help"]) { | 248 | }; |
177 | eprintln!( | 249 | |
178 | "\ | 250 | Command::Stats { verbosity, randomize, memory_usage, only, with_deps, path } |
251 | } | ||
252 | "analysis-bench" => { | ||
253 | if matches.contains(["-h", "--help"]) { | ||
254 | eprintln!( | ||
255 | "\ | ||
179 | ra_cli-analysis-bench | 256 | ra_cli-analysis-bench |
180 | 257 | ||
181 | USAGE: | 258 | USAGE: |
@@ -191,29 +268,27 @@ OPTIONS: | |||
191 | 268 | ||
192 | ARGS: | 269 | ARGS: |
193 | <PATH> Project to analyse" | 270 | <PATH> Project to analyse" |
194 | ); | 271 | ); |
195 | return Ok(()); | 272 | return Ok(Err(HelpPrinted)); |
196 | } | 273 | } |
197 | 274 | ||
198 | let verbose = matches.contains(["-v", "--verbose"]); | 275 | let path: PathBuf = matches.opt_value_from_str("--path")?.unwrap_or_default(); |
199 | let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default(); | 276 | let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?; |
200 | let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?; | 277 | let complete_path: Option<Position> = matches.opt_value_from_str("--complete")?; |
201 | let complete_path: Option<String> = matches.opt_value_from_str("--complete")?; | 278 | let goto_def_path: Option<Position> = matches.opt_value_from_str("--goto-def")?; |
202 | let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?; | 279 | let what = match (highlight_path, complete_path, goto_def_path) { |
203 | let op = match (highlight_path, complete_path, goto_def_path) { | 280 | (Some(path), None, None) => BenchWhat::Highlight { path: path.into() }, |
204 | (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() }, | 281 | (None, Some(position), None) => BenchWhat::Complete(position), |
205 | (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?), | 282 | (None, None, Some(position)) => BenchWhat::GotoDef(position), |
206 | (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?), | 283 | _ => panic!( |
207 | _ => panic!( | 284 | "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" |
208 | "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" | 285 | ), |
209 | ), | 286 | }; |
210 | }; | 287 | Command::Bench { verbosity, path, what } |
211 | matches.finish().or_else(handle_extra_flags)?; | 288 | } |
212 | 289 | _ => { | |
213 | analysis_bench::run(verbose, path.as_ref(), op)?; | 290 | eprintln!( |
214 | } | 291 | "\ |
215 | _ => eprintln!( | ||
216 | "\ | ||
217 | ra-cli | 292 | ra-cli |
218 | 293 | ||
219 | USAGE: | 294 | USAGE: |
@@ -228,9 +303,12 @@ SUBCOMMANDS: | |||
228 | highlight | 303 | highlight |
229 | parse | 304 | parse |
230 | symbols" | 305 | symbols" |
231 | ), | 306 | ); |
307 | return Ok(Err(HelpPrinted)); | ||
308 | } | ||
309 | }; | ||
310 | Ok(Ok(command)) | ||
232 | } | 311 | } |
233 | Ok(()) | ||
234 | } | 312 | } |
235 | 313 | ||
236 | fn handle_extra_flags(e: pico_args::Error) -> Result<()> { | 314 | fn handle_extra_flags(e: pico_args::Error) -> Result<()> { |
@@ -240,9 +318,9 @@ fn handle_extra_flags(e: pico_args::Error) -> Result<()> { | |||
240 | write!(&mut invalid_flags, "{}, ", flag)?; | 318 | write!(&mut invalid_flags, "{}, ", flag)?; |
241 | } | 319 | } |
242 | let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2); | 320 | let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2); |
243 | Err(format!("Invalid flags: {}", invalid_flags).into()) | 321 | bail!("Invalid flags: {}", invalid_flags); |
244 | } else { | 322 | } else { |
245 | Err(e.to_string().into()) | 323 | bail!(e); |
246 | } | 324 | } |
247 | } | 325 | } |
248 | 326 | ||