Skip to content

Commit

Permalink
support --disable-bytecode
Browse files Browse the repository at this point in the history
  • Loading branch information
blahgeek committed Jan 6, 2024
1 parent 187d190 commit d138e01
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 30 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ Please see https://github.com/blahgeek/emacs-lsp-booster/issues/1 . Huge thanks

1. Check that `emacs-lsp-booster` process is running
2. Check the stderr buffer (e.g. for lsp-mode, `*pyright::stderr*` buffer), it should contain `emacs_lsp_booster` related log.

### Advanced usage

Run `emacs-lsp-booster --help` for more options.
43 changes: 24 additions & 19 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::{mpsc, Arc, atomic::{AtomicI32, self}};

use log::{warn, info};
use log::{warn, info, debug};
use anyhow::Result;
use serde_json as json;

Expand Down Expand Up @@ -64,36 +64,41 @@ fn process_client_reader(reader: impl std::io::Read,

fn process_server_reader(reader: impl std::io::Read,
channel_pub: mpsc::Sender<String>,
bytecode_options: BytecodeOptions) -> Result<()> {
bytecode_options: Option<BytecodeOptions>) -> Result<()> {
let mut bufreader = std::io::BufReader::new(reader);
loop {
let msg = rpcio::rpc_read(&mut bufreader)?;
if msg.is_empty() {
break
}
let json_val = json::from_str(&msg)?;
match bytecode::generate_bytecode_repl(&json_val, bytecode_options.clone()) {
Ok(bytecode_str) => {
if let Some(ref bytecode_options) = bytecode_options {
let json_val = json::from_str(&msg)?;
if let Ok(bytecode_str) = bytecode::generate_bytecode_repl(&json_val, bytecode_options.clone()) {
channel_pub.send(bytecode_str)?;
},
Err(e) => {
warn!("Failed to generate bytecode: {}; fallback to original json", e);
channel_pub.send(msg)?;
},
continue
}
}
channel_pub.send(msg)?;
}
Ok(())
}

pub struct AppOptions {
pub bytecode_options: bytecode::BytecodeOptions,
// if bytecode_options is None, then don't generate bytecode!
pub bytecode_options: Option<bytecode::BytecodeOptions>,
}

pub fn run_app_forever(client_reader: impl std::io::Read + Send + 'static,
client_writer: impl std::io::Write + Send + 'static,
mut server_cmd: std::process::Command,
options: AppOptions) -> Result<std::process::ExitStatus> {
info!("Running server {:?}", server_cmd);
if let Some(ref bytecode_options) = options.bytecode_options {
info!("Will convert server json to bytecode! bytecode options: {:?}", bytecode_options);
} else {
info!("Bytecode disabled! Will forward server json as-is.")
}

let mut proc = server_cmd
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
Expand All @@ -108,30 +113,30 @@ pub fn run_app_forever(client_reader: impl std::io::Read + Send + 'static,
let c2s_channel_counter = c2s_channel_counter.clone();
let proc_stdin = proc.stdin.take().unwrap();
std::thread::spawn(move || {
info!("Started client->server write thread");
debug!("Started client->server write thread");
process_channel_to_writer(c2s_channel_sub, Some(c2s_channel_counter), proc_stdin).unwrap();
info!("Finished client->server write thread");
debug!("Finished client->server write thread");
});
}
std::thread::spawn(move || {
info!("Started server->client write thread");
debug!("Started server->client write thread");
process_channel_to_writer(s2c_channel_sub, None, client_writer).unwrap();
info!("Finished server->client write thread");
debug!("Finished server->client write thread");
});
{
let s2c_channel_pub = s2c_channel_pub.clone();
let proc_stdout = proc.stdout.take().unwrap();
std::thread::spawn(move || {
info!("Started server->client read thread");
debug!("Started server->client read thread");
process_server_reader(proc_stdout, s2c_channel_pub, options.bytecode_options).unwrap();
info!("Finished server->client read thread");
debug!("Finished server->client read thread");
});
}
std::thread::spawn(move || {
info!("Started client->server read thread");
debug!("Started client->server read thread");
process_client_reader(
client_reader, c2s_channel_pub, c2s_channel_counter, s2c_channel_pub).unwrap();
info!("Finished client->server read thread");
debug!("Finished client->server read thread");
});

Ok(proc.wait()?)
Expand Down
2 changes: 1 addition & 1 deletion src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub enum ObjectType {
Alist,
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct BytecodeOptions {
pub object_type: ObjectType,
// TODO: array_type
Expand Down
20 changes: 13 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ use emacs_lsp_booster::bytecode;
arg_required_else_help = true, after_help = "For backward compatibility, `emacs-lsp-booster <SERVER_CMD>...` (without any options) is also supported" )]
struct Cli {
#[command(flatten)]
verbose: clap_verbosity_flag::Verbosity,
verbose: clap_verbosity_flag::Verbosity<clap_verbosity_flag::InfoLevel>,

#[arg(last = true)]
server_cmd: Vec<String>,

#[arg(short = 'n', long,
help = "Disable bytecode generation. Simply forward server json as-is. Useful for debugging or benchmarking.")]
disable_bytecode: bool,

#[arg(long, default_value = "plist",
help = "Lisp type used to represent a JSON object. Plist is the most performant one.\nMust match what lsp client expects.\n")]
json_object_type: bytecode::ObjectType,
Expand Down Expand Up @@ -61,11 +65,12 @@ fn main() -> Result<()> {
cmd.args(&cli.server_cmd[1..]);

let exit_status = app::run_app_forever(std::io::stdin(), std::io::stdout(), cmd, app::AppOptions {
bytecode_options: bytecode::BytecodeOptions {
object_type: cli.json_object_type,
null_value: cli.json_null_value,
false_value: cli.json_false_value,
},
bytecode_options: if !cli.disable_bytecode {
Some(bytecode::BytecodeOptions {
object_type: cli.json_object_type,
null_value: cli.json_null_value,
false_value: cli.json_false_value,
}) } else { None },
})?;
std::process::exit(exit_status.code().unwrap_or(1))
}
Expand All @@ -74,6 +79,7 @@ fn main() -> Result<()> {
fn test_parse_args() {
let cli = parse_args(vec!["emacs-lsp-booster", "server_cmd", "arg1"]);
assert_eq!(cli.server_cmd, vec!["server_cmd", "arg1"]);
assert_eq!(cli.verbose.log_level_filter(), log::LevelFilter::Info);

let cli = parse_args(vec!["emacs-lsp-booster", "--", "server_cmd", "arg1"]);
assert_eq!(cli.server_cmd, vec!["server_cmd", "arg1"]);
Expand All @@ -83,7 +89,7 @@ fn test_parse_args() {
"--json-null-value", ":null",
"--json-false-value", ":json-false",
"--", "server_cmd", "arg1"]);
assert_eq!(cli.verbose.log_level_filter(), log::LevelFilter::Warn);
assert_eq!(cli.verbose.log_level_filter(), log::LevelFilter::Debug);
assert_eq!(cli.server_cmd, vec!["server_cmd", "arg1"]);
assert_eq!(cli.json_object_type, bytecode::ObjectType::Hashtable);
assert_eq!(cli.json_null_value, bytecode::LispObject::Symbol("null".into()));
Expand Down
4 changes: 2 additions & 2 deletions src/rpcio.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{str::FromStr, io::Write};

use log::debug;
use log::trace;
use anyhow::{Result, bail};

// return empty string on EOF
Expand All @@ -24,7 +24,7 @@ pub fn rpc_read(reader: &mut impl std::io::BufRead) -> Result<String> {
if splitted.len() != 2 {
bail!("Invalid header format");
}
debug!("Header: {:?}", splitted);
trace!("Header: {:?}", splitted);
if splitted[0] == "Content-Length" {
content_len = Some(usize::from_str(splitted[1])?);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/app_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn test_app_with_echo_server() -> Result<()> {
cmd.args(&["1", "cat"]);

let exit_status = app::run_app_forever(input_pair_out, output_file, cmd, app::AppOptions {
bytecode_options: Default::default(),
bytecode_options: Some(Default::default()),
})?;
assert!(!exit_status.success()); // timeout kill

Expand Down

0 comments on commit d138e01

Please sign in to comment.