From 7d5425e1423e5bb1cbaef268f0969aab0c4da556 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 26 Oct 2021 12:17:51 -0700 Subject: [PATCH] Move lsp configuration into language crate Co-Authored-By: Nathan Sobo --- crates/language/build.rs | 6 ++++ crates/language/src/language.rs | 40 +++++++++++++++++++++++++++ crates/lsp/build.rs | 10 ------- crates/lsp/src/lib.rs | 39 +++++++------------------- crates/project/src/lib.rs | 20 ++++++++++---- crates/project/src/worktree.rs | 3 +- crates/zed/languages/rust/config.toml | 4 +++ script/download-rust-analyzer | 4 +++ 8 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 crates/language/build.rs delete mode 100644 crates/lsp/build.rs diff --git a/crates/language/build.rs b/crates/language/build.rs new file mode 100644 index 0000000000..d69cce4d1d --- /dev/null +++ b/crates/language/build.rs @@ -0,0 +1,6 @@ +fn main() { + if let Ok(bundled) = std::env::var("ZED_BUNDLE") { + println!("cargo:rustc-env=ZED_BUNDLE={}", bundled); + } +} + diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 2260990566..b6ff132881 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -1,5 +1,6 @@ use crate::HighlightMap; use anyhow::Result; +use gpui::AppContext; use parking_lot::Mutex; use serde::Deserialize; use std::{path::Path, str, sync::Arc}; @@ -12,6 +13,13 @@ pub struct LanguageConfig { pub name: String, pub path_suffixes: Vec, pub brackets: Vec, + pub language_server: Option, +} + +#[derive(Deserialize)] +pub struct LanguageServerConfig { + pub binary: String, + pub disk_based_diagnostic_sources: Vec, } #[derive(Clone, Debug, Deserialize)] @@ -51,6 +59,12 @@ impl LanguageRegistry { } } + pub fn get_language(&self, name: &str) -> Option<&Arc> { + self.languages + .iter() + .find(|language| language.name() == name) + } + pub fn select_language(&self, path: impl AsRef) -> Option<&Arc> { let path = path.as_ref(); let filename = path.file_name().and_then(|name| name.to_str()); @@ -97,6 +111,32 @@ impl Language { self.config.name.as_str() } + pub fn start_server( + &self, + root_path: &Path, + cx: &AppContext, + ) -> Result>> { + if let Some(config) = &self.config.language_server { + const ZED_BUNDLE: Option<&'static str> = option_env!("ZED_BUNDLE"); + let binary_path = if ZED_BUNDLE.map_or(Ok(false), |b| b.parse())? { + cx.platform() + .path_for_resource(Some(&config.binary), None)? + } else { + Path::new(&config.binary).to_path_buf() + }; + lsp::LanguageServer::new(&binary_path, root_path, cx.background()).map(Some) + } else { + Ok(None) + } + } + + pub fn disk_based_diagnostic_sources(&self) -> &[String] { + self.config + .language_server + .as_ref() + .map_or(&[], |config| &config.disk_based_diagnostic_sources) + } + pub fn brackets(&self) -> &[BracketPair] { &self.config.brackets } diff --git a/crates/lsp/build.rs b/crates/lsp/build.rs deleted file mode 100644 index 703d9ccd3c..0000000000 --- a/crates/lsp/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::env; - -fn main() { - let target = env::var("TARGET").unwrap(); - println!("cargo:rustc-env=ZED_TARGET={}", target); - - if let Ok(bundled) = env::var("ZED_BUNDLE") { - println!("cargo:rustc-env=ZED_BUNDLE={}", bundled); - } -} diff --git a/crates/lsp/src/lib.rs b/crates/lsp/src/lib.rs index 1aba87e375..88fd5a4bc7 100644 --- a/crates/lsp/src/lib.rs +++ b/crates/lsp/src/lib.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Context, Result}; use futures::{io::BufWriter, AsyncRead, AsyncWrite}; -use gpui::{executor, AppContext, Task}; +use gpui::{executor, Task}; use parking_lot::{Mutex, RwLock}; use postage::{barrier, oneshot, prelude::Stream, sink::Sink}; use serde::{Deserialize, Serialize}; @@ -86,47 +86,25 @@ struct Error { } impl LanguageServer { - pub fn rust(root_path: &Path, cx: &AppContext) -> Result> { - const ZED_BUNDLE: Option<&'static str> = option_env!("ZED_BUNDLE"); - const ZED_TARGET: &'static str = env!("ZED_TARGET"); - - let rust_analyzer_name = format!("rust-analyzer-{}", ZED_TARGET); - if ZED_BUNDLE.map_or(Ok(false), |b| b.parse())? { - let rust_analyzer_path = cx - .platform() - .path_for_resource(Some(&rust_analyzer_name), None)?; - Self::new(root_path, &rust_analyzer_path, &[], cx.background()) - } else { - Self::new( - root_path, - Path::new(&rust_analyzer_name), - &[], - cx.background(), - ) - } - } - pub fn new( + binary_path: &Path, root_path: &Path, - server_path: &Path, - server_args: &[&str], background: &executor::Background, ) -> Result> { - let mut server = Command::new(server_path) - .args(server_args) + let mut server = Command::new(binary_path) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::inherit()) .spawn()?; let stdin = server.stdin.take().unwrap(); let stdout = server.stdout.take().unwrap(); - Self::new_internal(root_path, stdin, stdout, background) + Self::new_internal(stdin, stdout, root_path, background) } fn new_internal( - root_path: &Path, stdin: Stdin, stdout: Stdout, + root_path: &Path, background: &executor::Background, ) -> Result> where @@ -410,7 +388,7 @@ impl LanguageServer { buffer: Vec::new(), }; - let server = Self::new_internal(Path::new("/"), stdin.0, stdout.1, executor).unwrap(); + let server = Self::new_internal(stdin.0, stdout.1, Path::new("/"), executor).unwrap(); let (init_id, _) = fake.receive_request::().await; fake.respond(init_id, InitializeResult::default()).await; @@ -535,7 +513,10 @@ mod tests { let lib_file_uri = lsp_types::Url::from_file_path(root_dir.path().join("src/lib.rs")).unwrap(); - let server = cx.read(|cx| LanguageServer::rust(root_dir.path(), cx).unwrap()); + let server = cx.read(|cx| { + LanguageServer::new(Path::new("rust-analyzer"), root_dir.path(), cx.background()) + .unwrap() + }); server.next_idle_notification().await; server diff --git a/crates/project/src/lib.rs b/crates/project/src/lib.rs index a98b89db5a..552974bc69 100644 --- a/crates/project/src/lib.rs +++ b/crates/project/src/lib.rs @@ -8,12 +8,11 @@ use futures::Future; use fuzzy::{PathMatch, PathMatchCandidate, PathMatchCandidateSet}; use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task}; use language::LanguageRegistry; -use lsp::LanguageServer; use std::{ path::Path, sync::{atomic::AtomicBool, Arc}, }; -use util::TryFutureExt as _; +use util::{ResultExt, TryFutureExt as _}; pub use fs::*; pub use worktree::*; @@ -74,11 +73,20 @@ impl Project { let rpc = self.client.clone(); let languages = self.languages.clone(); let path = Arc::from(abs_path); - let language_server = LanguageServer::rust(&path, cx); + let language_server = languages + .get_language("Rust") + .unwrap() + .start_server(&path, cx); cx.spawn(|this, mut cx| async move { - let worktree = - Worktree::open_local(rpc, path, fs, languages, Some(language_server?), &mut cx) - .await?; + let worktree = Worktree::open_local( + rpc, + path, + fs, + languages, + language_server.log_err().flatten(), + &mut cx, + ) + .await?; this.update(&mut cx, |this, cx| { this.add_worktree(worktree.clone(), cx); }); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 47e400aa09..c05f121acc 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -295,7 +295,7 @@ impl Worktree { } } - pub fn language_server(&self) -> Option<&Arc> { + pub fn language_server(&self) -> Option<&Arc> { match self { Worktree::Local(worktree) => worktree.language_server.as_ref(), Worktree::Remote(_) => None, @@ -2872,7 +2872,6 @@ mod tests { use anyhow::Result; use client::test::FakeServer; use fs::RealFs; - use language::Point; use lsp::Url; use rand::prelude::*; use serde_json::json; diff --git a/crates/zed/languages/rust/config.toml b/crates/zed/languages/rust/config.toml index 11b273d137..5719164008 100644 --- a/crates/zed/languages/rust/config.toml +++ b/crates/zed/languages/rust/config.toml @@ -8,3 +8,7 @@ brackets = [ { start = "\"", end = "\"", close = true, newline = false }, { start = "/*", end = " */", close = true, newline = false }, ] + +[language_server] +binary = "rust-analyzer" +disk_based_diagnostic_sources = ["rustc"] diff --git a/script/download-rust-analyzer b/script/download-rust-analyzer index 9a64f9ed69..8cc0c00e6f 100755 --- a/script/download-rust-analyzer +++ b/script/download-rust-analyzer @@ -13,3 +13,7 @@ function download { mkdir -p vendor/bin download "x86_64-apple-darwin" download "aarch64-apple-darwin" + +cd vendor/bin +lipo -create rust-analyzer-* -output rust-analyzer +rm rust-analyzer-*