Make python run local worktree LSPs (#18353)
Release Notes: - Python: made it possible to use locally installed `pyright` if available --------- Co-authored-by: conrad <conrad@zed.dev>
This commit is contained in:
parent
dc7c49bd0b
commit
ae6a3d15af
4 changed files with 73 additions and 1 deletions
|
@ -313,6 +313,10 @@ pub trait LspAdapterDelegate: Send + Sync {
|
||||||
fn update_status(&self, language: LanguageServerName, status: LanguageServerBinaryStatus);
|
fn update_status(&self, language: LanguageServerName, status: LanguageServerBinaryStatus);
|
||||||
async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
|
async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
|
||||||
|
|
||||||
|
async fn npm_package_installed_version(
|
||||||
|
&self,
|
||||||
|
package_name: &str,
|
||||||
|
) -> Result<Option<(PathBuf, String)>>;
|
||||||
async fn which(&self, command: &OsStr) -> Option<PathBuf>;
|
async fn which(&self, command: &OsStr) -> Option<PathBuf>;
|
||||||
async fn shell_env(&self) -> HashMap<String, String>;
|
async fn shell_env(&self) -> HashMap<String, String>;
|
||||||
async fn read_text_file(&self, path: PathBuf) -> Result<String>;
|
async fn read_text_file(&self, path: PathBuf) -> Result<String>;
|
||||||
|
|
|
@ -20,6 +20,7 @@ use task::{TaskTemplate, TaskTemplates, VariableName};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
const SERVER_PATH: &str = "node_modules/pyright/langserver.index.js";
|
const SERVER_PATH: &str = "node_modules/pyright/langserver.index.js";
|
||||||
|
const NODE_MODULE_RELATIVE_SERVER_PATH: &str = "pyright/langserver.index.js";
|
||||||
|
|
||||||
fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||||
vec![server_path.into(), "--stdio".into()]
|
vec![server_path.into(), "--stdio".into()]
|
||||||
|
@ -43,6 +44,26 @@ impl LspAdapter for PythonLspAdapter {
|
||||||
Self::SERVER_NAME.clone()
|
Self::SERVER_NAME.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn check_if_user_installed(
|
||||||
|
&self,
|
||||||
|
delegate: &dyn LspAdapterDelegate,
|
||||||
|
_: &AsyncAppContext,
|
||||||
|
) -> Option<LanguageServerBinary> {
|
||||||
|
let node = delegate.which("node".as_ref()).await?;
|
||||||
|
let (node_modules_path, _) = delegate
|
||||||
|
.npm_package_installed_version(Self::SERVER_NAME.as_ref())
|
||||||
|
.await
|
||||||
|
.log_err()??;
|
||||||
|
|
||||||
|
let path = node_modules_path.join(NODE_MODULE_RELATIVE_SERVER_PATH);
|
||||||
|
|
||||||
|
Some(LanguageServerBinary {
|
||||||
|
path: node,
|
||||||
|
env: None,
|
||||||
|
arguments: server_binary_arguments(&path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async fn fetch_latest_server_version(
|
async fn fetch_latest_server_version(
|
||||||
&self,
|
&self,
|
||||||
_: &dyn LspAdapterDelegate,
|
_: &dyn LspAdapterDelegate,
|
||||||
|
|
|
@ -177,6 +177,7 @@ impl NodeRuntime {
|
||||||
"5000",
|
"5000",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// This is also wrong because the directory is wrong.
|
||||||
self.run_npm_subcommand(directory, "install", &arguments)
|
self.run_npm_subcommand(directory, "install", &arguments)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -576,7 +577,7 @@ impl NodeRuntimeTrait for SystemNodeRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_package_installed_version(
|
pub async fn read_package_installed_version(
|
||||||
node_module_directory: PathBuf,
|
node_module_directory: PathBuf,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<Option<String>> {
|
) -> Result<Option<String>> {
|
||||||
|
|
|
@ -48,6 +48,7 @@ use lsp::{
|
||||||
LspRequestFuture, MessageActionItem, MessageType, OneOf, ServerHealthStatus, ServerStatus,
|
LspRequestFuture, MessageActionItem, MessageType, OneOf, ServerHealthStatus, ServerStatus,
|
||||||
SymbolKind, TextEdit, Url, WorkDoneProgressCancelParams, WorkspaceFolder,
|
SymbolKind, TextEdit, Url, WorkDoneProgressCancelParams, WorkspaceFolder,
|
||||||
};
|
};
|
||||||
|
use node_runtime::read_package_installed_version;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
@ -7801,6 +7802,44 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
|
||||||
task.await.unwrap_or_default()
|
task.await.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn npm_package_installed_version(
|
||||||
|
&self,
|
||||||
|
package_name: &str,
|
||||||
|
) -> Result<Option<(PathBuf, String)>> {
|
||||||
|
let local_package_directory = self.worktree_root_path();
|
||||||
|
let node_modules_directory = local_package_directory.join("node_modules");
|
||||||
|
|
||||||
|
if let Some(version) =
|
||||||
|
read_package_installed_version(node_modules_directory.clone(), package_name).await?
|
||||||
|
{
|
||||||
|
return Ok(Some((node_modules_directory, version)));
|
||||||
|
}
|
||||||
|
let Some(npm) = self.which("npm".as_ref()).await else {
|
||||||
|
log::warn!(
|
||||||
|
"Failed to find npm executable for {:?}",
|
||||||
|
local_package_directory
|
||||||
|
);
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let env = self.shell_env().await;
|
||||||
|
let output = smol::process::Command::new(&npm)
|
||||||
|
.args(["root", "-g"])
|
||||||
|
.envs(env)
|
||||||
|
.current_dir(local_package_directory)
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
let global_node_modules =
|
||||||
|
PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string());
|
||||||
|
|
||||||
|
if let Some(version) =
|
||||||
|
read_package_installed_version(global_node_modules.clone(), package_name).await?
|
||||||
|
{
|
||||||
|
return Ok(Some((global_node_modules, version)));
|
||||||
|
}
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
async fn which(&self, command: &OsStr) -> Option<PathBuf> {
|
async fn which(&self, command: &OsStr) -> Option<PathBuf> {
|
||||||
let worktree_abs_path = self.worktree.abs_path();
|
let worktree_abs_path = self.worktree.abs_path();
|
||||||
|
@ -7883,6 +7922,13 @@ impl LspAdapterDelegate for SshLspAdapterDelegate {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn npm_package_installed_version(
|
||||||
|
&self,
|
||||||
|
_package_name: &str,
|
||||||
|
) -> Result<Option<(PathBuf, String)>> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
fn http_client(&self) -> Arc<dyn HttpClient> {
|
fn http_client(&self) -> Arc<dyn HttpClient> {
|
||||||
Arc::new(BlockedHttpClient)
|
Arc::new(BlockedHttpClient)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue