From 5189416434adc67a2e0e9959c9fd9e0e29666eca Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Fri, 3 Feb 2023 12:37:52 +0800 Subject: [PATCH] Refactor to bubble up as many errors as possible to lapce 1. Respond to the initialization request with InitializeResult::default(). 2. Bubble up error to Lapce except when using `host_sucess`, `host_error` and `start_lsp` because if they fail then there's not much that can be done. A better way to deal with issues in plugins is for Lapce to be aware of it but this should work for now. Signed-off-by: Hanif Bin Ariffin --- .gitignore | 1 + Cargo.lock | 127 +++++++++++++++++++++++----------------------------- Cargo.toml | 6 +-- src/main.rs | 119 ++++++++++++++++++++++++------------------------ 4 files changed, 118 insertions(+), 135 deletions(-) diff --git a/.gitignore b/.gitignore index ad8d4b5..9382a5a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ **/*.rs.bk lapce-rust.wasm +justfile diff --git a/Cargo.lock b/Cargo.lock index 7008dd9..73fd522 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,15 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "anyhow" -version = "1.0.61" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] name = "bitflags" @@ -40,22 +34,20 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crc32fast" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ - "cfg-if", "crc32fast", - "libc", "miniz_oxide", ] @@ -99,9 +91,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jsonrpc-lite" @@ -116,19 +108,19 @@ dependencies = [ [[package]] name = "lapce-plugin" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c169cb693c2c10ff40addb0429697d90f506c938d405932b2c46e529bcb555c" +version = "0.1.0" +source = "git+https://github.com/lapce/lapce-plugin-rust?rev=1657b855016c6bb50953e74eba4d079bf3173d63#1657b855016c6bb50953e74eba4d079bf3173d63" dependencies = [ "anyhow", "bytes", "http", "jsonrpc-lite", - "lapce-wasi-experimental-http", "once_cell", "psp-types", "serde", "serde_json", + "thiserror", + "wasi-experimental-http", ] [[package]] @@ -142,25 +134,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "lapce-wasi-experimental-http" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf7608ac13ab536e2481cdbe0cb4e6ecf34f19e0b3dcd6bcd002fe959ce810e" -dependencies = [ - "anyhow", - "bytes", - "http", - "thiserror", - "tracing", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - [[package]] name = "log" version = "0.4.17" @@ -191,19 +164,18 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", - "autocfg", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "percent-encoding" @@ -219,18 +191,17 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "psp-types" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edd2a687afe6f35676710d6c949faa5d0be0a2098dd81bb9dea1922cce859de" +source = "git+https://github.com/lapce/psp-types?branch=master#05112e8ebd0b73f089caa715e08b8e3a8c8fddc5" dependencies = [ "lsp-types", "serde", @@ -239,33 +210,33 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "serde" -version = "1.0.132" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.132" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -274,9 +245,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.73" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -296,29 +267,29 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.82" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -379,6 +350,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + [[package]] name = "unicode-normalization" version = "0.1.21" @@ -388,12 +365,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "url" version = "2.2.2" @@ -406,3 +377,15 @@ dependencies = [ "percent-encoding", "serde", ] + +[[package]] +name = "wasi-experimental-http" +version = "0.9.0" +source = "git+https://github.com/lapce/wasi-experimental-http#5c6d970fe0750932f76979678384bf1c5ab5be2e" +dependencies = [ + "anyhow", + "bytes", + "http", + "thiserror", + "tracing", +] diff --git a/Cargo.toml b/Cargo.toml index d58ddbe..55d2c9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] anyhow = "1.0" -flate2 = "1.0.22" -serde_json = "1.0.59" +flate2 = "1.0.25" +serde_json = "1.0.91" serde = { version = "1.0", features = ["derive"] } -lapce-plugin = "0.1.1" +lapce-plugin = { git = "https://github.com/lapce/lapce-plugin-rust", rev = "1657b855016c6bb50953e74eba4d079bf3173d63" } diff --git a/src/main.rs b/src/main.rs index 27de2f9..059104d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,13 @@ use std::{fs::File, path::PathBuf}; -use anyhow::Result; +use anyhow::{anyhow, Result}; use flate2::read::GzDecoder; use lapce_plugin::{ psp_types::{ - lsp_types::{request::Initialize, DocumentFilter, InitializeParams, MessageType, Url}, + lsp_types::{request::Initialize, DocumentFilter, InitializeParams, InitializeResult, Url}, Request, }, - register_plugin, Http, LapcePlugin, PLUGIN_RPC, + register_plugin, Http, LapcePlugin, VoltEnvironment, PLUGIN_RPC, }; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -30,7 +30,16 @@ pub struct Configuration { register_plugin!(State); -fn initialize(params: InitializeParams) -> Result<()> { +type LspParams = (Url, Vec, Vec, Option); + +fn calculate_lsp_params(params: Value) -> Result { + let params = serde_json::from_value::(params)?; + let document_filters = vec![DocumentFilter { + language: Some("rust".to_string()), + scheme: None, + pattern: Some("**/**.rs".to_string()), + }]; + let server_path = params .initialization_options .as_ref() @@ -45,55 +54,48 @@ fn initialize(params: InitializeParams) -> Result<()> { }); if let Some(server_path) = server_path { - let program = match std::env::var("VOLT_OS").as_deref() { + let program = match VoltEnvironment::operating_system().as_deref() { Ok("windows") => "where", _ => "which", }; - let exits = PLUGIN_RPC + return match PLUGIN_RPC .execute_process(program.to_string(), vec![server_path.to_string()]) .map(|r| r.success) - .unwrap_or(false); - if !exits { - PLUGIN_RPC.window_show_message( - MessageType::ERROR, - format!("server path {server_path} couldn't be found, please check"), - ); - return Ok(()); - } - PLUGIN_RPC.start_lsp( - Url::parse(&format!("urn:{}", server_path))?, - Vec::new(), - vec![DocumentFilter { - language: Some("rust".to_string()), - scheme: None, - pattern: None, - }], - params.initialization_options, - ); - return Ok(()); + { + Ok(true) => Ok(( + Url::parse(&format!("urn:{server_path}"))?, + Vec::new(), + document_filters, + params.initialization_options, + )), + Ok(false) => Err(anyhow!( + "Cannot find the LSP binary at the server path provided. Please check." + )), + Err(err) => Err(anyhow!("Unable to execute command because {}", err)), + }; } - let arch = match std::env::var("VOLT_ARCH").as_deref() { + let arch = match VoltEnvironment::architecture().as_deref() { Ok("x86_64") => "x86_64", Ok("aarch64") => "aarch64", - _ => return Ok(()), + Ok(o) => return Err(anyhow!("'{}' is not a supported architecture", o)), + Err(_) => return Err(anyhow!("Unable to determine the CPU architecture in use")), }; - let os = match std::env::var("VOLT_OS").as_deref() { + let os = match VoltEnvironment::operating_system().as_deref() { Ok("linux") => "unknown-linux-gnu", Ok("macos") => "apple-darwin", Ok("windows") => "pc-windows-msvc", - _ => return Ok(()), + Ok(o) => return Err(anyhow!("'{}' is not a supported operating system", o)), + Err(_) => return Err(anyhow!("Unable to determine the operating system in use")), }; - let file_name = format!("rust-analyzer-{}-{}", arch, os); + let file_name = format!("rust-analyzer-{arch}-{os}"); let file_path = PathBuf::from(&file_name); let gz_path = PathBuf::from(file_name.clone() + ".gz"); if !file_path.exists() { let result: Result<()> = { - let url = format!( - "https://github.com/rust-lang/rust-analyzer/releases/download/2023-01-02/{}.gz", - file_name - ); - let mut resp = Http::get(&url)?; + let mut resp = Http::get(&format!( + "https://github.com/rust-lang/rust-analyzer/releases/download/2023-01-02/{file_name}.gz" + ))?; let body = resp.body_read_all()?; std::fs::write(&gz_path, body)?; let mut gz = GzDecoder::new(File::open(&gz_path)?); @@ -102,41 +104,38 @@ fn initialize(params: InitializeParams) -> Result<()> { std::fs::remove_file(&gz_path)?; Ok(()) }; - if result.is_err() { - PLUGIN_RPC.window_show_message( - MessageType::ERROR, - format!("can't download rust-analyzer, please use server path in the settings."), - ); - return Ok(()); + if let Err(err) = result { + return Err(anyhow!( + "can't download rust-analyzer because '{}'. Please use server path in the settings.", + err.to_string() + )); } } - let volt_uri = std::env::var("VOLT_URI")?; - let server_path = Url::parse(&volt_uri)?.join(&file_name)?; - PLUGIN_RPC.start_lsp( - server_path, + return Ok(( + Url::parse(&format!("urn:{}", VoltEnvironment::uri()?))?.join(&file_name)?, Vec::new(), - vec![DocumentFilter { - language: Some("rust".to_string()), - scheme: None, - pattern: None, - }], + document_filters, params.initialization_options, - ); - Ok(()) + )); } impl LapcePlugin for State { - fn handle_request(&mut self, _id: u64, method: String, params: Value) { + fn handle_request(&mut self, id: u64, method: String, params: Value) { #[allow(clippy::single_match)] match method.as_str() { - Initialize::METHOD => { - let params: InitializeParams = serde_json::from_value(params).unwrap(); - if let Err(e) = initialize(params) { - PLUGIN_RPC.stderr(&format!("plugin returned with error: {e}")) + Initialize::METHOD => match calculate_lsp_params(params.clone()) { + Ok((uri, args, filters, params)) => { + PLUGIN_RPC.start_lsp(uri, args, filters, params).unwrap(); + PLUGIN_RPC + .host_success(id, InitializeResult::default()) + .unwrap() } - } - _ => {} - } + Err(err) => PLUGIN_RPC.host_error(id, err.to_string()).unwrap(), + }, + o => PLUGIN_RPC + .host_error(id, format!("Plugin does not understand method '{o}'")) + .unwrap(), + }; } }