feat(rust): use thiserror for generate crate

Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
This commit is contained in:
WillLillis 2024-12-24 19:16:19 -05:00 committed by Amaan Qureshi
parent 5a825a0930
commit 867433afd7
17 changed files with 821 additions and 371 deletions

View file

@ -381,7 +381,8 @@ pub fn generate_grammar_files(
let Some(opts) = opts else { unreachable!() };
let tree_sitter_json = opts.clone().to_tree_sitter_json();
write_file(path, serde_json::to_string_pretty(&tree_sitter_json)?)
write_file(path, serde_json::to_string_pretty(&tree_sitter_json)?)?;
Ok(())
},
|path| {
// updating the config, if needed
@ -523,10 +524,9 @@ pub fn generate_grammar_files(
|path| {
let contents = fs::read_to_string(path)?;
if contents.contains("fs.exists(") {
write_file(path, contents.replace("fs.exists(", "fs.existsSync("))
} else {
Ok(())
write_file(path, contents.replace("fs.exists(", "fs.existsSync("))?;
}
Ok(())
},
)?;
@ -566,10 +566,9 @@ pub fn generate_grammar_files(
let contents = fs::read_to_string(path)?;
let old = "add_custom_target(test";
if contents.contains(old) {
write_file(path, contents.replace(old, "add_custom_target(ts-test"))
} else {
Ok(())
write_file(path, contents.replace(old, "add_custom_target(ts-test"))?;
}
Ok(())
},
)?;
@ -671,10 +670,9 @@ pub fn generate_grammar_files(
"egg_info": EggInfo,
"#},
);
write_file(path, contents)
} else {
Ok(())
write_file(path, contents)?;
}
Ok(())
},
)?;
@ -951,7 +949,8 @@ fn generate_file(
}
}
write_file(path, replacement)
write_file(path, replacement)?;
Ok(())
}
fn create_dir(path: &Path) -> Result<()> {

View file

@ -22,7 +22,7 @@ use tree_sitter_cli::{
init::{generate_grammar_files, get_root_path, migrate_package_json, JsonConfigOpts},
input::{get_input, get_tmp_source_file, CliInput},
logger,
parse::{self, ParseFileOptions, ParseOutput, ParseResult, ParseTheme},
parse::{self, ParseFileOptions, ParseOutput, ParseTheme},
playground, query,
tags::{self, TagsOptions},
test::{self, TestOptions, TestStats},
@ -121,6 +121,9 @@ struct Generate {
/// Produce a report of the states for the given rule, use `-` to report every rule
#[arg(long)]
pub report_states_for_rule: Option<String>,
/// Report conflicts in a JSON format
#[arg(long)]
pub json: bool,
/// The name or path of the JavaScript runtime to use for generating parsers
#[arg(
long,
@ -215,7 +218,7 @@ struct Parse {
pub open_log: bool,
/// Output parsing results in a JSON format
#[arg(long, short = 'j')]
pub output_json_summary: bool,
pub json: bool,
/// The path to an alternative config.json file
#[arg(long)]
pub config_path: Option<PathBuf>,
@ -729,14 +732,22 @@ impl Generate {
version.parse().expect("invalid abi version flag")
}
});
tree_sitter_generate::generate_parser_in_directory(
if let Err(err) = tree_sitter_generate::generate_parser_in_directory(
current_dir,
self.output.as_deref(),
self.grammar_path.as_deref(),
abi_version,
self.report_states_for_rule.as_deref(),
self.js_runtime.as_deref(),
)?;
) {
if self.json {
eprintln!("{}", serde_json::to_string_pretty(&err)?);
// Exit early to prevent errors from being printed a second time in the caller
std::process::exit(1);
} else {
return Err(err.into());
}
}
if self.build {
if let Some(path) = self.libdir {
loader = loader::Loader::with_parser_lib_path(PathBuf::from(path));
@ -815,7 +826,7 @@ impl Parse {
ParseOutput::Xml
} else if self.output_cst {
ParseOutput::Cst
} else if self.quiet || self.output_json_summary {
} else if self.quiet || self.json {
ParseOutput::Quiet
} else {
ParseOutput::Normal
@ -862,9 +873,9 @@ impl Parse {
loader.find_all_languages(&loader_config)?;
let should_track_stats = self.stat;
let mut stats = parse::ParseStats::new();
let mut stats = parse::ParseStats::default();
let options = ParseFileOptions {
let mut options = ParseFileOptions {
edits: &edits
.iter()
.map(std::string::String::as_str)
@ -872,6 +883,7 @@ impl Parse {
output,
print_time: time,
timeout,
stats: &mut stats,
debug: self.debug,
debug_graph: self.debug_graph,
cancellation_flag: Some(&cancellation_flag),
@ -881,14 +893,15 @@ impl Parse {
parse_theme: &parse_theme,
};
let mut update_stats = |parse_result: ParseResult| {
let mut update_stats = |stats: &mut parse::ParseStats| {
let parse_result = stats.parse_summaries.last().unwrap();
if should_track_stats {
stats.total_parses += 1;
stats.cumulative_stats.total_parses += 1;
if parse_result.successful {
stats.cumulative_stats.successful_parses += 1;
}
if let Some(duration) = parse_result.duration {
stats.cumulative_stats.total_bytes += parse_result.bytes;
if let (Some(duration), Some(bytes)) = (parse_result.duration, parse_result.bytes) {
stats.cumulative_stats.total_bytes += bytes;
stats.cumulative_stats.total_duration += duration;
}
}
@ -915,15 +928,15 @@ impl Parse {
let language =
loader.select_language(path, current_dir, self.scope.as_deref())?;
let parse_result = parse::parse_file_at_path(
parse::parse_file_at_path(
&mut parser,
&language,
path,
&path.display().to_string(),
max_path_length,
&options,
&mut options,
)?;
update_stats(parse_result);
update_stats(options.stats);
}
}
@ -941,15 +954,15 @@ impl Parse {
.map(|(l, _)| l.clone())
.ok_or_else(|| anyhow!("No language found"))?;
let parse_result = parse::parse_file_at_path(
parse::parse_file_at_path(
&mut parser,
&language,
&path,
&name,
name.chars().count(),
&options,
&mut options,
)?;
update_stats(parse_result);
update_stats(&mut stats);
fs::remove_file(path)?;
}
@ -961,15 +974,15 @@ impl Parse {
let name = "stdin";
let language = loader.select_language(&path, current_dir, None)?;
let parse_result = parse::parse_file_at_path(
parse::parse_file_at_path(
&mut parser,
&language,
&path,
name,
name.chars().count(),
&options,
&mut options,
)?;
update_stats(parse_result);
update_stats(&mut stats);
fs::remove_file(path)?;
}
}
@ -977,7 +990,7 @@ impl Parse {
if should_track_stats {
println!("\n{}", stats.cumulative_stats);
}
if self.output_json_summary {
if self.json {
println!("{}", serde_json::to_string_pretty(&stats)?);
}

View file

@ -204,10 +204,11 @@ pub struct ParseSummary {
pub start: Option<ParsePoint>,
pub end: Option<ParsePoint>,
pub duration: Option<Duration>,
pub bytes: Option<u128>,
pub bytes: Option<usize>,
}
impl ParseSummary {
#[must_use]
pub fn new(path: &Path) -> Self {
Self {
file: path.to_path_buf(),
@ -217,21 +218,12 @@ impl ParseSummary {
}
}
#[derive(Serialize, Debug)]
#[derive(Serialize, Debug, Default)]
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,
@ -260,8 +252,8 @@ pub fn parse_file_at_path(
path: &Path,
name: &str,
max_path_length: usize,
opts: &ParseFileOptions,
) -> Result<ParseResult> {
opts: &mut ParseFileOptions,
) -> Result<()> {
let mut _log_session = None;
parser.set_language(language)?;
let mut source_code = fs::read(path).with_context(|| format!("Error reading {name:?}"))?;
@ -398,10 +390,6 @@ 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();
@ -656,11 +644,16 @@ pub fn parse_file_at_path(
writeln!(&mut stdout)?;
}
return Ok(ParseResult {
successful: first_error.is_none(),
bytes: source_code.len(),
opts.stats.parse_summaries.push(ParseSummary {
file: path.to_path_buf(),
successful: true,
start: Some(tree.root_node().start_position().into()),
end: Some(tree.root_node().end_position().into()),
duration: Some(parse_duration),
bytes: Some(source_code.len()),
});
return Ok(());
}
parser.stop_printing_dot_graphs();
@ -675,11 +668,16 @@ pub fn parse_file_at_path(
)?;
}
Ok(ParseResult {
opts.stats.parse_summaries.push(ParseSummary {
file: path.to_path_buf(),
successful: false,
bytes: source_code.len(),
start: None,
end: None,
duration: None,
})
bytes: Some(source_code.len()),
});
Ok(())
}
const fn escape_invisible(c: char) -> Option<&'static str> {