From c8ddada31c564b3be602e121b8ffc9966636f031 Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Fri, 28 Feb 2025 09:39:09 -0800 Subject: [PATCH 1/5] Initialize Cargo package --- .gitignore | 5 + Cargo.lock | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 ++ src/lib.rs | 14 +++ 4 files changed, 358 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore index 6509c91..bb2c6b4 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,8 @@ Icon Network Trash Folder Temporary Items .apdisk + + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..faa3f6a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,329 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "log" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" + +[[package]] +name = "serde" +version = "1.0.218" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.218" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[package]] +name = "spdx" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b69356da67e2fc1f542c71ea7e654a361a79c938e4424392ecf4fa065d2193" +dependencies = [ + "smallvec", +] + +[[package]] +name = "sql" +version = "1.1.2" +dependencies = [ + "zed_extension_api", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wasm-encoder" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fd83062c17b9f4985d438603cde0a5e8c5c8198201a6937f778b607924c7da2" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288f992ea30e6b5c531b52cdd5f3be81c148554b09ea416f058d16556ba92c27" +dependencies = [ + "bitflags", + "wit-bindgen-rt", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85e72719ffbccf279359ad071497e47eb0675fe22106dea4ed2d8a7fcb60ba4" +dependencies = [ + "anyhow", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb8738270f32a2d6739973cbbb7c1b6dd8959ce515578a6e19165853272ee64" + +[[package]] +name = "wit-bindgen-rust" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a39a15d1ae2077688213611209849cad40e9e5cccf6e61951a425850677ff3" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d376d3ae5850526dfd00d937faea0d81a06fa18f7ac1e26f386d760f241a8f4b" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421c0c848a0660a8c22e2fd217929a0191f14476b68962afd2af89fd22e39825" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196d3ecfc4b759a8573bf86a9b3f8996b304b3732e4c7de81655f875f6efdca6" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zed_extension_api" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd16b8b30a9dc920fc1678ff852f696b5bdf5b5843bc745a128be0aac29859e" +dependencies = [ + "serde", + "serde_json", + "wit-bindgen", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b5ca1b7 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "sql" +version = "1.1.2" +edition = "2024" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +zed_extension_api = "0.2.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..65ed6c1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,14 @@ +use zed_extension_api::{Extension, register_extension}; + +struct Sql; + +impl Extension for Sql { + fn new() -> Self + where + Self: Sized, + { + Self + } +} + +register_extension!(Sql); From fda32c1a5db3b182b504deff42916883de28bb77 Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Fri, 28 Feb 2025 11:56:53 -0800 Subject: [PATCH 2/5] Download and run sqls language server --- .gitignore | 7 ++- extension.toml | 4 ++ src/lib.rs | 117 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 121 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index bb2c6b4..147c205 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,6 @@ Network Trash Folder Temporary Items .apdisk - -# Added by cargo - -/target +target/ +grammars/ +extension.wasm diff --git a/extension.toml b/extension.toml index cdd7db9..8253cfc 100644 --- a/extension.toml +++ b/extension.toml @@ -9,3 +9,7 @@ repository = "https://github.com/nervenes/zed-sql" [grammars.sql] repository = "https://github.com/nervenes/tree-sitter-sql" commit = "6dfca8b6dcb196d943c10e9cabab25e60232d332" + +[language_servers.sqls] +name = "sqls" +languages = ["SQL"] diff --git a/src/lib.rs b/src/lib.rs index 65ed6c1..b5da9c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,124 @@ -use zed_extension_api::{Extension, register_extension}; +use std::{ + fs::{metadata, read_dir, remove_dir_all}, + path::Path, +}; -struct Sql; +use zed_extension_api::{ + self as zed, DownloadedFileType, Extension, GithubReleaseOptions, LanguageServerId, + LanguageServerInstallationStatus, Os, Worktree, current_platform, download_file, + latest_github_release, make_file_executable, register_extension, serde_json::Value, + set_language_server_installation_status, settings::LspSettings, +}; + +struct Sql { + command_path: Option, +} + +impl Sql { + fn get_command_path(&mut self, language_server_id: &LanguageServerId) -> zed::Result { + if let Some(command_path) = &self.command_path { + if metadata(command_path).is_ok_and(|metadata| metadata.is_file()) { + return Ok(command_path.clone()); + } + } + + set_language_server_installation_status( + language_server_id, + &LanguageServerInstallationStatus::CheckingForUpdate, + ); + + let latest_release = latest_github_release( + "sqls-server/sqls", + GithubReleaseOptions { + require_assets: true, + pre_release: false, + }, + )?; + let ls_path = format!("{language_server_id}/"); + let version_path = format!("{ls_path}{}/", latest_release.version); + let mut command_path = format!("{version_path}sqls"); + + if current_platform().0 == Os::Windows { + command_path += ".exe"; + } + + if metadata(&command_path).is_ok_and(|metadata| metadata.is_file()) { + set_language_server_installation_status( + language_server_id, + &LanguageServerInstallationStatus::None, + ); + + return Ok(command_path); + } + + let asset_name = format!( + "sqls-{}-{}.zip", + match current_platform().0 { + Os::Mac => "darwin", + Os::Linux => "linux", + Os::Windows => "windows", + }, + // Substring needed to remove the leading 'v' + &latest_release.version[1..], + ); + let asset = latest_release + .assets + .into_iter() + .find(|asset| asset.name == asset_name) + .ok_or("no asset found for platform")?; + + set_language_server_installation_status( + language_server_id, + &LanguageServerInstallationStatus::Downloading, + ); + download_file(&asset.download_url, &version_path, DownloadedFileType::Zip)?; + make_file_executable(&command_path)?; + + for entry in read_dir(ls_path).map_err(|err| err.to_string())? { + let entry = entry.map_err(|err| err.to_string())?; + let entry_path = entry.path(); + + if entry_path != Path::new(&version_path) { + remove_dir_all(entry_path).map_err(|err| err.to_string())?; + } + } + + set_language_server_installation_status( + language_server_id, + &LanguageServerInstallationStatus::None, + ); + + Ok(command_path) + } +} impl Extension for Sql { fn new() -> Self where Self: Sized, { - Self + Self { command_path: None } + } + + fn language_server_command( + &mut self, + language_server_id: &LanguageServerId, + _worktree: &Worktree, + ) -> zed::Result { + Ok(zed::Command { + command: self.get_command_path(language_server_id)?, + args: Vec::new(), + env: Vec::new(), + }) + } + + fn language_server_workspace_configuration( + &mut self, + language_server_id: &LanguageServerId, + worktree: &Worktree, + ) -> zed_extension_api::Result> { + LspSettings::for_worktree(language_server_id.as_ref(), worktree) + .map(|settings| settings.settings) } } From cc97b24147bf650b685ecfbfa153d04499fa8d14 Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Fri, 28 Feb 2025 11:58:48 -0800 Subject: [PATCH 3/5] Add myself to authors list I think adding support for a language server is substantial enough to warrant some credit --- extension.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension.toml b/extension.toml index 8253cfc..35539f3 100644 --- a/extension.toml +++ b/extension.toml @@ -2,7 +2,7 @@ id = "sql" name = "SQL" schema_version = 1 version = "1.1.2" -authors = ["nervenes", "notpeter", "phileix", "tammyxiong"] +authors = ["nervenes", "notpeter", "phileix", "tammyxiong", "valentinegb"] description = "SQL language support." repository = "https://github.com/nervenes/zed-sql" From 9a4219821eca1ae590b0a775e4b92f9e5677c89b Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Fri, 28 Feb 2025 22:35:48 -0800 Subject: [PATCH 4/5] Cache command path Oops, forgot to do that --- src/lib.rs | 61 +++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b5da9c1..1e7812d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,47 +42,42 @@ impl Sql { command_path += ".exe"; } - if metadata(&command_path).is_ok_and(|metadata| metadata.is_file()) { + if !metadata(&command_path).is_ok_and(|metadata| metadata.is_file()) { + let asset_name = format!( + "sqls-{}-{}.zip", + match current_platform().0 { + Os::Mac => "darwin", + Os::Linux => "linux", + Os::Windows => "windows", + }, + // Substring needed to remove the leading 'v' + &latest_release.version[1..], + ); + let asset = latest_release + .assets + .into_iter() + .find(|asset| asset.name == asset_name) + .ok_or("no asset found for platform")?; + set_language_server_installation_status( language_server_id, - &LanguageServerInstallationStatus::None, + &LanguageServerInstallationStatus::Downloading, ); + download_file(&asset.download_url, &version_path, DownloadedFileType::Zip)?; + make_file_executable(&command_path)?; - return Ok(command_path); - } - - let asset_name = format!( - "sqls-{}-{}.zip", - match current_platform().0 { - Os::Mac => "darwin", - Os::Linux => "linux", - Os::Windows => "windows", - }, - // Substring needed to remove the leading 'v' - &latest_release.version[1..], - ); - let asset = latest_release - .assets - .into_iter() - .find(|asset| asset.name == asset_name) - .ok_or("no asset found for platform")?; - - set_language_server_installation_status( - language_server_id, - &LanguageServerInstallationStatus::Downloading, - ); - download_file(&asset.download_url, &version_path, DownloadedFileType::Zip)?; - make_file_executable(&command_path)?; - - for entry in read_dir(ls_path).map_err(|err| err.to_string())? { - let entry = entry.map_err(|err| err.to_string())?; - let entry_path = entry.path(); + for entry in read_dir(ls_path).map_err(|err| err.to_string())? { + let entry = entry.map_err(|err| err.to_string())?; + let entry_path = entry.path(); - if entry_path != Path::new(&version_path) { - remove_dir_all(entry_path).map_err(|err| err.to_string())?; + if entry_path != Path::new(&version_path) { + remove_dir_all(entry_path).map_err(|err| err.to_string())?; + } } } + self.command_path = Some(command_path.clone()); + set_language_server_installation_status( language_server_id, &LanguageServerInstallationStatus::None, From cd3f78ca3ea0e2f182dc371ae428088466a297d9 Mon Sep 17 00:00:00 2001 From: NathanielH <108092467+NathanielH-snek@users.noreply.github.com> Date: Sat, 28 Mar 2026 23:54:10 -0400 Subject: [PATCH 5/5] Wrap Settings with sqls Barely had to do much to hook this up so credit to valentinegb. Tested with sqlite --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1e7812d..169bddf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ use std::{ use zed_extension_api::{ self as zed, DownloadedFileType, Extension, GithubReleaseOptions, LanguageServerId, LanguageServerInstallationStatus, Os, Worktree, current_platform, download_file, - latest_github_release, make_file_executable, register_extension, serde_json::Value, + latest_github_release, make_file_executable, register_extension, serde_json::{self, Value}, set_language_server_installation_status, settings::LspSettings, }; @@ -113,7 +113,7 @@ impl Extension for Sql { worktree: &Worktree, ) -> zed_extension_api::Result> { LspSettings::for_worktree(language_server_id.as_ref(), worktree) - .map(|settings| settings.settings) + .map(|settings| settings.settings.map(|s| serde_json::json!({ "sqls": s }))) } }