2019-02-19 10:35:03 -08:00
|
|
|
use super::error::{Error, Result};
|
2019-01-08 21:03:51 -08:00
|
|
|
use super::util;
|
2019-01-07 17:57:36 -08:00
|
|
|
use std::fs;
|
|
|
|
|
use std::io::{self, Write};
|
2019-01-08 21:03:51 -08:00
|
|
|
use std::path::Path;
|
2019-01-17 17:15:10 -08:00
|
|
|
use std::time::Instant;
|
2019-01-08 21:03:51 -08:00
|
|
|
use tree_sitter::{Language, LogType, Parser};
|
2019-01-07 17:57:36 -08:00
|
|
|
|
2019-01-08 21:03:51 -08:00
|
|
|
pub fn parse_file_at_path(
|
|
|
|
|
language: Language,
|
|
|
|
|
path: &Path,
|
2019-01-17 17:15:10 -08:00
|
|
|
max_path_length: usize,
|
|
|
|
|
quiet: bool,
|
|
|
|
|
print_time: bool,
|
2019-03-14 12:39:04 -07:00
|
|
|
timeout: u64,
|
2019-01-08 21:03:51 -08:00
|
|
|
debug: bool,
|
|
|
|
|
debug_graph: bool,
|
2019-02-06 16:17:35 -08:00
|
|
|
) -> Result<bool> {
|
2019-01-17 17:15:10 -08:00
|
|
|
let mut _log_session = None;
|
2019-01-07 17:57:36 -08:00
|
|
|
let mut parser = Parser::new();
|
|
|
|
|
parser.set_language(language)?;
|
2019-02-19 10:35:03 -08:00
|
|
|
let source_code = fs::read(path)
|
|
|
|
|
.map_err(|e| Error(format!("Error reading source file {:?}: {}", path, e)))?;
|
2019-01-08 21:03:51 -08:00
|
|
|
|
|
|
|
|
if debug_graph {
|
2019-01-17 17:15:10 -08:00
|
|
|
_log_session = Some(util::log_graphs(&mut parser, "log.html")?);
|
2019-01-08 21:03:51 -08:00
|
|
|
} else if debug {
|
|
|
|
|
parser.set_logger(Some(Box::new(|log_type, message| {
|
|
|
|
|
if log_type == LogType::Lex {
|
|
|
|
|
io::stderr().write(b" ").unwrap();
|
|
|
|
|
}
|
|
|
|
|
write!(&mut io::stderr(), "{}\n", message).unwrap();
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-14 11:52:50 -07:00
|
|
|
parser.set_timeout_micros(timeout);
|
2019-01-17 17:15:10 -08:00
|
|
|
let time = Instant::now();
|
2019-03-14 11:52:50 -07:00
|
|
|
let tree = parser.parse(&source_code, None);
|
2019-01-17 17:15:10 -08:00
|
|
|
let duration = time.elapsed();
|
|
|
|
|
let duration_ms = duration.as_secs() * 1000 + duration.subsec_nanos() as u64 / 1000000;
|
2019-01-07 17:57:36 -08:00
|
|
|
|
|
|
|
|
let stdout = io::stdout();
|
|
|
|
|
let mut stdout = stdout.lock();
|
2019-01-17 17:15:10 -08:00
|
|
|
|
2019-03-14 11:52:50 -07:00
|
|
|
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;
|
|
|
|
|
}
|
2019-01-17 17:15:10 -08:00
|
|
|
} else {
|
2019-03-14 11:52:50 -07:00
|
|
|
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;
|
2019-01-17 17:15:10 -08:00
|
|
|
}
|
2019-03-14 11:52:50 -07:00
|
|
|
if cursor.goto_first_child() {
|
|
|
|
|
did_visit_children = false;
|
|
|
|
|
indent_level += 1;
|
|
|
|
|
} else {
|
|
|
|
|
did_visit_children = true;
|
2019-01-17 17:15:10 -08:00
|
|
|
}
|
2019-01-07 17:57:36 -08:00
|
|
|
}
|
2019-03-14 11:52:50 -07:00
|
|
|
}
|
|
|
|
|
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;
|
2019-01-17 17:15:10 -08:00
|
|
|
} else {
|
2019-03-14 11:52:50 -07:00
|
|
|
cursor.goto_first_child();
|
|
|
|
|
}
|
|
|
|
|
} else if !cursor.goto_next_sibling() {
|
|
|
|
|
if !cursor.goto_parent() {
|
|
|
|
|
break;
|
2019-01-07 17:57:36 -08:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-17 17:15:10 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-14 11:52:50 -07:00
|
|
|
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
|
|
|
|
|
)?;
|
2019-01-17 17:15:10 -08:00
|
|
|
}
|
2019-03-14 11:52:50 -07:00
|
|
|
write!(&mut stdout, "\n")?;
|
2019-01-17 17:15:10 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-14 11:52:50 -07:00
|
|
|
return Ok(first_error.is_some())
|
|
|
|
|
} else if print_time {
|
|
|
|
|
writeln!(
|
2019-01-17 17:15:10 -08:00
|
|
|
&mut stdout,
|
2019-03-14 11:52:50 -07:00
|
|
|
"{:width$}\t{} ms (timed out)",
|
2019-01-17 17:15:10 -08:00
|
|
|
path.to_str().unwrap(),
|
|
|
|
|
duration_ms,
|
|
|
|
|
width = max_path_length
|
|
|
|
|
)?;
|
2019-01-07 17:57:36 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-14 11:52:50 -07:00
|
|
|
Ok(false)
|
2019-01-07 17:57:36 -08:00
|
|
|
}
|