aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cli/src/main.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-17 18:03:03 +0000
committerAleksey Kladov <[email protected]>2020-02-17 18:03:03 +0000
commit659b0e73cfd9ef7755d032f90622a08576f1d86d (patch)
tree238a2cb3e021502608d357785ebbe3b21f94573f /crates/ra_cli/src/main.rs
parent2d1b3da5fb69d932c65884a361ec10d81e8a51d8 (diff)
Merge cli and ra_lsp_server
Diffstat (limited to 'crates/ra_cli/src/main.rs')
-rw-r--r--crates/ra_cli/src/main.rs336
1 files changed, 0 insertions, 336 deletions
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
deleted file mode 100644
index 4cf062f47..000000000
--- a/crates/ra_cli/src/main.rs
+++ /dev/null
@@ -1,336 +0,0 @@
1//! FIXME: write short doc here
2
3mod load_cargo;
4mod analysis_stats;
5mod analysis_bench;
6mod progress_report;
7
8use std::{fmt::Write, io::Read, path::PathBuf, str::FromStr};
9
10use pico_args::Arguments;
11use ra_ide::{file_structure, Analysis};
12use ra_prof::profile;
13use ra_syntax::{AstNode, SourceFile};
14
15use anyhow::{bail, format_err, Result};
16
17fn 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
62enum 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}
84
85#[derive(Clone, Copy)]
86pub enum Verbosity {
87 Spammy,
88 Verbose,
89 Normal,
90 Quiet,
91}
92
93impl Verbosity {
94 fn is_verbose(self) -> bool {
95 match self {
96 Verbosity::Verbose | Verbosity::Spammy => true,
97 _ => false,
98 }
99 }
100 fn is_spammy(self) -> bool {
101 match self {
102 Verbosity::Spammy => true,
103 _ => false,
104 }
105 }
106}
107
108enum BenchWhat {
109 Highlight { path: PathBuf },
110 Complete(Position),
111 GotoDef(Position),
112}
113
114pub(crate) struct Position {
115 path: PathBuf,
116 line: u32,
117 column: u32,
118}
119
120impl FromStr for Position {
121 type Err = anyhow::Error;
122 fn from_str(s: &str) -> Result<Self> {
123 let (path_line, column) = rsplit_at_char(s, ':')?;
124 let (path, line) = rsplit_at_char(path_line, ':')?;
125 Ok(Position { path: path.into(), line: line.parse()?, column: column.parse()? })
126 }
127}
128
129fn 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
134struct HelpPrinted;
135
136impl 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 "\
159ra-cli-parse
160
161USAGE:
162 ra_cli parse [FLAGS]
163
164FLAGS:
165 -h, --help Prints help inforamtion
166 --no-dump"
167 );
168 return Ok(Err(HelpPrinted));
169 }
170
171 let no_dump = matches.contains("--no-dump");
172 matches.finish().or_else(handle_extra_flags)?;
173 Command::Parse { no_dump }
174 }
175 "symbols" => {
176 if matches.contains(["-h", "--help"]) {
177 eprintln!(
178 "\
179ra-cli-symbols
180
181USAGE:
182 ra_cli highlight [FLAGS]
183
184FLAGS:
185 -h, --help Prints help inforamtion"
186 );
187 return Ok(Err(HelpPrinted));
188 }
189
190 matches.finish().or_else(handle_extra_flags)?;
191
192 Command::Symbols
193 }
194 "highlight" => {
195 if matches.contains(["-h", "--help"]) {
196 eprintln!(
197 "\
198ra-cli-highlight
199
200USAGE:
201 ra_cli highlight [FLAGS]
202
203FLAGS:
204 -h, --help Prints help information
205 -r, --rainbow"
206 );
207 return Ok(Err(HelpPrinted));
208 }
209
210 let rainbow = matches.contains(["-r", "--rainbow"]);
211 matches.finish().or_else(handle_extra_flags)?;
212 Command::Highlight { rainbow }
213 }
214 "analysis-stats" => {
215 if matches.contains(["-h", "--help"]) {
216 eprintln!(
217 "\
218ra-cli-analysis-stats
219
220USAGE:
221 ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH]
222
223FLAGS:
224 -h, --help Prints help information
225 --memory-usage
226 -v, --verbose
227 -q, --quiet
228
229OPTIONS:
230 -o <ONLY>
231
232ARGS:
233 <PATH>"
234 );
235 return Ok(Err(HelpPrinted));
236 }
237
238 let randomize = matches.contains("--randomize");
239 let memory_usage = matches.contains("--memory-usage");
240 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
241 let with_deps: bool = matches.contains("--with-deps");
242 let path = {
243 let mut trailing = matches.free()?;
244 if trailing.len() != 1 {
245 bail!("Invalid flags");
246 }
247 trailing.pop().unwrap().into()
248 };
249
250 Command::Stats { verbosity, randomize, memory_usage, only, with_deps, path }
251 }
252 "analysis-bench" => {
253 if matches.contains(["-h", "--help"]) {
254 eprintln!(
255 "\
256ra_cli-analysis-bench
257
258USAGE:
259 ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH]
260
261FLAGS:
262 -h, --help Prints help information
263 -v, --verbose
264
265OPTIONS:
266 --complete <PATH:LINE:COLUMN> Compute completions at this location
267 --highlight <PATH> Hightlight this file
268
269ARGS:
270 <PATH> Project to analyse"
271 );
272 return Ok(Err(HelpPrinted));
273 }
274
275 let path: PathBuf = matches.opt_value_from_str("--path")?.unwrap_or_default();
276 let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?;
277 let complete_path: Option<Position> = matches.opt_value_from_str("--complete")?;
278 let goto_def_path: Option<Position> = matches.opt_value_from_str("--goto-def")?;
279 let what = match (highlight_path, complete_path, goto_def_path) {
280 (Some(path), None, None) => BenchWhat::Highlight { path: path.into() },
281 (None, Some(position), None) => BenchWhat::Complete(position),
282 (None, None, Some(position)) => BenchWhat::GotoDef(position),
283 _ => panic!(
284 "exactly one of `--highlight`, `--complete` or `--goto-def` must be set"
285 ),
286 };
287 Command::Bench { verbosity, path, what }
288 }
289 _ => {
290 eprintln!(
291 "\
292ra-cli
293
294USAGE:
295 ra_cli <SUBCOMMAND>
296
297FLAGS:
298 -h, --help Prints help information
299
300SUBCOMMANDS:
301 analysis-bench
302 analysis-stats
303 highlight
304 parse
305 symbols"
306 );
307 return Ok(Err(HelpPrinted));
308 }
309 };
310 Ok(Ok(command))
311 }
312}
313
314fn handle_extra_flags(e: pico_args::Error) -> Result<()> {
315 if let pico_args::Error::UnusedArgsLeft(flags) = e {
316 let mut invalid_flags = String::new();
317 for flag in flags {
318 write!(&mut invalid_flags, "{}, ", flag)?;
319 }
320 let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2);
321 bail!("Invalid flags: {}", invalid_flags);
322 } else {
323 bail!(e);
324 }
325}
326
327fn file() -> Result<SourceFile> {
328 let text = read_stdin()?;
329 Ok(SourceFile::parse(&text).tree())
330}
331
332fn read_stdin() -> Result<String> {
333 let mut buff = String::new();
334 std::io::stdin().read_to_string(&mut buff)?;
335 Ok(buff)
336}