Improve lsp log viewer's behavior in the presence of LSP restarts

Improve settings interface to local LSP
This commit is contained in:
Mikayla 2023-09-24 04:59:55 -07:00
parent 02a85b1252
commit 052cb459a6
No known key found for this signature in database
6 changed files with 71 additions and 15 deletions

1
Cargo.lock generated
View file

@ -9868,6 +9868,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"settings", "settings",
"shellexpand",
"simplelog", "simplelog",
"smallvec", "smallvec",
"smol", "smol",

View file

@ -384,11 +384,11 @@
// "next": "off" // "next": "off"
// 2. Use a bundled version of the next Next LS LSP server // 2. Use a bundled version of the next Next LS LSP server
// "next": "on", // "next": "on",
// 3. Use a locally running version of the next Next LS LSP server, // 3. Use a local build of the next Next LS LSP server:
// on a specific port:
// "next": { // "next": {
// "local": { // "local": {
// "port": 4000 // "path": "~/next-ls/bin/start",
// "arguments": ["--stdio"]
// } // }
// }, // },
// //

View file

@ -8,8 +8,8 @@ use gpui::{
ParentElement, Stack, ParentElement, Stack,
}, },
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AnyElement, AppContext, Element, Entity, ModelContext, ModelHandle, View, ViewContext, AnyElement, AppContext, Element, Entity, ModelContext, ModelHandle, Subscription, View,
ViewHandle, WeakModelHandle, ViewContext, ViewHandle, WeakModelHandle,
}; };
use language::{Buffer, LanguageServerId, LanguageServerName}; use language::{Buffer, LanguageServerId, LanguageServerName};
use lsp::IoKind; use lsp::IoKind;
@ -52,10 +52,12 @@ pub struct LspLogView {
current_server_id: Option<LanguageServerId>, current_server_id: Option<LanguageServerId>,
is_showing_rpc_trace: bool, is_showing_rpc_trace: bool,
project: ModelHandle<Project>, project: ModelHandle<Project>,
_log_store_subscription: Subscription,
} }
pub struct LspLogToolbarItemView { pub struct LspLogToolbarItemView {
log_view: Option<ViewHandle<LspLogView>>, log_view: Option<ViewHandle<LspLogView>>,
_log_view_subscription: Option<Subscription>,
menu_open: bool, menu_open: bool,
} }
@ -346,12 +348,49 @@ impl LspLogView {
.get(&project.downgrade()) .get(&project.downgrade())
.and_then(|project| project.servers.keys().copied().next()); .and_then(|project| project.servers.keys().copied().next());
let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "")); let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, ""));
let _log_store_subscription = cx.observe(&log_store, |this, store, cx| {
(|| -> Option<()> {
let project_state = store.read(cx).projects.get(&this.project.downgrade())?;
if let Some(current_lsp) = this.current_server_id {
if !project_state.servers.contains_key(&current_lsp) {
if let Some(server) = project_state.servers.iter().next() {
if this.is_showing_rpc_trace {
this.show_rpc_trace_for_server(*server.0, cx)
} else {
this.show_logs_for_server(*server.0, cx)
}
} else {
this.current_server_id = None;
this.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
editor.clear(cx);
editor.set_read_only(true);
});
cx.notify();
}
}
} else {
if let Some(server) = project_state.servers.iter().next() {
if this.is_showing_rpc_trace {
this.show_rpc_trace_for_server(*server.0, cx)
} else {
this.show_logs_for_server(*server.0, cx)
}
}
}
Some(())
})();
cx.notify();
});
let mut this = Self { let mut this = Self {
editor: Self::editor_for_buffer(project.clone(), buffer, cx), editor: Self::editor_for_buffer(project.clone(), buffer, cx),
project, project,
log_store, log_store,
current_server_id: None, current_server_id: None,
is_showing_rpc_trace: false, is_showing_rpc_trace: false,
_log_store_subscription,
}; };
if let Some(server_id) = server_id { if let Some(server_id) = server_id {
this.show_logs_for_server(server_id, cx); this.show_logs_for_server(server_id, cx);
@ -556,18 +595,22 @@ impl ToolbarItemView for LspLogToolbarItemView {
fn set_active_pane_item( fn set_active_pane_item(
&mut self, &mut self,
active_pane_item: Option<&dyn ItemHandle>, active_pane_item: Option<&dyn ItemHandle>,
_: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> workspace::ToolbarItemLocation { ) -> workspace::ToolbarItemLocation {
self.menu_open = false; self.menu_open = false;
if let Some(item) = active_pane_item { if let Some(item) = active_pane_item {
if let Some(log_view) = item.downcast::<LspLogView>() { if let Some(log_view) = item.downcast::<LspLogView>() {
self.log_view = Some(log_view.clone()); self.log_view = Some(log_view.clone());
self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| {
cx.notify();
}));
return ToolbarItemLocation::PrimaryLeft { return ToolbarItemLocation::PrimaryLeft {
flex: Some((1., false)), flex: Some((1., false)),
}; };
} }
} }
self.log_view = None; self.log_view = None;
self._log_view_subscription = None;
ToolbarItemLocation::Hidden ToolbarItemLocation::Hidden
} }
} }
@ -697,6 +740,7 @@ impl LspLogToolbarItemView {
Self { Self {
menu_open: false, menu_open: false,
log_view: None, log_view: None,
_log_view_subscription: None,
} }
} }

