@@ -141,7 +141,7 @@ impl CachedLspAdapter {
self.adapter.cached_server_binary(container_dir).await
}
- async fn installation_test_binary(
+ pub async fn installation_test_binary(
&self,
container_dir: PathBuf,
) -> Option<LanguageServerBinary> {
@@ -544,6 +544,7 @@ struct LanguageRegistryState {
pub struct PendingLanguageServer {
pub server_id: LanguageServerId,
pub task: Task<Result<lsp::LanguageServer>>,
+ pub container_dir: Option<Arc<Path>>,
}
impl LanguageRegistry {
@@ -824,8 +825,8 @@ impl LanguageRegistry {
cx: &mut AppContext,
) -> Option<PendingLanguageServer> {
let server_id = self.state.write().next_language_server_id();
- log::info!(
- "starting language server name:{}, path:{root_path:?}, id:{server_id}",
+ println!(
+ "starting language server {:?}, path: {root_path:?}, id: {server_id}",
adapter.name.0
);
@@ -858,7 +859,11 @@ impl LanguageRegistry {
Ok(server)
});
- return Some(PendingLanguageServer { server_id, task });
+ return Some(PendingLanguageServer {
+ server_id,
+ task,
+ container_dir: None,
+ });
}
let download_dir = self
@@ -869,46 +874,54 @@ impl LanguageRegistry {
let this = self.clone();
let language = language.clone();
let http_client = http_client.clone();
- let download_dir = download_dir.clone();
+ let container_dir: Arc<Path> = Arc::from(download_dir.join(adapter.name.0.as_ref()));
let root_path = root_path.clone();
let adapter = adapter.clone();
let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone();
let login_shell_env_loaded = self.login_shell_env_loaded.clone();
- let task = cx.spawn(|cx| async move {
- login_shell_env_loaded.await;
-
- let mut lock = this.lsp_binary_paths.lock();
- let entry = lock
- .entry(adapter.name.clone())
- .or_insert_with(|| {
- get_binary(
- adapter.clone(),
- language.clone(),
- http_client,
- download_dir,
- lsp_binary_statuses,
- )
- .map_err(Arc::new)
- .boxed()
- .shared()
- })
- .clone();
- drop(lock);
+ let task = {
+ let container_dir = container_dir.clone();
+ cx.spawn(|cx| async move {
+ login_shell_env_loaded.await;
- let binary = entry.clone().map_err(|e| anyhow!(e)).await?;
- let server = lsp::LanguageServer::new(
- server_id,
- binary,
- &root_path,
- adapter.code_action_kinds(),
- cx,
- )?;
+ let mut lock = this.lsp_binary_paths.lock();
+ let entry = lock
+ .entry(adapter.name.clone())
+ .or_insert_with(|| {
+ get_binaries(
+ adapter.clone(),
+ language.clone(),
+ http_client,
+ container_dir,
+ lsp_binary_statuses,
+ )
+ .map_err(Arc::new)
+ .boxed()
+ .shared()
+ })
+ .clone();
+ drop(lock);
+
+ let binaries = entry.clone().map_err(|e| anyhow!(e)).await?;
+ println!("starting server");
+ let server = lsp::LanguageServer::new(
+ server_id,
+ binaries,
+ &root_path,
+ adapter.code_action_kinds(),
+ cx,
+ )?;
- Ok(server)
- });
+ Ok(server)
+ })
+ };
- Some(PendingLanguageServer { server_id, task })
+ Some(PendingLanguageServer {
+ server_id,
+ task,
+ container_dir: Some(container_dir),
+ })
}
pub fn language_server_binary_statuses(
@@ -922,6 +935,7 @@ impl LanguageRegistry {
adapter: Arc<CachedLspAdapter>,
cx: &mut AppContext,
) -> Task<()> {
+ println!("deleting server container");
let mut lock = self.lsp_binary_paths.lock();
lock.remove(&adapter.name);
@@ -984,20 +998,20 @@ impl Default for LanguageRegistry {
}
}
-async fn get_binary(
+async fn get_binaries(
adapter: Arc<CachedLspAdapter>,
language: Arc<Language>,
http_client: Arc<dyn HttpClient>,
- download_dir: Arc<Path>,
+ container_dir: Arc<Path>,
statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
) -> Result<LanguageServerBinaries> {
- let container_dir = download_dir.join(adapter.name.0.as_ref());
if !container_dir.exists() {
smol::fs::create_dir_all(&container_dir)
.await
.context("failed to create container directory")?;
}
+ println!("fetching binary");
let binary = fetch_latest_binary(
adapter.clone(),
language.clone(),
@@ -1008,11 +1022,16 @@ async fn get_binary(
.await;
if let Err(error) = binary.as_ref() {
- if let Some(binary) = adapter.cached_server_binary(container_dir.clone()).await {
+ if let Some(binary) = adapter
+ .cached_server_binary(container_dir.to_path_buf())
+ .await
+ {
statuses
.broadcast((language.clone(), LanguageServerBinaryStatus::Cached))
.await?;
- let installation_test_binary = adapter.installation_test_binary(container_dir).await;
+ let installation_test_binary = adapter
+ .installation_test_binary(container_dir.to_path_buf())
+ .await;
return Ok(LanguageServerBinaries {
binary,
installation_test_binary,
@@ -65,7 +65,7 @@ pub struct LanguageServer {
output_done_rx: Mutex<Option<barrier::Receiver>>,
root_path: PathBuf,
server: Option<Mutex<Child>>,
- test_installation_binary: Option<LanguageServerBinary>,
+ installation_test_binary: Option<LanguageServerBinary>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -190,7 +190,7 @@ impl LanguageServer {
stdin: Stdin,
stdout: Stdout,
server: Option<Child>,
- test_installation_binary: Option<LanguageServerBinary>,
+ installation_test_binary: Option<LanguageServerBinary>,
root_path: &Path,
code_action_kinds: Option<Vec<CodeActionKind>>,
cx: AsyncAppContext,
@@ -245,7 +245,7 @@ impl LanguageServer {
output_done_rx: Mutex::new(Some(output_done_rx)),
root_path: root_path.to_path_buf(),
server: server.map(|server| Mutex::new(server)),
- test_installation_binary,
+ installation_test_binary,
}
}
@@ -262,8 +262,8 @@ impl LanguageServer {
}
}
- pub fn test_installation_binary(&self) -> &Option<LanguageServerBinary> {
- &self.test_installation_binary
+ pub fn installation_test_binary(&self) -> &Option<LanguageServerBinary> {
+ &self.installation_test_binary
}
pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
@@ -45,7 +45,7 @@ use language::{
use log::error;
use lsp::{
DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,
- DocumentHighlightKind, LanguageServer, LanguageServerId, OneOf,
+ DocumentHighlightKind, LanguageServer, LanguageServerBinary, LanguageServerId, OneOf,
};
use lsp_command::*;
use postage::watch;
@@ -2442,22 +2442,23 @@ impl Project {
}
let server_id = pending_server.server_id;
+ let container_dir = pending_server.container_dir.clone();
let state = LanguageServerState::Starting({
let server_name = adapter.name.0.clone();
let languages = self.languages.clone();
let key = key.clone();
- cx.spawn_weak(|this, cx| async move {
+ cx.spawn_weak(|this, mut cx| async move {
let result = Self::setup_and_insert_language_server(
this,
initialization_options,
pending_server,
- adapter,
+ adapter.clone(),
languages,
language,
server_id,
key,
- cx,
+ &mut cx,
)
.await;
@@ -2465,8 +2466,24 @@ impl Project {
Ok(server) => Some(server),
Err(err) => {
- log::warn!("Error starting language server {:?}: {}", server_name, err);
- // TODO: Prompt installation validity check LSP ERROR
+ println!("failed to start language server {:?}: {}", server_name, err);
+
+ if let Some(this) = this.upgrade(&cx) {
+ if let Some(container_dir) = container_dir {
+ let installation_test_binary = adapter
+ .installation_test_binary(container_dir.to_path_buf())
+ .await;
+
+ this.update(&mut cx, |_, cx| {
+ Self::check_errored_server_id(
+ server_id,
+ installation_test_binary,
+ cx,
+ )
+ });
+ }
+ }
+
None
}
}
@@ -2482,6 +2499,7 @@ impl Project {
server_id: LanguageServerId,
cx: &mut ModelContext<Self>,
) -> Option<Task<()>> {
+ println!("starting to reinstall server");
let (adapter, language, server) = match self.language_servers.remove(&server_id) {
Some(LanguageServerState::Running {
adapter,
@@ -2495,6 +2513,7 @@ impl Project {
Some(cx.spawn(move |this, mut cx| async move {
if let Some(task) = server.shutdown() {
+ println!("shutting down existing server");
task.await;
}
@@ -2516,6 +2535,7 @@ impl Project {
let worktree_id = worktree.id();
let root_path = worktree.abs_path();
+ println!("prompting server start: {:?}", &adapter.name.0);
this.start_language_server(
worktree_id,
root_path,
@@ -2537,7 +2557,7 @@ impl Project {
language: Arc<Language>,
server_id: LanguageServerId,
key: (WorktreeId, LanguageServerName),
- mut cx: AsyncAppContext,
+ cx: &mut AsyncAppContext,
) -> Result<Arc<LanguageServer>> {
let language_server = Self::setup_pending_language_server(
this,
@@ -2546,16 +2566,16 @@ impl Project {
adapter.clone(),
languages,
server_id,
- &mut cx,
+ cx,
)
.await?;
- let this = match this.upgrade(&mut cx) {
+ let this = match this.upgrade(cx) {
Some(this) => this,
None => return Err(anyhow!("failed to upgrade project handle")),
};
- this.update(&mut cx, |this, cx| {
+ this.update(cx, |this, cx| {
this.insert_newly_running_language_server(
language,
adapter,
@@ -3012,32 +3032,39 @@ impl Project {
.detach();
}
- fn check_errored_lsp_installation(
+ fn check_errored_language_server(
&self,
language_server: Arc<LanguageServer>,
cx: &mut ModelContext<Self>,
) {
- cx.spawn(|this, mut cx| async move {
- if !language_server.is_dead() {
- return;
- }
- let server_id = language_server.server_id();
+ if !language_server.is_dead() {
+ return;
+ }
+
+ let server_id = language_server.server_id();
+ let installation_test_binary = language_server.installation_test_binary().clone();
+ Self::check_errored_server_id(server_id, installation_test_binary, cx);
+ }
+ fn check_errored_server_id(
+ server_id: LanguageServerId,
+ installation_test_binary: Option<LanguageServerBinary>,
+ cx: &mut ModelContext<Self>,
+ ) {
+ cx.spawn(|this, mut cx| async move {
+ println!("About to spawn test binary");
// A lack of test binary counts as a failure
- let process = language_server
- .test_installation_binary()
- .as_ref()
- .and_then(|binary| {
- smol::process::Command::new(&binary.path)
- .current_dir(&binary.path)
- .args(&binary.arguments)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::inherit())
- .kill_on_drop(true)
- .spawn()
- .ok()
- });
+ let process = installation_test_binary.and_then(|binary| {
+ smol::process::Command::new(&binary.path)
+ .current_dir(&binary.path)
+ .args(binary.arguments)
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::inherit())
+ .kill_on_drop(true)
+ .spawn()
+ .ok()
+ });
const PROCESS_TIMEOUT: Duration = Duration::from_secs(5);
let mut timeout = cx.background().timer(PROCESS_TIMEOUT).fuse();
@@ -3046,13 +3073,14 @@ impl Project {
if let Some(mut process) = process {
futures::select! {
status = process.status().fuse() => match status {
- Ok(status) => errored = !status.success(),
+ Ok(status) => errored = !dbg!(status.success()),
Err(_) => errored = true,
},
- _ = timeout => {}
+ _ = timeout => { println!("test binary time-ed out"); }
}
} else {
+ println!("test binary failed to launch");
errored = true;
}
@@ -3883,7 +3911,7 @@ impl Project {
);
this.update(cx, |this, cx| {
- this.check_errored_lsp_installation(language_server.clone(), cx);
+ this.check_errored_language_server(language_server.clone(), cx);
});
None