From e30e827c5ffd9db2ec5e5876535c2492d09a0639 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Mar 2019 11:52:50 -0700 Subject: [PATCH] CLI: Add timeout flag to parse command --- cli/src/main.rs | 7 +- cli/src/parse.rs | 176 +++++++++++++++++++++++++---------------------- 2 files changed, 100 insertions(+), 83 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 15499622..5ad072c6 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -52,7 +52,8 @@ fn run() -> error::Result<()> { .arg(Arg::with_name("debug").long("debug").short("d")) .arg(Arg::with_name("debug-graph").long("debug-graph").short("D")) .arg(Arg::with_name("quiet").long("quiet").short("q")) - .arg(Arg::with_name("time").long("time").short("t")), + .arg(Arg::with_name("time").long("time").short("t")) + .arg(Arg::with_name("timeout").long("timeout").takes_value(true)), ) .subcommand( SubCommand::with_name("test") @@ -132,6 +133,9 @@ fn run() -> error::Result<()> { let debug_graph = matches.is_present("debug-graph"); let quiet = matches.is_present("quiet"); let time = matches.is_present("time"); + let timeout = matches + .value_of("timeout") + .map_or(0, |t| usize::from_str_radix(t, 10).unwrap()); loader.find_all_languages(&config.parser_directories)?; let paths = matches .values_of("path") @@ -157,6 +161,7 @@ fn run() -> error::Result<()> { max_path_length, quiet, time, + timeout, debug, debug_graph, )?; diff --git a/cli/src/parse.rs b/cli/src/parse.rs index 2e8b3e4c..27b96c38 100644 --- a/cli/src/parse.rs +++ b/cli/src/parse.rs @@ -12,6 +12,7 @@ pub fn parse_file_at_path( max_path_length: usize, quiet: bool, print_time: bool, + timeout: usize, debug: bool, debug_graph: bool, ) -> Result { @@ -32,111 +33,122 @@ pub fn parse_file_at_path( }))); } + parser.set_timeout_micros(timeout); let time = Instant::now(); - let tree = parser - .parse(&source_code, None) - .expect("Incompatible language version"); + let tree = parser.parse(&source_code, None); let duration = time.elapsed(); let duration_ms = duration.as_secs() * 1000 + duration.subsec_nanos() as u64 / 1000000; - let mut cursor = tree.walk(); - let stdout = io::stdout(); let mut stdout = stdout.lock(); - if !quiet { - let mut needs_newline = false; - let mut indent_level = 0; - let mut did_visit_children = false; + if let Some(tree) = tree { + let mut cursor = tree.walk(); + + if !quiet { + let mut needs_newline = false; + let mut indent_level = 0; + let mut did_visit_children = false; + loop { + let node = cursor.node(); + let is_named = node.is_named(); + if did_visit_children { + if is_named { + stdout.write(b")")?; + needs_newline = true; + } + if cursor.goto_next_sibling() { + did_visit_children = false; + } else if cursor.goto_parent() { + did_visit_children = true; + indent_level -= 1; + } else { + break; + } + } else { + if is_named { + if needs_newline { + stdout.write(b"\n")?; + } + for _ in 0..indent_level { + stdout.write(b" ")?; + } + let start = node.start_position(); + let end = node.end_position(); + write!( + &mut stdout, + "({} [{}, {}] - [{}, {}]", + node.kind(), + start.row, + start.column, + end.row, + end.column + )?; + needs_newline = true; + } + if cursor.goto_first_child() { + did_visit_children = false; + indent_level += 1; + } else { + did_visit_children = true; + } + } + } + cursor.reset(tree.root_node()); + println!(""); + } + + let mut first_error = None; loop { let node = cursor.node(); - let is_named = node.is_named(); - if did_visit_children { - if is_named { - stdout.write(b")")?; - needs_newline = true; - } - if cursor.goto_next_sibling() { - did_visit_children = false; - } else if cursor.goto_parent() { - did_visit_children = true; - indent_level -= 1; + if node.has_error() { + if node.is_error() || node.is_missing() { + first_error = Some(node); + break; } else { + cursor.goto_first_child(); + } + } else if !cursor.goto_next_sibling() { + if !cursor.goto_parent() { break; } - } else { - if is_named { - if needs_newline { - stdout.write(b"\n")?; - } - for _ in 0..indent_level { - stdout.write(b" ")?; - } - let start = node.start_position(); - let end = node.end_position(); - write!( - &mut stdout, - "({} [{}, {}] - [{}, {}]", - node.kind(), - start.row, - start.column, - end.row, - end.column - )?; - needs_newline = true; - } - if cursor.goto_first_child() { - did_visit_children = false; - indent_level += 1; - } else { - did_visit_children = true; - } } } - cursor.reset(tree.root_node()); - println!(""); - } - let mut first_error = None; - loop { - let node = cursor.node(); - if node.has_error() { - if node.is_error() || node.is_missing() { - first_error = Some(node); - break; - } else { - cursor.goto_first_child(); - } - } else if !cursor.goto_next_sibling() { - if !cursor.goto_parent() { - break; + if first_error.is_some() || print_time { + write!( + &mut stdout, + "{:width$}\t{} ms", + path.to_str().unwrap(), + duration_ms, + width = max_path_length + )?; + if let Some(node) = first_error { + let start = node.start_position(); + let end = node.end_position(); + write!( + &mut stdout, + "\t({} [{}, {}] - [{}, {}])", + node.kind(), + start.row, + start.column, + end.row, + end.column + )?; } + write!(&mut stdout, "\n")?; } - } - if first_error.is_some() || print_time { - write!( + return Ok(first_error.is_some()) + } else if print_time { + writeln!( &mut stdout, - "{:width$}\t{} ms", + "{:width$}\t{} ms (timed out)", path.to_str().unwrap(), duration_ms, width = max_path_length )?; - if let Some(node) = first_error { - let start = node.start_position(); - let end = node.end_position(); - write!( - &mut stdout, - "\t({} [{}, {}] - [{}, {}])", - node.kind(), - start.row, - start.column, - end.row, - end.column - )?; - } - write!(&mut stdout, "\n")?; } - Ok(first_error.is_some()) + Ok(false) }