diff options
Diffstat (limited to 'crates/ra_cli/src/main.rs')
-rw-r--r-- | crates/ra_cli/src/main.rs | 336 |
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 | |||
3 | mod load_cargo; | ||
4 | mod analysis_stats; | ||
5 | mod analysis_bench; | ||
6 | mod progress_report; | ||
7 | |||
8 | use std::{fmt::Write, io::Read, path::PathBuf, str::FromStr}; | ||
9 | |||
10 | use pico_args::Arguments; | ||
11 | use ra_ide::{file_structure, Analysis}; | ||
12 | use ra_prof::profile; | ||
13 | use ra_syntax::{AstNode, SourceFile}; | ||
14 | |||
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 | } | ||
84 | |||
85 | #[derive(Clone, Copy)] | ||
86 | pub enum Verbosity { | ||
87 | Spammy, | ||
88 | Verbose, | ||
89 | Normal, | ||
90 | Quiet, | ||
91 | } | ||
92 | |||
93 | impl 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 | |||
108 | enum BenchWhat { | ||
109 | Highlight { path: PathBuf }, | ||
110 | Complete(Position), | ||
111 | GotoDef(Position), | ||
112 | } | ||
113 | |||
114 | pub(crate) struct Position { | ||
115 | path: PathBuf, | ||
116 | line: u32, | ||
117 | column: u32, | ||
118 | } | ||
119 | |||
120 | impl 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 | |||
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 | "\ | ||
159 | ra-cli-parse | ||
160 | |||
161 | USAGE: | ||
162 | ra_cli parse [FLAGS] | ||
163 | |||
164 | FLAGS: | ||
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 | "\ | ||
179 | ra-cli-symbols | ||
180 | |||
181 | USAGE: | ||
182 | ra_cli highlight [FLAGS] | ||
183 | |||
184 | FLAGS: | ||
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 | "\ | ||
198 | ra-cli-highlight | ||
199 | |||
200 | USAGE: | ||
201 | ra_cli highlight [FLAGS] | ||
202 | |||
203 | FLAGS: | ||
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 | "\ | ||
218 | ra-cli-analysis-stats | ||
219 | |||
220 | USAGE: | ||
221 | ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH] | ||
222 | |||
223 | FLAGS: | ||
224 | -h, --help Prints help information | ||
225 | --memory-usage | ||
226 | -v, --verbose | ||
227 | -q, --quiet | ||
228 | |||
229 | OPTIONS: | ||
230 | -o <ONLY> | ||
231 | |||
232 | ARGS: | ||
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 | "\ | ||
256 | ra_cli-analysis-bench | ||
257 | |||
258 | USAGE: | ||
259 | ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH] | ||
260 | |||
261 | FLAGS: | ||
262 | -h, --help Prints help information | ||
263 | -v, --verbose | ||
264 | |||
265 | OPTIONS: | ||
266 | --complete <PATH:LINE:COLUMN> Compute completions at this location | ||
267 | --highlight <PATH> Hightlight this file | ||
268 | |||
269 | ARGS: | ||
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 | "\ | ||
292 | ra-cli | ||
293 | |||
294 | USAGE: | ||
295 | ra_cli <SUBCOMMAND> | ||
296 | |||
297 | FLAGS: | ||
298 | -h, --help Prints help information | ||
299 | |||
300 | SUBCOMMANDS: | ||
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 | |||
314 | fn 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 | |||
327 | fn file() -> Result<SourceFile> { | ||
328 | let text = read_stdin()?; | ||
329 | Ok(SourceFile::parse(&text).tree()) | ||
330 | } | ||
331 | |||
332 | fn read_stdin() -> Result<String> { | ||
333 | let mut buff = String::new(); | ||
334 | std::io::stdin().read_to_string(&mut buff)?; | ||
335 | Ok(buff) | ||
336 | } | ||