1068: profiling crate first draft r=matklad a=pasa I've made this first draft for #961 Could you look at it? Is this something what you are looking for? It has lack of tests. I can't figure out how to test stderr output in rust right now. Do you have some clues? Additionally I'm thinking about to implement procedural macros to annotate methods with this profiler. Will it be helpful? Co-authored-by: Sergey Parilin <sergey.parilin@fxdd.com>
86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
mod analysis_stats;
|
|
|
|
use std::{fs, io::Read, path::Path};
|
|
|
|
use clap::{App, Arg, SubCommand};
|
|
use ra_ide_api::file_structure;
|
|
use ra_syntax::{SourceFile, TreeArc, AstNode};
|
|
use tools::collect_tests;
|
|
use flexi_logger::Logger;
|
|
use ra_prof::profile;
|
|
|
|
type Result<T> = ::std::result::Result<T, failure::Error>;
|
|
|
|
fn main() -> Result<()> {
|
|
Logger::with_env().start()?;
|
|
let matches = App::new("ra-cli")
|
|
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
|
|
.subcommand(
|
|
SubCommand::with_name("render-test")
|
|
.arg(Arg::with_name("line").long("--line").required(true).takes_value(true))
|
|
.arg(Arg::with_name("file").long("--file").required(true).takes_value(true)),
|
|
)
|
|
.subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump")))
|
|
.subcommand(SubCommand::with_name("symbols"))
|
|
.subcommand(
|
|
SubCommand::with_name("analysis-stats").arg(Arg::with_name("verbose").short("v")),
|
|
)
|
|
.get_matches();
|
|
match matches.subcommand() {
|
|
("parse", Some(matches)) => {
|
|
let _p = profile("parsing");
|
|
let file = file()?;
|
|
if !matches.is_present("no-dump") {
|
|
println!("{}", file.syntax().debug_dump());
|
|
}
|
|
::std::mem::forget(file);
|
|
}
|
|
("symbols", _) => {
|
|
let file = file()?;
|
|
for s in file_structure(&file) {
|
|
println!("{:?}", s);
|
|
}
|
|
}
|
|
("render-test", Some(matches)) => {
|
|
let file = matches.value_of("file").unwrap();
|
|
let file = Path::new(file);
|
|
let line: usize = matches.value_of("line").unwrap().parse()?;
|
|
let line = line - 1;
|
|
let (test, tree) = render_test(file, line)?;
|
|
println!("{}\n{}", test, tree);
|
|
}
|
|
("analysis-stats", Some(matches)) => {
|
|
let verbose = matches.is_present("verbose");
|
|
analysis_stats::run(verbose)?;
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn file() -> Result<TreeArc<SourceFile>> {
|
|
let text = read_stdin()?;
|
|
Ok(SourceFile::parse(&text))
|
|
}
|
|
|
|
fn read_stdin() -> Result<String> {
|
|
let mut buff = String::new();
|
|
::std::io::stdin().read_to_string(&mut buff)?;
|
|
Ok(buff)
|
|
}
|
|
|
|
fn render_test(file: &Path, line: usize) -> Result<(String, String)> {
|
|
let text = fs::read_to_string(file)?;
|
|
let tests = collect_tests(&text);
|
|
let test = tests.into_iter().find(|(start_line, t)| {
|
|
*start_line <= line && line <= *start_line + t.text.lines().count()
|
|
});
|
|
let test = match test {
|
|
None => failure::bail!("No test found at line {} at {}", line, file.display()),
|
|
Some((_start_line, test)) => test,
|
|
};
|
|
let file = SourceFile::parse(&test.text);
|
|
let tree = file.syntax().debug_dump();
|
|
Ok((test.text, tree))
|
|
}
|