From 462808e5b0fbdce5413256d9350f8bfcec0d56a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Thu, 29 Aug 2024 10:32:15 +0800 Subject: [PATCH] windows: Fix extensions couldn't start if the path contained spaces (#15489) Closes #15441 . Fixed the issue where extensions couldn't start if the path contained spaces. Additionally, this PR introduces the `node_environment_path` function to obtain the PATH environment variable which includes the node path. Release Notes: - N/A --- crates/languages/src/tailwind.rs | 21 +++++---------- crates/node_runtime/src/node_runtime.rs | 36 ++++++++++++++++--------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/crates/languages/src/tailwind.rs b/crates/languages/src/tailwind.rs index e4486efe8e..39ccc8afa1 100644 --- a/crates/languages/src/tailwind.rs +++ b/crates/languages/src/tailwind.rs @@ -23,10 +23,16 @@ const SERVER_PATH: &str = "node_modules/.bin/tailwindcss-language-server.ps1"; #[cfg(not(target_os = "windows"))] const SERVER_PATH: &str = "node_modules/.bin/tailwindcss-language-server"; +#[cfg(not(target_os = "windows"))] fn server_binary_arguments(server_path: &Path) -> Vec { vec![server_path.into(), "--stdio".into()] } +#[cfg(target_os = "windows")] +fn server_binary_arguments(server_path: &Path) -> Vec { + vec!["-File".into(), server_path.into(), "--stdio".into()] +} + pub struct TailwindLspAdapter { node: Arc, } @@ -113,20 +119,7 @@ impl LspAdapter for TailwindLspAdapter { #[cfg(target_os = "windows")] { - let mut env_path = vec![self - .node - .binary_path() - .await? - .parent() - .expect("invalid node binary path") - .to_path_buf()]; - - if let Some(existing_path) = std::env::var_os("PATH") { - let mut paths = std::env::split_paths(&existing_path).collect::>(); - env_path.append(&mut paths); - } - - let env_path = std::env::join_paths(env_path)?; + let env_path = self.node.node_environment_path().await?; let mut env = HashMap::default(); env.insert("PATH".to_string(), env_path.to_string_lossy().to_string()); diff --git a/crates/node_runtime/src/node_runtime.rs b/crates/node_runtime/src/node_runtime.rs index cc4bacc54d..8ea392d1a7 100644 --- a/crates/node_runtime/src/node_runtime.rs +++ b/crates/node_runtime/src/node_runtime.rs @@ -10,6 +10,7 @@ use semver::Version; use serde::Deserialize; use smol::io::BufReader; use smol::{fs, lock::Mutex, process::Command}; +use std::ffi::OsString; use std::io; use std::process::{Output, Stdio}; use std::{ @@ -55,6 +56,7 @@ pub struct NpmInfoDistTags { #[async_trait::async_trait] pub trait NodeRuntime: Send + Sync { async fn binary_path(&self) -> Result; + async fn node_environment_path(&self) -> Result; async fn run_npm_subcommand( &self, @@ -216,6 +218,22 @@ impl NodeRuntime for RealNodeRuntime { Ok(installation_path.join(NODE_PATH)) } + async fn node_environment_path(&self) -> Result { + let installation_path = self.install_if_needed().await?; + let node_binary = installation_path.join(NODE_PATH); + let mut env_path = vec![node_binary + .parent() + .expect("invalid node binary path") + .to_path_buf()]; + + if let Some(existing_path) = std::env::var_os("PATH") { + let mut paths = std::env::split_paths(&existing_path).collect::>(); + env_path.append(&mut paths); + } + + Ok(std::env::join_paths(env_path).context("failed to create PATH env variable")?) + } + async fn run_npm_subcommand( &self, directory: Option<&Path>, @@ -224,21 +242,9 @@ impl NodeRuntime for RealNodeRuntime { ) -> Result { let attempt = || async move { let installation_path = self.install_if_needed().await?; - let node_binary = installation_path.join(NODE_PATH); let npm_file = installation_path.join(NPM_PATH); - let mut env_path = vec![node_binary - .parent() - .expect("invalid node binary path") - .to_path_buf()]; - - if let Some(existing_path) = std::env::var_os("PATH") { - let mut paths = std::env::split_paths(&existing_path).collect::>(); - env_path.append(&mut paths); - } - - let env_path = - std::env::join_paths(env_path).context("failed to create PATH env variable")?; + let env_path = self.node_environment_path().await?; if smol::fs::metadata(&node_binary).await.is_err() { return Err(anyhow!("missing node binary file")); @@ -423,6 +429,10 @@ impl NodeRuntime for FakeNodeRuntime { unreachable!() } + async fn node_environment_path(&self) -> anyhow::Result { + unreachable!() + } + async fn run_npm_subcommand( &self, _: Option<&Path>,