feat(cli): add json summary of parsing

This commit is contained in:
WillLillis 2024-12-23 21:54:48 -05:00
parent a7e6d01144
commit fbf8965cd4
2 changed files with 74 additions and 8 deletions

View file

@ -213,6 +213,9 @@ struct Parse {
/// Open `log.html` in the default browser, if `--debug-graph` is supplied
#[arg(long)]
pub open_log: bool,
/// Output parsing results in a JSON format
#[arg(long, short = 'j')]
pub output_json_summary: bool,
/// The path to an alternative config.json file
#[arg(long)]
pub config_path: Option<PathBuf>,
@ -812,7 +815,7 @@ impl Parse {
ParseOutput::Xml
} else if self.output_cst {
ParseOutput::Cst
} else if self.quiet {
} else if self.quiet || self.output_json_summary {
ParseOutput::Quiet
} else {
ParseOutput::Normal
@ -859,7 +862,7 @@ impl Parse {
loader.find_all_languages(&loader_config)?;
let should_track_stats = self.stat;
let mut stats = parse::Stats::default();
let mut stats = parse::ParseStats::new();
let options = ParseFileOptions {
edits: &edits
@ -882,11 +885,11 @@ impl Parse {
if should_track_stats {
stats.total_parses += 1;
if parse_result.successful {
stats.successful_parses += 1;
stats.cumulative_stats.successful_parses += 1;
}
if let Some(duration) = parse_result.duration {
stats.total_bytes += parse_result.bytes;
stats.total_duration += duration;
stats.cumulative_stats.total_bytes += parse_result.bytes;
stats.cumulative_stats.total_duration += duration;
}
}
@ -972,7 +975,10 @@ impl Parse {
}
if should_track_stats {
println!("\n{stats}");
println!("\n{}", stats.cumulative_stats);
}
if self.output_json_summary {
println!("{}", serde_json::to_string_pretty(&stats)?);
}
if has_error {

View file

@ -1,7 +1,7 @@
use std::{
fmt, fs,
io::{self, StdoutLock, Write},
path::Path,
path::{Path, PathBuf},
sync::atomic::{AtomicUsize, Ordering},
time::{Duration, Instant},
};
@ -17,7 +17,7 @@ use tree_sitter::{
use super::util;
use crate::{fuzz::edits::Edit, test::paint};
#[derive(Debug, Default)]
#[derive(Debug, Default, Serialize)]
pub struct Stats {
pub successful_parses: usize,
pub total_parses: usize,
@ -177,9 +177,65 @@ pub enum ParseOutput {
Dot,
}
/// A position in a multi-line text document, in terms of rows and columns.
///
/// Rows and columns are zero-based.
///
/// This serves as a serializable wrapper for `Point`
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
pub struct ParsePoint {
pub row: usize,
pub column: usize,
}
impl From<Point> for ParsePoint {
fn from(value: Point) -> Self {
Self {
row: value.row,
column: value.column,
}
}
}
#[derive(Serialize, Default, Debug, Clone)]
pub struct ParseSummary {
pub file: PathBuf,
pub successful: bool,
pub start: Option<ParsePoint>,
pub end: Option<ParsePoint>,
pub duration: Option<Duration>,
pub bytes: Option<u128>,
}
impl ParseSummary {
pub fn new(path: &Path) -> Self {
Self {
file: path.to_path_buf(),
successful: false,
..Default::default()
}
}
}
#[derive(Serialize, Debug)]
pub struct ParseStats {
pub parse_summaries: Vec<ParseSummary>,
pub cumulative_stats: Stats,
}
impl ParseStats {
pub fn new() -> Self {
Self {
parse_summaries: Vec::new(),
cumulative_stats: Stats::default(),
}
}
}
pub struct ParseFileOptions<'a> {
pub edits: &'a [&'a str],
pub output: ParseOutput,
pub stats: &'a mut ParseStats,
pub print_time: bool,
pub timeout: u64,
pub debug: bool,
@ -342,6 +398,10 @@ pub fn parse_file_at_path(
parser.stop_printing_dot_graphs();
let current_summary = opts.stats.parse_summaries.last_mut().unwrap();
current_summary.start = Some(tree.root_node().start_position().into());
current_summary.end = Some(tree.root_node().end_position().into());
let parse_duration_ms = parse_duration.as_micros() as f64 / 1e3;
let edit_duration_ms = edit_duration.as_micros() as f64 / 1e3;
let mut cursor = tree.walk();