diff --git a/Cargo.lock b/Cargo.lock index b01c22ed75b..8d3f951dddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -417,12 +417,42 @@ dependencies = [ "tempfile", ] +[[package]] +name = "async-io" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da8f3146014722c89e7859e1d7bb97873125d7346d10ca642ffab794355828" +dependencies = [ + "async-lock", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "waker-fn", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + [[package]] name = "async-lsp" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ + "async-io", "futures 0.3.30", "lsp-types 0.94.1", "pin-project-lite", @@ -554,9 +584,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitmaps" @@ -782,9 +812,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -978,6 +1008,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" +[[package]] +name = "concurrent-queue" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console" version = "0.15.8" @@ -1651,6 +1690,12 @@ dependencies = [ "str-buf", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "eyre" version = "0.6.8" @@ -1856,6 +1901,16 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -2635,16 +2690,16 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.4.1", "libc", "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -3041,6 +3096,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "noir_lsp_wasm" +version = "0.27.0" +dependencies = [ + "acvm", + "async-io", + "async-lsp", + "futures 0.3.30", + "noir_lsp", + "tower", +] + [[package]] name = "noir_wasm" version = "0.27.0" @@ -3208,7 +3275,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.4.1", "crossbeam-channel", "filetime", "fsevent-sys", @@ -3346,6 +3413,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.11.2" @@ -3528,6 +3601,20 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +dependencies = [ + "cfg-if 1.0.0", + "concurrent-queue", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "pprof" version = "0.12.1" @@ -3696,7 +3783,7 @@ checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.4.1", "lazy_static", "num-traits", "rand 0.8.5", @@ -4091,12 +4178,27 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom 0.2.10", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "rkyv" version = "0.7.42" @@ -4183,11 +4285,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.4" +version = "0.38.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -4196,12 +4298,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-webpki", "sct", ] @@ -4217,12 +4319,12 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -4363,8 +4465,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -4698,6 +4800,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.6.0" @@ -5343,6 +5451,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "1.7.2" @@ -5409,6 +5523,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + [[package]] name = "walkdir" version = "2.5.0" @@ -5679,7 +5799,7 @@ version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.4.1", "indexmap 2.0.0", "semver", ] diff --git a/Cargo.toml b/Cargo.toml index cdbb40f630a..f465efe7931 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "tooling/backend_interface", "tooling/bb_abstraction_leaks", "tooling/lsp", + "tooling/lsp_wasm", "tooling/debugger", "tooling/nargo", "tooling/nargo_fmt", @@ -75,6 +76,7 @@ nargo = { path = "tooling/nargo" } nargo_fmt = { path = "tooling/nargo_fmt" } nargo_toml = { path = "tooling/nargo_toml" } noir_lsp = { path = "tooling/lsp" } +noir_lsp_wasm = { path = "tooling/lsp_wasm" } noir_debugger = { path = "tooling/debugger" } noirc_abi = { path = "tooling/noirc_abi" } bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 750e85694e2..3f75f57a884 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true [dependencies] acvm.workspace = true codespan-lsp.workspace = true -lsp-types.workspace = true nargo.workspace = true nargo_fmt.workspace = true nargo_toml.workspace = true @@ -21,6 +20,7 @@ noirc_frontend.workspace = true serde.workspace = true serde_json.workspace = true tower.workspace = true +lsp-types.workspace = true async-lsp = { workspace = true, features = ["omni-trait"] } serde_with = "3.2.0" thiserror.workspace = true diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index be9b83e02f6..54db5a95aff 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -152,6 +152,15 @@ impl LspService for NargoLspService { } } +// This smooths over `vscode-test-web://` or other schemes that may be sent from a browser client +fn uri_to_file_path(uri: &Url) -> Result { + if uri.scheme() == "vscode-test-web" { + Ok(PathBuf::from("/").join(uri.path())) + } else { + uri.to_file_path() + } +} + fn get_package_tests_in_crate( context: &Context, crate_id: &CrateId, @@ -170,6 +179,8 @@ fn get_package_tests_in_crate( let file_path = fm.path(file_id).expect("file must exist to contain tests"); let range = byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + // These `file://` URIs are currently normalized inside of the vscode extension + // TODO: Do proper normalization inside the LSP instead of at the extension let file_uri = Url::from_file_path(file_path) .expect("Expected a valid file path that can be converted into a URI"); diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 355bb7832c4..efab57b19b8 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -59,13 +59,13 @@ pub(super) fn on_did_change_text_document( let _ = check_crate(&mut context, crate_id, false, false); let workspace = match resolve_workspace_for_source_path( - params.text_document.uri.to_file_path().unwrap().as_path(), + ¶ms.text_document.uri.to_file_path().unwrap(), ) { Ok(workspace) => workspace, Err(lsp_error) => { return ControlFlow::Break(Err(ResponseError::new( ErrorCode::REQUEST_FAILED, - lsp_error.to_string(), + lsp_error, ) .into())) } diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs index 893ba33d845..6b50116385d 100644 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -9,7 +9,7 @@ use noirc_frontend::hir::FunctionNameMatch; use crate::{ byte_span_to_range, prepare_source, resolve_workspace_for_source_path, types::{CodeLens, CodeLensParams, CodeLensResult, Command}, - LspState, + uri_to_file_path, LspState, }; const ARROW: &str = "▶\u{fe0e}"; @@ -49,7 +49,7 @@ fn on_code_lens_request_inner( state: &mut LspState, params: CodeLensParams, ) -> Result { - let file_path = params.text_document.uri.to_file_path().map_err(|_| { + let file_path = uri_to_file_path(¶ms.text_document.uri).map_err(|_| { ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") })?; diff --git a/tooling/lsp_wasm/Cargo.toml b/tooling/lsp_wasm/Cargo.toml new file mode 100644 index 00000000000..a9ece204d36 --- /dev/null +++ b/tooling/lsp_wasm/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "noir_lsp_wasm" +description = "Language server for Noir compiled to WASI" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +noir_lsp.workspace = true +tower.workspace = true +futures = { version = "0.3.28", default-features = false, features = ["async-await", "std", "executor"] } +async-lsp = { workspace = true, features = ["omni-trait", "stdio", "async-io"] } +async-io = "2" diff --git a/tooling/lsp_wasm/src/main.rs b/tooling/lsp_wasm/src/main.rs new file mode 100644 index 00000000000..07246dff63c --- /dev/null +++ b/tooling/lsp_wasm/src/main.rs @@ -0,0 +1,32 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +use async_lsp::{concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer}; +use noir_lsp::NargoLspService; +use tower::ServiceBuilder; + +fn main() { + // let blackbox_solver = acvm::blackbox_solver::BarretenbergSolver::initialize().await; + let blackbox_solver = acvm::blackbox_solver::StubbedBlackBoxSolver; + let (server, _) = async_lsp::MainLoop::new_server(|client| { + let router = NargoLspService::new(&client, blackbox_solver); + + ServiceBuilder::new() + .layer(LifecycleLayer::default()) + .layer(CatchUnwindLayer::default()) + .layer(ConcurrencyLayer::default()) + .service(router) + }); + + let stdin = async_lsp::stdio::PipeStdin::lock().expect("stdin to lock"); + let stdout = async_lsp::stdio::PipeStdout::lock().expect("stdout to lock"); + + let stdin = async_io::Async::new(stdin).expect("stdin to async-ify"); + let stdout = async_io::Async::new(stdout).expect("stdout to async-ify"); + + futures::executor::block_on(async { + server.run_buffered(stdin, stdout).await.expect("server should start"); + }); +} diff --git a/tooling/noirc_abi_wasm/src/js_witness_map.rs b/tooling/noirc_abi_wasm/src/js_witness_map.rs index 293c5c089f8..2fa658734f0 100644 --- a/tooling/noirc_abi_wasm/src/js_witness_map.rs +++ b/tooling/noirc_abi_wasm/src/js_witness_map.rs @@ -54,7 +54,7 @@ pub(crate) fn js_value_to_field_element(js_value: JsValue) -> Result JsString {