-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use the LSP from workspace #9
Changes from all commits
de9da82
0389760
473ff7c
7d9ce65
1953f58
1b42138
e7dc5da
af61176
57fc993
dda7bb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,53 @@ | ||
use std::{env, fs}; | ||
use zed_extension_api::{self as zed, LanguageServerId, Result}; | ||
use std::{env, fs, path::Path}; | ||
use zed_extension_api::{self as zed, serde_json, LanguageServerId, Result}; | ||
|
||
const SERVER_PATH: &str = "node_modules/.bin/biome"; | ||
const SERVER_PATH: &str = "node_modules/@biomejs/biome/bin/biome"; | ||
const PACKAGE_NAME: &str = "@biomejs/biome"; | ||
|
||
struct BiomeExtension { | ||
did_find_server: bool, | ||
} | ||
struct BiomeExtension; | ||
|
||
impl BiomeExtension { | ||
fn server_exists(&self) -> bool { | ||
fs::metadata(SERVER_PATH).map_or(false, |stat| stat.is_file()) | ||
fn server_exists(&self, path: &str) -> bool { | ||
fs::metadata(path).map_or(false, |stat| stat.is_file()) | ||
} | ||
|
||
fn server_script_path(&mut self, language_server_id: &LanguageServerId) -> Result<String> { | ||
let server_exists = self.server_exists(); | ||
if self.did_find_server && server_exists { | ||
return Ok(SERVER_PATH.to_string()); | ||
fn server_script_path( | ||
&mut self, | ||
language_server_id: &LanguageServerId, | ||
worktree: &zed::Worktree, | ||
) -> Result<String> { | ||
// This is a workaround, as reading the file from wasm doesn't work. | ||
// Instead we try to read the `package.json`, see if `@biomejs/biome` is installed | ||
let package_json = worktree | ||
.read_text_file("package.json") | ||
.unwrap_or(String::from(r#"{}"#)); | ||
let package_json: Option<serde_json::Value> = serde_json::from_str(package_json.as_str()).ok(); | ||
|
||
let server_package_exists = package_json.is_some_and(|f| { | ||
!f["dependencies"]["@biomejs/biome"].is_null() | ||
|| !f["devDependencies"]["@biomejs/biome"].is_null() | ||
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this error if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested a bit, it will return null if one of the fields is non-existent. But feel free to test it again. |
||
}); | ||
|
||
if server_package_exists { | ||
let worktree_root_path = worktree.root_path(); | ||
let worktree_server_path = Path::new(worktree_root_path.as_str()) | ||
.join(SERVER_PATH) | ||
.to_string_lossy() | ||
.to_string(); | ||
|
||
return Ok(worktree_server_path); | ||
} | ||
|
||
zed::set_language_server_installation_status( | ||
language_server_id, | ||
&zed::LanguageServerInstallationStatus::CheckingForUpdate, | ||
); | ||
|
||
let fallback_server_path = SERVER_PATH.to_string(); | ||
let fallback_server_exist = self.server_exists(fallback_server_path.as_str()); | ||
let version = zed::npm_package_latest_version(PACKAGE_NAME)?; | ||
|
||
if !server_exists | ||
if !fallback_server_exist | ||
|| zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version) | ||
{ | ||
zed::set_language_server_installation_status( | ||
|
@@ -35,38 +57,35 @@ impl BiomeExtension { | |
let result = zed::npm_install_package(PACKAGE_NAME, &version); | ||
match result { | ||
Ok(()) => { | ||
if !self.server_exists() { | ||
if !self.server_exists(fallback_server_path.as_str()) { | ||
Err(format!( | ||
"installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'", | ||
"installed package '{PACKAGE_NAME}' did not contain expected path '{fallback_server_path}'", | ||
))?; | ||
} | ||
} | ||
Err(error) => { | ||
if !self.server_exists() { | ||
if !self.server_exists(fallback_server_path.as_str()) { | ||
Err(error)?; | ||
} | ||
} | ||
} | ||
} | ||
|
||
self.did_find_server = true; | ||
Ok(SERVER_PATH.to_string()) | ||
Ok(fallback_server_path.to_string()) | ||
} | ||
} | ||
|
||
impl zed::Extension for BiomeExtension { | ||
fn new() -> Self { | ||
Self { | ||
did_find_server: false, | ||
} | ||
Self | ||
} | ||
|
||
fn language_server_command( | ||
&mut self, | ||
language_server_id: &LanguageServerId, | ||
_worktree: &zed::Worktree, | ||
worktree: &zed::Worktree, | ||
) -> Result<zed::Command> { | ||
let path = self.server_script_path(language_server_id)?; | ||
let path = self.server_script_path(language_server_id, worktree)?; | ||
|
||
Ok(zed::Command { | ||
command: zed::node_binary_path()?, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check the existence of the LSP binary in the workspace with
fs::metadata
doesn't work, probably because of wasm. Instead, we can read thepackage.json
withworktree::read_text_file
and find out if the user has included the@biomejs/biome
as part ofdependencies
ordevDependencies
.Originally I was trying to read the
node_modules/@biomejs/biome/package.json
withworktree::read_text_file
, just to check if the user already installed the package, but it doesn't work for some reason.