Merge pull request #2441 from tree-sitter/error-contexts
More error contexts + conv panics to errors with context
This commit is contained in:
commit
0fb816d1f9
3 changed files with 72 additions and 54 deletions
|
|
@ -48,22 +48,22 @@ pub fn generate_parser_in_directory(
|
|||
let src_path = repo_path.join("src");
|
||||
let header_path = src_path.join("tree_sitter");
|
||||
|
||||
// Read the grammar.json.
|
||||
let grammar_json = match grammar_path {
|
||||
Some(path) => load_grammar_file(path.as_ref())?,
|
||||
None => {
|
||||
let grammar_js_path = grammar_path.map_or(repo_path.join("grammar.js"), |s| s.into());
|
||||
load_grammar_file(&grammar_js_path)?
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure that the output directories exist.
|
||||
fs::create_dir_all(&src_path)?;
|
||||
fs::create_dir_all(&header_path)?;
|
||||
|
||||
// Read the grammar.json.
|
||||
let grammar_json;
|
||||
match grammar_path {
|
||||
Some(path) => {
|
||||
grammar_json = load_grammar_file(path.as_ref())?;
|
||||
}
|
||||
None => {
|
||||
let grammar_js_path = grammar_path.map_or(repo_path.join("grammar.js"), |s| s.into());
|
||||
grammar_json = load_grammar_file(&grammar_js_path)?;
|
||||
fs::write(&src_path.join("grammar.json"), &grammar_json)
|
||||
.with_context(|| format!("Failed to write grammar.json to {:?}", src_path))?;
|
||||
}
|
||||
if grammar_path.is_none() {
|
||||
fs::write(&src_path.join("grammar.json"), &grammar_json)
|
||||
.with_context(|| format!("Failed to write grammar.json to {:?}", src_path))?;
|
||||
}
|
||||
|
||||
// Parse and preprocess the grammar.
|
||||
|
|
@ -157,9 +157,18 @@ fn generate_parser_for_grammar_with_opts(
|
|||
}
|
||||
|
||||
pub fn load_grammar_file(grammar_path: &Path) -> Result<String> {
|
||||
if grammar_path.is_dir() {
|
||||
return Err(anyhow!(
|
||||
"Path to a grammar file with `.js` or `.json` extension is required"
|
||||
));
|
||||
}
|
||||
match grammar_path.extension().and_then(|e| e.to_str()) {
|
||||
Some("js") => Ok(load_js_grammar_file(grammar_path)?),
|
||||
Some("json") => Ok(fs::read_to_string(grammar_path)?),
|
||||
Some("js") => {
|
||||
Ok(load_js_grammar_file(grammar_path).with_context(|| "Failed to load grammar.js")?)
|
||||
}
|
||||
Some("json") => {
|
||||
Ok(fs::read_to_string(grammar_path).with_context(|| "Failed to load grammar.json")?)
|
||||
}
|
||||
_ => Err(anyhow!(
|
||||
"Unknown grammar file extension: {:?}",
|
||||
grammar_path
|
||||
|
|
@ -174,14 +183,14 @@ fn load_js_grammar_file(grammar_path: &Path) -> Result<String> {
|
|||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run `node`");
|
||||
.with_context(|| "Failed to run `node`")?;
|
||||
|
||||
let mut node_stdin = node_process
|
||||
.stdin
|
||||
.take()
|
||||
.expect("Failed to open stdin for node");
|
||||
.with_context(|| "Failed to open stdin for node")?;
|
||||
let cli_version = Version::parse(env!("CARGO_PKG_VERSION"))
|
||||
.expect("Could not parse this package's version as semver.");
|
||||
.with_context(|| "Could not parse this package's version as semver.")?;
|
||||
write!(
|
||||
node_stdin,
|
||||
"global.TREE_SITTER_CLI_VERSION_MAJOR = {};
|
||||
|
|
@ -189,22 +198,22 @@ fn load_js_grammar_file(grammar_path: &Path) -> Result<String> {
|
|||
global.TREE_SITTER_CLI_VERSION_PATCH = {};",
|
||||
cli_version.major, cli_version.minor, cli_version.patch,
|
||||
)
|
||||
.expect("Failed to write tree-sitter version to node's stdin");
|
||||
.with_context(|| "Failed to write tree-sitter version to node's stdin")?;
|
||||
let javascript_code = include_bytes!("./dsl.js");
|
||||
node_stdin
|
||||
.write(javascript_code)
|
||||
.expect("Failed to write grammar dsl to node's stdin");
|
||||
.with_context(|| "Failed to write grammar dsl to node's stdin")?;
|
||||
drop(node_stdin);
|
||||
let output = node_process
|
||||
.wait_with_output()
|
||||
.expect("Failed to read output from node");
|
||||
.with_context(|| "Failed to read output from node")?;
|
||||
match output.status.code() {
|
||||
None => panic!("Node process was killed"),
|
||||
Some(0) => {}
|
||||
Some(code) => return Err(anyhow!("Node process exited with status {}", code)),
|
||||
}
|
||||
|
||||
let mut result = String::from_utf8(output.stdout).expect("Got invalid UTF8 from node");
|
||||
let mut result =
|
||||
String::from_utf8(output.stdout).with_context(|| "Got invalid UTF8 from node")?;
|
||||
result.push('\n');
|
||||
Ok(result)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{anyhow, Context, Error, Result};
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
use glob::glob;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -317,16 +317,18 @@ fn run() -> Result<()> {
|
|||
if matches.is_present("log") {
|
||||
logger::init();
|
||||
}
|
||||
let abi_version =
|
||||
matches
|
||||
.value_of("abi-version")
|
||||
.map_or(DEFAULT_GENERATE_ABI_VERSION, |version| {
|
||||
if version == "latest" {
|
||||
tree_sitter::LANGUAGE_VERSION
|
||||
} else {
|
||||
version.parse().expect("invalid abi version flag")
|
||||
}
|
||||
});
|
||||
let abi_version = matches.value_of("abi-version").map_or(
|
||||
Ok::<_, Error>(DEFAULT_GENERATE_ABI_VERSION),
|
||||
|version| {
|
||||
Ok(if version == "latest" {
|
||||
tree_sitter::LANGUAGE_VERSION
|
||||
} else {
|
||||
version
|
||||
.parse()
|
||||
.with_context(|| "invalid abi version flag")?
|
||||
})
|
||||
},
|
||||
)?;
|
||||
let generate_bindings = !matches.is_present("no-bindings");
|
||||
generate::generate_parser_in_directory(
|
||||
¤t_dir,
|
||||
|
|
@ -635,7 +637,7 @@ fn run() -> Result<()> {
|
|||
|
||||
("playground", Some(matches)) => {
|
||||
let open_in_browser = !matches.is_present("quiet");
|
||||
playground::serve(¤t_dir, open_in_browser);
|
||||
playground::serve(¤t_dir, open_in_browser)?;
|
||||
}
|
||||
|
||||
("dump-languages", Some(_)) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::wasm;
|
||||
use anyhow::Context;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
env, fs,
|
||||
|
|
@ -43,20 +43,17 @@ fn get_main_html(tree_sitter_dir: &Option<PathBuf>) -> Cow<'static, [u8]> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn serve(grammar_path: &Path, open_in_browser: bool) {
|
||||
let server = get_server();
|
||||
pub fn serve(grammar_path: &Path, open_in_browser: bool) -> Result<()> {
|
||||
let server = get_server()?;
|
||||
let grammar_name = wasm::get_grammar_name(&grammar_path.join("src"))
|
||||
.with_context(|| "Failed to get wasm filename")
|
||||
.unwrap();
|
||||
.with_context(|| "Failed to get wasm filename")?;
|
||||
let wasm_filename = format!("tree-sitter-{}.wasm", grammar_name);
|
||||
let language_wasm = fs::read(grammar_path.join(&wasm_filename))
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Failed to read {}. Run `tree-sitter build-wasm` first.",
|
||||
wasm_filename
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
let language_wasm = fs::read(grammar_path.join(&wasm_filename)).with_context(|| {
|
||||
format!(
|
||||
"Failed to read {}. Run `tree-sitter build-wasm` first.",
|
||||
wasm_filename
|
||||
)
|
||||
})?;
|
||||
let url = format!("http://{}", server.server_addr());
|
||||
println!("Started playground on: {}", url);
|
||||
if open_in_browser {
|
||||
|
|
@ -105,8 +102,12 @@ pub fn serve(grammar_path: &Path, open_in_browser: bool) {
|
|||
}
|
||||
_ => response(b"Not found", &html_header).with_status_code(404),
|
||||
};
|
||||
request.respond(res).expect("Failed to write HTTP response");
|
||||
request
|
||||
.respond(res)
|
||||
.with_context(|| "Failed to write HTTP response")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn redirect<'a>(url: &'a str) -> Response<&'a [u8]> {
|
||||
|
|
@ -121,18 +122,24 @@ fn response<'a>(data: &'a [u8], header: &Header) -> Response<&'a [u8]> {
|
|||
.with_header(header.clone())
|
||||
}
|
||||
|
||||
fn get_server() -> Server {
|
||||
fn get_server() -> Result<Server> {
|
||||
let addr = env::var("TREE_SITTER_PLAYGROUND_ADDR").unwrap_or("127.0.0.1".to_owned());
|
||||
let port = env::var("TREE_SITTER_PLAYGROUND_PORT")
|
||||
.map(|v| v.parse::<u16>().expect("Invalid port specification"))
|
||||
.map(|v| {
|
||||
v.parse::<u16>()
|
||||
.with_context(|| "Invalid port specification")
|
||||
})
|
||||
.ok();
|
||||
let listener = match port {
|
||||
Some(port) => bind_to(&*addr, port).expect("Can't bind to the specified port"),
|
||||
None => {
|
||||
get_listener_on_available_port(&*addr).expect("Can't find a free port to bind to it")
|
||||
Some(port) => {
|
||||
bind_to(&*addr, port?).with_context(|| "Failed to bind to the specified port")?
|
||||
}
|
||||
None => get_listener_on_available_port(&*addr)
|
||||
.with_context(|| "Failed to find a free port to bind to it")?,
|
||||
};
|
||||
Server::from_listener(listener, None).expect("Failed to start web server")
|
||||
let server =
|
||||
Server::from_listener(listener, None).map_err(|_| anyhow!("Failed to start web server"))?;
|
||||
Ok(server)
|
||||
}
|
||||
|
||||
fn get_listener_on_available_port(addr: &str) -> Option<TcpListener> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue