windows: Fix `tailwindcss-language-server` (#13891)

张小白 created

We should run this server with `powershell`, or we will get some runtime
errors.

![Screenshot 2024-07-06
180154](https://github.com/zed-industries/zed/assets/14981363/e272e146-d4a8-4447-aa65-b657a49622de)


Release Notes:

- Fixed `tailwindcss-language-server` on Windows.

Change summary

crates/languages/src/tailwind.rs | 41 +++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 5 deletions(-)

Detailed changes

crates/languages/src/tailwind.rs 🔗

@@ -18,6 +18,9 @@ use std::{
 };
 use util::{maybe, ResultExt};
 
+#[cfg(target_os = "windows")]
+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";
 
 fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
@@ -108,11 +111,39 @@ impl LspAdapter for TailwindLspAdapter {
                 .await?;
         }
 
-        Ok(LanguageServerBinary {
-            path: self.node.binary_path().await?,
-            env: None,
-            arguments: server_binary_arguments(&server_path),
-        })
+        #[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::<Vec<_>>();
+                env_path.append(&mut paths);
+            }
+
+            let env_path = std::env::join_paths(env_path)?;
+            let mut env = HashMap::default();
+            env.insert("PATH".to_string(), env_path.to_string_lossy().to_string());
+
+            Ok(LanguageServerBinary {
+                path: "powershell.exe".into(),
+                env: Some(env),
+                arguments: server_binary_arguments(&server_path),
+            })
+        }
+        #[cfg(not(target_os = "windows"))]
+        {
+            Ok(LanguageServerBinary {
+                path: self.node.binary_path().await?,
+                env: None,
+                arguments: server_binary_arguments(&server_path),
+            })
+        }
     }
 
     async fn cached_server_binary(