View file

@ -62,6 +62,7 @@ rpc = { path = "../rpc" }
settings = { path = "../settings" } settings = { path = "../settings" }
feature_flags = { path = "../feature_flags" } feature_flags = { path = "../feature_flags" }
sum_tree = { path = "../sum_tree" } sum_tree = { path = "../sum_tree" }
shellexpand = "2.1.0"
text = { path = "../text" } text = { path = "../text" }
terminal_view = { path = "../terminal_view" } terminal_view = { path = "../terminal_view" }
theme = { path = "../theme" } theme = { path = "../theme" }

View file

@ -79,11 +79,12 @@ pub fn init(
vec![Arc::new(elixir::ElixirLspAdapter)], vec![Arc::new(elixir::ElixirLspAdapter)],
), ),
elixir_next::ElixirNextSetting::On => todo!(), elixir_next::ElixirNextSetting::On => todo!(),
elixir_next::ElixirNextSetting::Local { path } => language( elixir_next::ElixirNextSetting::Local { path, arguments } => language(
"elixir", "elixir",
tree_sitter_elixir::language(), tree_sitter_elixir::language(),
vec![Arc::new(elixir_next::LocalNextLspAdapter { vec![Arc::new(elixir_next::LocalNextLspAdapter {
path: path.clone(), path: path.clone(),
arguments: arguments.clone(),
})], })],
), ),
} }

View file

@ -5,7 +5,7 @@ use lsp::{CompletionItemKind, LanguageServerBinary, SymbolKind};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use settings::Setting; use settings::Setting;
use std::{any::Any, path::PathBuf, sync::Arc}; use std::{any::Any, ops::Deref, path::PathBuf, sync::Arc};
#[derive(Clone, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Serialize, Deserialize, JsonSchema)]
pub struct ElixirSettings { pub struct ElixirSettings {
@ -17,7 +17,10 @@ pub struct ElixirSettings {
pub enum ElixirNextSetting { pub enum ElixirNextSetting {
Off, Off,
On, On,
Local { path: String }, Local {
path: String,
arguments: Vec<String>,
},
} }
#[derive(Clone, Serialize, Default, Deserialize, JsonSchema)] #[derive(Clone, Serialize, Default, Deserialize, JsonSchema)]
@ -44,6 +47,7 @@ impl Setting for ElixirSettings {
pub struct LocalNextLspAdapter { pub struct LocalNextLspAdapter {
pub path: String, pub path: String,
pub arguments: Vec<String>,
} }
#[async_trait] #[async_trait]
@ -69,9 +73,10 @@ impl LspAdapter for LocalNextLspAdapter {
_: PathBuf, _: PathBuf,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let path = shellexpand::full(&self.path)?;
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.path.clone().into(), path: PathBuf::from(path.deref()),
arguments: vec!["--stdio".into()], arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
}) })
} }
@ -80,19 +85,22 @@ impl LspAdapter for LocalNextLspAdapter {
_: PathBuf, _: PathBuf,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let path = shellexpand::full(&self.path).ok()?;
Some(LanguageServerBinary { Some(LanguageServerBinary {
path: self.path.clone().into(), path: PathBuf::from(path.deref()),
arguments: vec!["--stdio".into()], arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
}) })
} }
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> { async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
let path = shellexpand::full(&self.path).ok()?;
Some(LanguageServerBinary { Some(LanguageServerBinary {
path: self.path.clone().into(), path: PathBuf::from(path.deref()),
arguments: vec!["--stdio".into()], arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
}) })
} }
// TODO:
async fn label_for_completion( async fn label_for_completion(
&self, &self,
completion: &lsp::CompletionItem, completion: &lsp::CompletionItem,
@ -147,6 +155,7 @@ impl LspAdapter for LocalNextLspAdapter {
None None
} }
// TODO:
async fn label_for_symbol( async fn label_for_symbol(
&self, &self,
name: &str, name: &str,