Refactor lsp store (#17435)
This PR moves the local, remote, and ssh components of the LSP store into their own types. Release Notes: - N/A --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com> Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
b887f8df8c
commit
8a1e8e37bb
4 changed files with 714 additions and 443 deletions
|
@ -688,7 +688,7 @@ impl LspLogView {
|
||||||
self.project
|
self.project
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.supplementary_language_servers(cx)
|
.supplementary_language_servers(cx)
|
||||||
.filter_map(|(&server_id, name)| {
|
.filter_map(|(server_id, name)| {
|
||||||
let state = log_store.language_servers.get(&server_id)?;
|
let state = log_store.language_servers.get(&server_id)?;
|
||||||
Some(LogMenuItem {
|
Some(LogMenuItem {
|
||||||
server_id,
|
server_id,
|
||||||
|
|
|
@ -85,27 +85,82 @@ const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
|
||||||
const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
|
const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
|
||||||
pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
|
pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
|
||||||
|
|
||||||
pub struct LspStore {
|
pub struct LocalLspStore {
|
||||||
downstream_client: Option<AnyProtoClient>,
|
|
||||||
upstream_client: Option<AnyProtoClient>,
|
|
||||||
project_id: u64,
|
|
||||||
http_client: Option<Arc<dyn HttpClient>>,
|
http_client: Option<Arc<dyn HttpClient>>,
|
||||||
|
environment: Model<ProjectEnvironment>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
nonce: u128,
|
yarn: Model<YarnPathStore>,
|
||||||
buffer_store: Model<BufferStore>,
|
|
||||||
worktree_store: Model<WorktreeStore>,
|
|
||||||
buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
|
|
||||||
environment: Option<Model<ProjectEnvironment>>,
|
|
||||||
supplementary_language_servers:
|
|
||||||
HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
|
|
||||||
languages: Arc<LanguageRegistry>,
|
|
||||||
language_servers: HashMap<LanguageServerId, LanguageServerState>,
|
language_servers: HashMap<LanguageServerId, LanguageServerState>,
|
||||||
language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
|
|
||||||
language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
|
|
||||||
last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
|
last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
|
||||||
language_server_watched_paths: HashMap<LanguageServerId, HashMap<WorktreeId, GlobSet>>,
|
language_server_watched_paths: HashMap<LanguageServerId, HashMap<WorktreeId, GlobSet>>,
|
||||||
language_server_watcher_registrations:
|
language_server_watcher_registrations:
|
||||||
HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
|
HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
|
||||||
|
supplementary_language_servers:
|
||||||
|
HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
|
||||||
|
_subscription: gpui::Subscription,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalLspStore {
|
||||||
|
fn shutdown_language_servers(
|
||||||
|
&mut self,
|
||||||
|
_cx: &mut ModelContext<LspStore>,
|
||||||
|
) -> impl Future<Output = ()> {
|
||||||
|
let shutdown_futures = self
|
||||||
|
.language_servers
|
||||||
|
.drain()
|
||||||
|
.map(|(_, server_state)| async {
|
||||||
|
use LanguageServerState::*;
|
||||||
|
match server_state {
|
||||||
|
Running { server, .. } => server.shutdown()?.await,
|
||||||
|
Starting(task) => task.await?.shutdown()?.await,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
futures::future::join_all(shutdown_futures).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RemoteLspStore {
|
||||||
|
upstream_client: AnyProtoClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemoteLspStore {}
|
||||||
|
|
||||||
|
pub struct SshLspStore {
|
||||||
|
upstream_client: AnyProtoClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum LspStoreMode {
|
||||||
|
Local(LocalLspStore), // ssh host and collab host
|
||||||
|
Remote(RemoteLspStore), // collab guest
|
||||||
|
Ssh(SshLspStore), // ssh client
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LspStoreMode {
|
||||||
|
fn is_local(&self) -> bool {
|
||||||
|
matches!(self, LspStoreMode::Local(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ssh(&self) -> bool {
|
||||||
|
matches!(self, LspStoreMode::Ssh(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LspStore {
|
||||||
|
mode: LspStoreMode,
|
||||||
|
downstream_client: Option<AnyProtoClient>,
|
||||||
|
project_id: u64,
|
||||||
|
nonce: u128,
|
||||||
|
buffer_store: Model<BufferStore>,
|
||||||
|
worktree_store: Model<WorktreeStore>,
|
||||||
|
buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
|
||||||
|
languages: Arc<LanguageRegistry>,
|
||||||
|
language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
|
||||||
|
language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
|
||||||
active_entry: Option<ProjectEntryId>,
|
active_entry: Option<ProjectEntryId>,
|
||||||
_maintain_workspace_config: Task<Result<()>>,
|
_maintain_workspace_config: Task<Result<()>>,
|
||||||
_maintain_buffer_languages: Task<()>,
|
_maintain_buffer_languages: Task<()>,
|
||||||
|
@ -122,8 +177,6 @@ pub struct LspStore {
|
||||||
)>,
|
)>,
|
||||||
>,
|
>,
|
||||||
>,
|
>,
|
||||||
yarn: Model<YarnPathStore>,
|
|
||||||
_subscription: gpui::Subscription,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LspStoreEvent {
|
pub enum LspStoreEvent {
|
||||||
|
@ -209,17 +262,53 @@ impl LspStore {
|
||||||
client.add_model_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
|
client.add_model_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
pub fn as_remote(&self) -> Option<&RemoteLspStore> {
|
||||||
pub fn new(
|
match &self.mode {
|
||||||
|
LspStoreMode::Remote(remote_lsp_store) => Some(remote_lsp_store),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ssh(&self) -> Option<&SshLspStore> {
|
||||||
|
match &self.mode {
|
||||||
|
LspStoreMode::Ssh(ssh_lsp_store) => Some(ssh_lsp_store),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_local(&self) -> Option<&LocalLspStore> {
|
||||||
|
match &self.mode {
|
||||||
|
LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_local_mut(&mut self) -> Option<&mut LocalLspStore> {
|
||||||
|
match &mut self.mode {
|
||||||
|
LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn upstream_client(&self) -> Option<AnyProtoClient> {
|
||||||
|
match &self.mode {
|
||||||
|
LspStoreMode::Ssh(SshLspStore {
|
||||||
|
upstream_client, ..
|
||||||
|
})
|
||||||
|
| LspStoreMode::Remote(RemoteLspStore {
|
||||||
|
upstream_client, ..
|
||||||
|
}) => Some(upstream_client.clone()),
|
||||||
|
LspStoreMode::Local(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_local(
|
||||||
buffer_store: Model<BufferStore>,
|
buffer_store: Model<BufferStore>,
|
||||||
worktree_store: Model<WorktreeStore>,
|
worktree_store: Model<WorktreeStore>,
|
||||||
environment: Option<Model<ProjectEnvironment>>,
|
environment: Model<ProjectEnvironment>,
|
||||||
languages: Arc<LanguageRegistry>,
|
languages: Arc<LanguageRegistry>,
|
||||||
http_client: Option<Arc<dyn HttpClient>>,
|
http_client: Option<Arc<dyn HttpClient>>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
downstream_client: Option<AnyProtoClient>,
|
|
||||||
upstream_client: Option<AnyProtoClient>,
|
|
||||||
remote_id: Option<u64>,
|
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let yarn = YarnPathStore::new(fs.clone(), cx);
|
let yarn = YarnPathStore::new(fs.clone(), cx);
|
||||||
|
@ -229,32 +318,85 @@ impl LspStore {
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
downstream_client,
|
mode: LspStoreMode::Local(LocalLspStore {
|
||||||
upstream_client,
|
|
||||||
http_client,
|
|
||||||
fs,
|
|
||||||
project_id: remote_id.unwrap_or(0),
|
|
||||||
buffer_store,
|
|
||||||
worktree_store,
|
|
||||||
languages: languages.clone(),
|
|
||||||
environment,
|
|
||||||
nonce: StdRng::from_entropy().gen(),
|
|
||||||
buffer_snapshots: Default::default(),
|
|
||||||
supplementary_language_servers: Default::default(),
|
supplementary_language_servers: Default::default(),
|
||||||
language_servers: Default::default(),
|
language_servers: Default::default(),
|
||||||
language_server_ids: Default::default(),
|
|
||||||
language_server_statuses: Default::default(),
|
|
||||||
last_workspace_edits_by_language_server: Default::default(),
|
last_workspace_edits_by_language_server: Default::default(),
|
||||||
language_server_watched_paths: Default::default(),
|
language_server_watched_paths: Default::default(),
|
||||||
language_server_watcher_registrations: Default::default(),
|
language_server_watcher_registrations: Default::default(),
|
||||||
|
environment,
|
||||||
|
http_client,
|
||||||
|
fs,
|
||||||
|
yarn,
|
||||||
|
_subscription: cx.on_app_quit(|this, cx| {
|
||||||
|
this.as_local_mut().unwrap().shutdown_language_servers(cx)
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
downstream_client: None,
|
||||||
|
project_id: 0,
|
||||||
|
buffer_store,
|
||||||
|
worktree_store,
|
||||||
|
languages: languages.clone(),
|
||||||
|
language_server_ids: Default::default(),
|
||||||
|
language_server_statuses: Default::default(),
|
||||||
|
nonce: StdRng::from_entropy().gen(),
|
||||||
|
buffer_snapshots: Default::default(),
|
||||||
|
next_diagnostic_group_id: Default::default(),
|
||||||
|
diagnostic_summaries: Default::default(),
|
||||||
|
diagnostics: Default::default(),
|
||||||
|
active_entry: None,
|
||||||
|
_maintain_workspace_config: Self::maintain_workspace_config(cx),
|
||||||
|
_maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_lsp_proto_request<R: LspCommand>(
|
||||||
|
&self,
|
||||||
|
buffer: Model<Buffer>,
|
||||||
|
client: AnyProtoClient,
|
||||||
|
request: R,
|
||||||
|
cx: &mut ModelContext<'_, LspStore>,
|
||||||
|
) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
|
||||||
|
let message = request.to_proto(self.project_id, buffer.read(cx));
|
||||||
|
cx.spawn(move |this, cx| async move {
|
||||||
|
let response = client.request(message).await?;
|
||||||
|
let this = this.upgrade().context("project dropped")?;
|
||||||
|
request
|
||||||
|
.response_from_proto(response, this, buffer, cx)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_remote(
|
||||||
|
buffer_store: Model<BufferStore>,
|
||||||
|
worktree_store: Model<WorktreeStore>,
|
||||||
|
languages: Arc<LanguageRegistry>,
|
||||||
|
upstream_client: AnyProtoClient,
|
||||||
|
project_id: u64,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Self {
|
||||||
|
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
|
||||||
|
.detach();
|
||||||
|
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
|
||||||
|
.detach();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
mode: LspStoreMode::Remote(RemoteLspStore { upstream_client }),
|
||||||
|
downstream_client: None,
|
||||||
|
project_id,
|
||||||
|
buffer_store,
|
||||||
|
worktree_store,
|
||||||
|
languages: languages.clone(),
|
||||||
|
language_server_ids: Default::default(),
|
||||||
|
language_server_statuses: Default::default(),
|
||||||
|
nonce: StdRng::from_entropy().gen(),
|
||||||
|
buffer_snapshots: Default::default(),
|
||||||
next_diagnostic_group_id: Default::default(),
|
next_diagnostic_group_id: Default::default(),
|
||||||
diagnostic_summaries: Default::default(),
|
diagnostic_summaries: Default::default(),
|
||||||
diagnostics: Default::default(),
|
diagnostics: Default::default(),
|
||||||
active_entry: None,
|
active_entry: None,
|
||||||
yarn,
|
|
||||||
_maintain_workspace_config: Self::maintain_workspace_config(cx),
|
_maintain_workspace_config: Self::maintain_workspace_config(cx),
|
||||||
_maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
|
_maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
|
||||||
_subscription: cx.on_app_quit(Self::shutdown_language_servers),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,27 +636,6 @@ impl LspStore {
|
||||||
self.active_entry = active_entry;
|
self.active_entry = active_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shutdown_language_servers(
|
|
||||||
&mut self,
|
|
||||||
_cx: &mut ModelContext<Self>,
|
|
||||||
) -> impl Future<Output = ()> {
|
|
||||||
let shutdown_futures = self
|
|
||||||
.language_servers
|
|
||||||
.drain()
|
|
||||||
.map(|(_, server_state)| async {
|
|
||||||
use LanguageServerState::*;
|
|
||||||
match server_state {
|
|
||||||
Running { server, .. } => server.shutdown()?.await,
|
|
||||||
Starting(task) => task.await?.shutdown()?.await,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
async move {
|
|
||||||
futures::future::join_all(shutdown_futures).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn send_diagnostic_summaries(
|
pub(crate) fn send_diagnostic_summaries(
|
||||||
&self,
|
&self,
|
||||||
worktree: &mut Worktree,
|
worktree: &mut Worktree,
|
||||||
|
@ -547,9 +668,11 @@ impl LspStore {
|
||||||
<R::LspRequest as lsp::request::Request>::Params: Send,
|
<R::LspRequest as lsp::request::Request>::Params: Send,
|
||||||
{
|
{
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
if self.upstream_client.is_some() {
|
|
||||||
return self.send_lsp_proto_request(buffer_handle, self.project_id, request, cx);
|
if let Some(upstream_client) = self.upstream_client() {
|
||||||
|
return self.send_lsp_proto_request(buffer_handle, upstream_client, request, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let language_server = match server {
|
let language_server = match server {
|
||||||
LanguageServerToQuery::Primary => {
|
LanguageServerToQuery::Primary => {
|
||||||
match self.primary_language_server_for_buffer(buffer, cx) {
|
match self.primary_language_server_for_buffer(buffer, cx) {
|
||||||
|
@ -635,26 +758,6 @@ impl LspStore {
|
||||||
Task::ready(Ok(Default::default()))
|
Task::ready(Ok(Default::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_lsp_proto_request<R: LspCommand>(
|
|
||||||
&self,
|
|
||||||
buffer: Model<Buffer>,
|
|
||||||
project_id: u64,
|
|
||||||
request: R,
|
|
||||||
cx: &mut ModelContext<'_, Self>,
|
|
||||||
) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
|
|
||||||
let Some(upstream_client) = self.upstream_client.clone() else {
|
|
||||||
return Task::ready(Err(anyhow!("disconnected before completing request")));
|
|
||||||
};
|
|
||||||
let message = request.to_proto(project_id, buffer.read(cx));
|
|
||||||
cx.spawn(move |this, cx| async move {
|
|
||||||
let response = upstream_client.request(message).await?;
|
|
||||||
let this = this.upgrade().context("project dropped")?;
|
|
||||||
request
|
|
||||||
.response_from_proto(response, this, buffer, cx)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn execute_code_actions_on_servers(
|
pub async fn execute_code_actions_on_servers(
|
||||||
this: &WeakModel<LspStore>,
|
this: &WeakModel<LspStore>,
|
||||||
adapters_and_servers: &Vec<(Arc<CachedLspAdapter>, Arc<LanguageServer>)>,
|
adapters_and_servers: &Vec<(Arc<CachedLspAdapter>, Arc<LanguageServer>)>,
|
||||||
|
@ -702,8 +805,10 @@ impl LspStore {
|
||||||
|
|
||||||
if let Some(command) = action.lsp_action.command {
|
if let Some(command) = action.lsp_action.command {
|
||||||
this.update(cx, |this, _| {
|
this.update(cx, |this, _| {
|
||||||
this.last_workspace_edits_by_language_server
|
if let LspStoreMode::Local(mode) = &mut this.mode {
|
||||||
|
mode.last_workspace_edits_by_language_server
|
||||||
.remove(&language_server.server_id());
|
.remove(&language_server.server_id());
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
language_server
|
language_server
|
||||||
|
@ -715,12 +820,14 @@ impl LspStore {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
this.update(cx, |this, _| {
|
this.update(cx, |this, _| {
|
||||||
|
if let LspStoreMode::Local(mode) = &mut this.mode {
|
||||||
project_transaction.0.extend(
|
project_transaction.0.extend(
|
||||||
this.last_workspace_edits_by_language_server
|
mode.last_workspace_edits_by_language_server
|
||||||
.remove(&language_server.server_id())
|
.remove(&language_server.server_id())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.0,
|
.0,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,7 +860,7 @@ impl LspStore {
|
||||||
push_to_history: bool,
|
push_to_history: bool,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<ProjectTransaction>> {
|
) -> Task<Result<ProjectTransaction>> {
|
||||||
if let Some(upstream_client) = self.upstream_client.clone() {
|
if let Some(upstream_client) = self.upstream_client() {
|
||||||
let request = proto::ApplyCodeAction {
|
let request = proto::ApplyCodeAction {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
||||||
|
@ -802,7 +909,9 @@ impl LspStore {
|
||||||
|
|
||||||
if let Some(command) = action.lsp_action.command {
|
if let Some(command) = action.lsp_action.command {
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, _| {
|
||||||
this.last_workspace_edits_by_language_server
|
this.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.last_workspace_edits_by_language_server
|
||||||
.remove(&lang_server.server_id());
|
.remove(&lang_server.server_id());
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -820,7 +929,9 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.update(&mut cx, |this, _| {
|
return this.update(&mut cx, |this, _| {
|
||||||
this.last_workspace_edits_by_language_server
|
this.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.last_workspace_edits_by_language_server
|
||||||
.remove(&lang_server.server_id())
|
.remove(&lang_server.server_id())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
});
|
});
|
||||||
|
@ -838,7 +949,7 @@ impl LspStore {
|
||||||
server_id: LanguageServerId,
|
server_id: LanguageServerId,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<anyhow::Result<InlayHint>> {
|
) -> Task<anyhow::Result<InlayHint>> {
|
||||||
if let Some(upstream_client) = self.upstream_client.clone() {
|
if let Some(upstream_client) = self.upstream_client() {
|
||||||
let request = proto::ResolveInlayHint {
|
let request = proto::ResolveInlayHint {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
||||||
|
@ -916,7 +1027,7 @@ impl LspStore {
|
||||||
.map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
|
.map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
|
||||||
.next()
|
.next()
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.upstream_client
|
self.upstream_client()
|
||||||
.is_some()
|
.is_some()
|
||||||
.then_some(LanguageServerToQuery::Primary)
|
.then_some(LanguageServerToQuery::Primary)
|
||||||
})
|
})
|
||||||
|
@ -949,7 +1060,7 @@ impl LspStore {
|
||||||
trigger: String,
|
trigger: String,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<Option<Transaction>>> {
|
) -> Task<Result<Option<Transaction>>> {
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request = proto::OnTypeFormatting {
|
let request = proto::OnTypeFormatting {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
buffer_id: buffer.read(cx).remote_id().into(),
|
buffer_id: buffer.read(cx).remote_id().into(),
|
||||||
|
@ -1099,7 +1210,7 @@ impl LspStore {
|
||||||
range: Range<Anchor>,
|
range: Range<Anchor>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Vec<CodeAction>> {
|
) -> Task<Vec<CodeAction>> {
|
||||||
if let Some(upstream_client) = self.upstream_client.as_ref() {
|
if let Some(upstream_client) = self.upstream_client() {
|
||||||
let request_task = upstream_client.request(proto::MultiLspQuery {
|
let request_task = upstream_client.request(proto::MultiLspQuery {
|
||||||
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
||||||
version: serialize_version(&buffer_handle.read(cx).version()),
|
version: serialize_version(&buffer_handle.read(cx).version()),
|
||||||
|
@ -1179,10 +1290,10 @@ impl LspStore {
|
||||||
) -> Task<Result<Vec<Completion>>> {
|
) -> Task<Result<Vec<Completion>>> {
|
||||||
let language_registry = self.languages.clone();
|
let language_registry = self.languages.clone();
|
||||||
|
|
||||||
if let Some(_) = self.upstream_client.clone() {
|
if let Some(upstream_client) = self.upstream_client() {
|
||||||
let task = self.send_lsp_proto_request(
|
let task = self.send_lsp_proto_request(
|
||||||
buffer.clone(),
|
buffer.clone(),
|
||||||
self.project_id,
|
upstream_client,
|
||||||
GetCompletions { position, context },
|
GetCompletions { position, context },
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
@ -1273,7 +1384,7 @@ impl LspStore {
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Arc<RwLock<Box<[Completion]>>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
let client = self.upstream_client.clone();
|
let client = self.upstream_client();
|
||||||
let language_registry = self.languages.clone();
|
let language_registry = self.languages.clone();
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
|
|
||||||
|
@ -1482,7 +1593,7 @@ impl LspStore {
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
let buffer_id = buffer.remote_id();
|
let buffer_id = buffer.remote_id();
|
||||||
|
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
cx.spawn(move |_, mut cx| async move {
|
cx.spawn(move |_, mut cx| async move {
|
||||||
let response = client
|
let response = client
|
||||||
|
@ -1598,7 +1709,7 @@ impl LspStore {
|
||||||
let buffer_id = buffer.remote_id().into();
|
let buffer_id = buffer.remote_id().into();
|
||||||
let lsp_request = InlayHints { range };
|
let lsp_request = InlayHints { range };
|
||||||
|
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request = proto::InlayHints {
|
let request = proto::InlayHints {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
|
@ -1648,7 +1759,7 @@ impl LspStore {
|
||||||
) -> Task<Vec<SignatureHelp>> {
|
) -> Task<Vec<SignatureHelp>> {
|
||||||
let position = position.to_point_utf16(buffer.read(cx));
|
let position = position.to_point_utf16(buffer.read(cx));
|
||||||
|
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request_task = client.request(proto::MultiLspQuery {
|
let request_task = client.request(proto::MultiLspQuery {
|
||||||
buffer_id: buffer.read(cx).remote_id().into(),
|
buffer_id: buffer.read(cx).remote_id().into(),
|
||||||
version: serialize_version(&buffer.read(cx).version()),
|
version: serialize_version(&buffer.read(cx).version()),
|
||||||
|
@ -1720,7 +1831,7 @@ impl LspStore {
|
||||||
position: PointUtf16,
|
position: PointUtf16,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Vec<Hover>> {
|
) -> Task<Vec<Hover>> {
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request_task = client.request(proto::MultiLspQuery {
|
let request_task = client.request(proto::MultiLspQuery {
|
||||||
buffer_id: buffer.read(cx).remote_id().into(),
|
buffer_id: buffer.read(cx).remote_id().into(),
|
||||||
version: serialize_version(&buffer.read(cx).version()),
|
version: serialize_version(&buffer.read(cx).version()),
|
||||||
|
@ -1794,7 +1905,7 @@ impl LspStore {
|
||||||
pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
|
pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
|
||||||
let language_registry = self.languages.clone();
|
let language_registry = self.languages.clone();
|
||||||
|
|
||||||
if let Some(upstream_client) = self.upstream_client.as_ref() {
|
if let Some(upstream_client) = self.upstream_client().as_ref() {
|
||||||
let request = upstream_client.request(proto::GetProjectSymbols {
|
let request = upstream_client.request(proto::GetProjectSymbols {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
query: query.to_string(),
|
query: query.to_string(),
|
||||||
|
@ -1841,7 +1952,8 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
let worktree_abs_path = worktree.abs_path().clone();
|
let worktree_abs_path = worktree.abs_path().clone();
|
||||||
|
|
||||||
let (lsp_adapter, language, server) = match self.language_servers.get(server_id) {
|
let (lsp_adapter, language, server) =
|
||||||
|
match self.as_local().unwrap().language_servers.get(server_id) {
|
||||||
Some(LanguageServerState::Running {
|
Some(LanguageServerState::Running {
|
||||||
adapter,
|
adapter,
|
||||||
language,
|
language,
|
||||||
|
@ -2152,7 +2264,7 @@ impl LspStore {
|
||||||
.worktree_store
|
.worktree_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.worktree_for_id(*worktree_id, cx)?;
|
.worktree_for_id(*worktree_id, cx)?;
|
||||||
let state = this.language_servers.get(server_id)?;
|
let state = this.as_local()?.language_servers.get(server_id)?;
|
||||||
let delegate = ProjectLspAdapterDelegate::new(this, &worktree, cx);
|
let delegate = ProjectLspAdapterDelegate::new(this, &worktree, cx);
|
||||||
match state {
|
match state {
|
||||||
LanguageServerState::Starting(_) => None,
|
LanguageServerState::Starting(_) => None,
|
||||||
|
@ -2218,7 +2330,7 @@ impl LspStore {
|
||||||
language,
|
language,
|
||||||
server,
|
server,
|
||||||
..
|
..
|
||||||
}) = self.language_servers.get(id)
|
}) = self.as_local()?.language_servers.get(id)
|
||||||
{
|
{
|
||||||
return Some((adapter, language, server));
|
return Some((adapter, language, server));
|
||||||
}
|
}
|
||||||
|
@ -2245,11 +2357,17 @@ impl LspStore {
|
||||||
self.language_server_ids
|
self.language_server_ids
|
||||||
.remove(&(id_to_remove, server_name));
|
.remove(&(id_to_remove, server_name));
|
||||||
self.language_server_statuses.remove(&server_id_to_remove);
|
self.language_server_statuses.remove(&server_id_to_remove);
|
||||||
self.language_server_watched_paths
|
if let Some(local_lsp_store) = self.as_local_mut() {
|
||||||
|
local_lsp_store
|
||||||
|
.language_server_watched_paths
|
||||||
.remove(&server_id_to_remove);
|
.remove(&server_id_to_remove);
|
||||||
self.last_workspace_edits_by_language_server
|
local_lsp_store
|
||||||
|
.last_workspace_edits_by_language_server
|
||||||
.remove(&server_id_to_remove);
|
.remove(&server_id_to_remove);
|
||||||
self.language_servers.remove(&server_id_to_remove);
|
local_lsp_store
|
||||||
|
.language_servers
|
||||||
|
.remove(&server_id_to_remove);
|
||||||
|
}
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2345,7 +2463,7 @@ impl LspStore {
|
||||||
let server = self
|
let server = self
|
||||||
.language_server_ids
|
.language_server_ids
|
||||||
.get(&(worktree_id, adapter.name.clone()))
|
.get(&(worktree_id, adapter.name.clone()))
|
||||||
.and_then(|id| self.language_servers.get(id))
|
.and_then(|id| self.as_local()?.language_servers.get(id))
|
||||||
.and_then(|server_state| {
|
.and_then(|server_state| {
|
||||||
if let LanguageServerState::Running { server, .. } = server_state {
|
if let LanguageServerState::Running { server, .. } = server_state {
|
||||||
Some(server.clone())
|
Some(server.clone())
|
||||||
|
@ -2541,7 +2659,7 @@ impl LspStore {
|
||||||
symbol: &Symbol,
|
symbol: &Symbol,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<Model<Buffer>>> {
|
) -> Task<Result<Model<Buffer>>> {
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request = client.request(proto::OpenBufferForSymbol {
|
let request = client.request(proto::OpenBufferForSymbol {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
symbol: Some(Self::serialize_symbol(symbol)),
|
symbol: Some(Self::serialize_symbol(symbol)),
|
||||||
|
@ -2609,7 +2727,7 @@ impl LspStore {
|
||||||
let p = abs_path.clone();
|
let p = abs_path.clone();
|
||||||
let yarn_worktree = this
|
let yarn_worktree = this
|
||||||
.update(&mut cx, move |this, cx| {
|
.update(&mut cx, move |this, cx| {
|
||||||
this.yarn.update(cx, |_, cx| {
|
this.as_local().unwrap().yarn.update(cx, |_, cx| {
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
let t = this
|
let t = this
|
||||||
.update(&mut cx, |this, cx| {
|
.update(&mut cx, |this, cx| {
|
||||||
|
@ -2759,7 +2877,7 @@ impl LspStore {
|
||||||
<R::LspRequest as lsp::request::Request>::Result: Send,
|
<R::LspRequest as lsp::request::Request>::Result: Send,
|
||||||
<R::LspRequest as lsp::request::Request>::Params: Send,
|
<R::LspRequest as lsp::request::Request>::Params: Send,
|
||||||
{
|
{
|
||||||
debug_assert!(self.upstream_client.is_none());
|
debug_assert!(self.upstream_client().is_none());
|
||||||
|
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let scope = position.and_then(|position| snapshot.language_scope_at(position));
|
let scope = position.and_then(|position| snapshot.language_scope_at(position));
|
||||||
|
@ -3188,7 +3306,9 @@ impl LspStore {
|
||||||
simulate_disk_based_diagnostics_completion,
|
simulate_disk_based_diagnostics_completion,
|
||||||
adapter,
|
adapter,
|
||||||
..
|
..
|
||||||
}) = self.language_servers.get_mut(&language_server_id)
|
}) = self
|
||||||
|
.as_local_mut()
|
||||||
|
.and_then(|local_store| local_store.language_servers.get_mut(&language_server_id))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -3209,8 +3329,9 @@ impl LspStore {
|
||||||
if let Some(LanguageServerState::Running {
|
if let Some(LanguageServerState::Running {
|
||||||
simulate_disk_based_diagnostics_completion,
|
simulate_disk_based_diagnostics_completion,
|
||||||
..
|
..
|
||||||
}) = this.language_servers.get_mut(&language_server_id)
|
}) = this.as_local_mut().and_then(|local_store| {
|
||||||
{
|
local_store.language_servers.get_mut(&language_server_id)
|
||||||
|
}) {
|
||||||
*simulate_disk_based_diagnostics_completion = None;
|
*simulate_disk_based_diagnostics_completion = None;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -3236,21 +3357,24 @@ impl LspStore {
|
||||||
language_server_id: LanguageServerId,
|
language_server_id: LanguageServerId,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
let Some(watchers) = self
|
let worktrees = self.worktree_store.read(cx).worktrees().collect::<Vec<_>>();
|
||||||
|
let local_lsp_store = self.as_local_mut().unwrap();
|
||||||
|
|
||||||
|
let Some(watchers) = local_lsp_store
|
||||||
.language_server_watcher_registrations
|
.language_server_watcher_registrations
|
||||||
.get(&language_server_id)
|
.get(&language_server_id)
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let watched_paths = self
|
let watched_paths = local_lsp_store
|
||||||
.language_server_watched_paths
|
.language_server_watched_paths
|
||||||
.entry(language_server_id)
|
.entry(language_server_id)
|
||||||
.or_default();
|
.or_default();
|
||||||
|
|
||||||
let mut builders = HashMap::default();
|
let mut builders = HashMap::default();
|
||||||
for watcher in watchers.values().flatten() {
|
for watcher in watchers.values().flatten() {
|
||||||
for worktree in self.worktree_store.read(cx).worktrees().collect::<Vec<_>>() {
|
for worktree in worktrees.iter() {
|
||||||
let glob_is_inside_worktree = worktree.update(cx, |tree, _| {
|
let glob_is_inside_worktree = worktree.update(cx, |tree, _| {
|
||||||
if let Some(abs_path) = tree.abs_path().to_str() {
|
if let Some(abs_path) = tree.abs_path().to_str() {
|
||||||
let relative_glob_pattern = match &watcher.glob_pattern {
|
let relative_glob_pattern = match &watcher.glob_pattern {
|
||||||
|
@ -3304,13 +3428,21 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
|
pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
|
||||||
if let Some(LanguageServerState::Running { server, .. }) = self.language_servers.get(&id) {
|
if let Some(local_lsp_store) = self.as_local() {
|
||||||
|
if let Some(LanguageServerState::Running { server, .. }) =
|
||||||
|
local_lsp_store.language_servers.get(&id)
|
||||||
|
{
|
||||||
Some(server.clone())
|
Some(server.clone())
|
||||||
} else if let Some((_, server)) = self.supplementary_language_servers.get(&id) {
|
} else if let Some((_, server)) =
|
||||||
|
local_lsp_store.supplementary_language_servers.get(&id)
|
||||||
|
{
|
||||||
Some(Arc::clone(server))
|
Some(Arc::clone(server))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_lsp_workspace_edit(
|
async fn on_lsp_workspace_edit(
|
||||||
|
@ -3338,7 +3470,9 @@ impl LspStore {
|
||||||
.log_err();
|
.log_err();
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, _| {
|
||||||
if let Some(transaction) = transaction {
|
if let Some(transaction) = transaction {
|
||||||
this.last_workspace_edits_by_language_server
|
this.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.last_workspace_edits_by_language_server
|
||||||
.insert(server_id, transaction);
|
.insert(server_id, transaction);
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
@ -3523,7 +3657,8 @@ impl LspStore {
|
||||||
params: DidChangeWatchedFilesRegistrationOptions,
|
params: DidChangeWatchedFilesRegistrationOptions,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
let registrations = self
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
let registrations = local
|
||||||
.language_server_watcher_registrations
|
.language_server_watcher_registrations
|
||||||
.entry(language_server_id)
|
.entry(language_server_id)
|
||||||
.or_default();
|
.or_default();
|
||||||
|
@ -3532,6 +3667,7 @@ impl LspStore {
|
||||||
|
|
||||||
self.rebuild_watched_paths(language_server_id, cx);
|
self.rebuild_watched_paths(language_server_id, cx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_lsp_unregister_did_change_watched_files(
|
fn on_lsp_unregister_did_change_watched_files(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -3539,7 +3675,8 @@ impl LspStore {
|
||||||
registration_id: &str,
|
registration_id: &str,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
let registrations = self
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
let registrations = local
|
||||||
.language_server_watcher_registrations
|
.language_server_watcher_registrations
|
||||||
.entry(language_server_id)
|
.entry(language_server_id)
|
||||||
.or_default();
|
.or_default();
|
||||||
|
@ -3560,6 +3697,7 @@ impl LspStore {
|
||||||
|
|
||||||
self.rebuild_watched_paths(language_server_id, cx);
|
self.rebuild_watched_paths(language_server_id, cx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) fn edits_from_lsp(
|
pub(crate) fn edits_from_lsp(
|
||||||
|
@ -4075,6 +4213,7 @@ impl LspStore {
|
||||||
language: Arc<Language>,
|
language: Arc<Language>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
|
if self.mode.is_local() {
|
||||||
if adapter.reinstall_attempt_count.load(SeqCst) > MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
|
if adapter.reinstall_attempt_count.load(SeqCst) > MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4090,9 +4229,12 @@ impl LspStore {
|
||||||
let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
|
let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
|
||||||
let lsp_adapter_delegate = ProjectLspAdapterDelegate::new(self, worktree_handle, cx);
|
let lsp_adapter_delegate = ProjectLspAdapterDelegate::new(self, worktree_handle, cx);
|
||||||
let cli_environment = self
|
let cli_environment = self
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
.environment
|
.environment
|
||||||
.as_ref()
|
.read(cx)
|
||||||
.and_then(|environment| environment.read(cx).get_cli_environment());
|
.get_cli_environment();
|
||||||
|
|
||||||
let pending_server = match self.languages.create_pending_language_server(
|
let pending_server = match self.languages.create_pending_language_server(
|
||||||
stderr_capture.clone(),
|
stderr_capture.clone(),
|
||||||
language.clone(),
|
language.clone(),
|
||||||
|
@ -4151,10 +4293,13 @@ impl LspStore {
|
||||||
let this = this.upgrade()?;
|
let this = this.upgrade()?;
|
||||||
let container_dir = container_dir?;
|
let container_dir = container_dir?;
|
||||||
|
|
||||||
let attempt_count = adapter.reinstall_attempt_count.fetch_add(1, SeqCst);
|
let attempt_count =
|
||||||
|
adapter.reinstall_attempt_count.fetch_add(1, SeqCst);
|
||||||
if attempt_count >= MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
|
if attempt_count >= MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
|
||||||
let max = MAX_SERVER_REINSTALL_ATTEMPT_COUNT;
|
let max = MAX_SERVER_REINSTALL_ATTEMPT_COUNT;
|
||||||
log::error!("Hit {max} reinstallation attempts for {server_name:?}");
|
log::error!(
|
||||||
|
"Hit {max} reinstallation attempts for {server_name:?}"
|
||||||
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4187,8 +4332,14 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
self.language_servers.insert(server_id, state);
|
self.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.language_servers
|
||||||
|
.insert(server_id, state);
|
||||||
self.language_server_ids.insert(key, server_id);
|
self.language_server_ids.insert(key, server_id);
|
||||||
|
} else if self.mode.is_ssh() {
|
||||||
|
// TODO ssh
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -4242,7 +4393,8 @@ impl LspStore {
|
||||||
) -> Option<Task<()>> {
|
) -> Option<Task<()>> {
|
||||||
log::info!("beginning to reinstall server");
|
log::info!("beginning to reinstall server");
|
||||||
|
|
||||||
let existing_server = match self.language_servers.remove(&server_id) {
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
let existing_server = match local.language_servers.remove(&server_id) {
|
||||||
Some(LanguageServerState::Running { server, .. }) => Some(server),
|
Some(LanguageServerState::Running { server, .. }) => Some(server),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -4275,11 +4427,22 @@ impl LspStore {
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
for worktree in this.worktree_store.read(cx).worktrees().collect::<Vec<_>>() {
|
for worktree in this.worktree_store.read(cx).worktrees().collect::<Vec<_>>() {
|
||||||
this.start_language_server(&worktree, adapter.clone(), language.clone(), cx);
|
this.start_language_server(
|
||||||
|
&worktree,
|
||||||
|
adapter.clone(),
|
||||||
|
language.clone(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}))
|
}))
|
||||||
|
} else if let Some(_ssh_store) = self.as_ssh() {
|
||||||
|
// TODO
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown_language_server(
|
async fn shutdown_language_server(
|
||||||
|
@ -4327,6 +4490,7 @@ impl LspStore {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Vec<WorktreeId>> {
|
) -> Task<Vec<WorktreeId>> {
|
||||||
let key = (worktree_id, adapter_name);
|
let key = (worktree_id, adapter_name);
|
||||||
|
if self.mode.is_local() {
|
||||||
if let Some(server_id) = self.language_server_ids.remove(&key) {
|
if let Some(server_id) = self.language_server_ids.remove(&key) {
|
||||||
let name = key.1 .0;
|
let name = key.1 .0;
|
||||||
log::info!("stopping language server {name}");
|
log::info!("stopping language server {name}");
|
||||||
|
@ -4387,11 +4551,18 @@ impl LspStore {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.language_server_watched_paths.remove(&server_id);
|
self.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.language_server_watched_paths
|
||||||
|
.remove(&server_id);
|
||||||
self.language_server_statuses.remove(&server_id);
|
self.language_server_statuses.remove(&server_id);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
let server_state = self.language_servers.remove(&server_id);
|
let server_state = self
|
||||||
|
.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.language_servers
|
||||||
|
.remove(&server_id);
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
|
||||||
cx.spawn(move |_, cx| async move {
|
cx.spawn(move |_, cx| async move {
|
||||||
Self::shutdown_language_server(server_state, name, cx).await;
|
Self::shutdown_language_server(server_state, name, cx).await;
|
||||||
|
@ -4400,6 +4571,12 @@ impl LspStore {
|
||||||
} else {
|
} else {
|
||||||
Task::ready(Vec::new())
|
Task::ready(Vec::new())
|
||||||
}
|
}
|
||||||
|
} else if self.mode.is_ssh() {
|
||||||
|
// TODO ssh
|
||||||
|
Task::ready(Vec::new())
|
||||||
|
} else {
|
||||||
|
Task::ready(Vec::new())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn restart_language_servers_for_buffers(
|
pub fn restart_language_servers_for_buffers(
|
||||||
|
@ -4407,7 +4584,7 @@ impl LspStore {
|
||||||
buffers: impl IntoIterator<Item = Model<Buffer>>,
|
buffers: impl IntoIterator<Item = Model<Buffer>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(client) = self.upstream_client.clone() {
|
if let Some(client) = self.upstream_client() {
|
||||||
let request = client.request(proto::RestartLanguageServers {
|
let request = client.request(proto::RestartLanguageServers {
|
||||||
project_id: self.project_id,
|
project_id: self.project_id,
|
||||||
buffer_ids: buffers
|
buffer_ids: buffers
|
||||||
|
@ -5192,7 +5369,8 @@ impl LspStore {
|
||||||
|
|
||||||
// Update language_servers collection with Running variant of LanguageServerState
|
// Update language_servers collection with Running variant of LanguageServerState
|
||||||
// indicating that the server is up and running and ready
|
// indicating that the server is up and running and ready
|
||||||
self.language_servers.insert(
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
local.language_servers.insert(
|
||||||
server_id,
|
server_id,
|
||||||
LanguageServerState::Running {
|
LanguageServerState::Running {
|
||||||
adapter: adapter.clone(),
|
adapter: adapter.clone(),
|
||||||
|
@ -5201,6 +5379,7 @@ impl LspStore {
|
||||||
simulate_disk_based_diagnostics_completion: None,
|
simulate_disk_based_diagnostics_completion: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.language_server_statuses.insert(
|
self.language_server_statuses.insert(
|
||||||
server_id,
|
server_id,
|
||||||
|
@ -5352,12 +5531,14 @@ impl LspStore {
|
||||||
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
self.language_server_ids_for_buffer(buffer, cx)
|
self.language_server_ids_for_buffer(buffer, cx)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|server_id| match self.language_servers.get(&server_id)? {
|
.filter_map(
|
||||||
|
|server_id| match self.as_local()?.language_servers.get(&server_id)? {
|
||||||
LanguageServerState::Running {
|
LanguageServerState::Running {
|
||||||
adapter, server, ..
|
adapter, server, ..
|
||||||
} => Some((adapter, server)),
|
} => Some((adapter, server)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cancel_language_server_work_for_buffers(
|
pub(crate) fn cancel_language_server_work_for_buffers(
|
||||||
|
@ -5395,37 +5576,46 @@ impl LspStore {
|
||||||
server: Arc<LanguageServer>,
|
server: Arc<LanguageServer>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.supplementary_language_servers
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
local
|
||||||
|
.supplementary_language_servers
|
||||||
.insert(id, (name, server));
|
.insert(id, (name, server));
|
||||||
cx.emit(LspStoreEvent::LanguageServerAdded(id));
|
cx.emit(LspStoreEvent::LanguageServerAdded(id));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unregister_supplementary_language_server(
|
pub fn unregister_supplementary_language_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: LanguageServerId,
|
id: LanguageServerId,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.supplementary_language_servers.remove(&id);
|
if let Some(local) = self.as_local_mut() {
|
||||||
|
local.supplementary_language_servers.remove(&id);
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(id));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(id));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn supplementary_language_servers(
|
pub fn supplementary_language_servers(
|
||||||
&self,
|
&self,
|
||||||
) -> impl '_ + Iterator<Item = (&LanguageServerId, &LanguageServerName)> {
|
) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
|
||||||
self.supplementary_language_servers
|
self.as_local().into_iter().flat_map(|local| {
|
||||||
|
local
|
||||||
|
.supplementary_language_servers
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, (name, _))| (id, name))
|
.map(|(id, (name, _))| (*id, name.clone()))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_server_adapter_for_id(
|
pub fn language_server_adapter_for_id(
|
||||||
&self,
|
&self,
|
||||||
id: LanguageServerId,
|
id: LanguageServerId,
|
||||||
) -> Option<Arc<CachedLspAdapter>> {
|
) -> Option<Arc<CachedLspAdapter>> {
|
||||||
if let Some(LanguageServerState::Running { adapter, .. }) = self.language_servers.get(&id) {
|
self.as_local()
|
||||||
Some(adapter.clone())
|
.and_then(|local| local.language_servers.get(&id))
|
||||||
} else {
|
.and_then(|language_server_state| match language_server_state {
|
||||||
None
|
LanguageServerState::Running { adapter, .. } => Some(adapter.clone()),
|
||||||
}
|
_ => None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_local_worktree_language_servers(
|
pub fn update_local_worktree_language_servers(
|
||||||
|
@ -5451,10 +5641,11 @@ impl LspStore {
|
||||||
|
|
||||||
let abs_path = worktree_handle.read(cx).abs_path();
|
let abs_path = worktree_handle.read(cx).abs_path();
|
||||||
for server_id in &language_server_ids {
|
for server_id in &language_server_ids {
|
||||||
|
if let Some(local) = self.as_local() {
|
||||||
if let Some(LanguageServerState::Running { server, .. }) =
|
if let Some(LanguageServerState::Running { server, .. }) =
|
||||||
self.language_servers.get(server_id)
|
local.language_servers.get(server_id)
|
||||||
{
|
{
|
||||||
if let Some(watched_paths) = self
|
if let Some(watched_paths) = local
|
||||||
.language_server_watched_paths
|
.language_server_watched_paths
|
||||||
.get(&server_id)
|
.get(&server_id)
|
||||||
.and_then(|paths| paths.get(&worktree_id))
|
.and_then(|paths| paths.get(&worktree_id))
|
||||||
|
@ -5489,6 +5680,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn cancel_language_server_work(
|
pub(crate) fn cancel_language_server_work(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -5497,7 +5689,9 @@ impl LspStore {
|
||||||
_cx: &mut ModelContext<Self>,
|
_cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
let status = self.language_server_statuses.get(&server_id);
|
let status = self.language_server_statuses.get(&server_id);
|
||||||
let server = self.language_servers.get(&server_id);
|
let server = self
|
||||||
|
.as_local()
|
||||||
|
.and_then(|local| local.language_servers.get(&server_id));
|
||||||
if let Some((server, status)) = server.zip(status) {
|
if let Some((server, status)) = server.zip(status) {
|
||||||
if let LanguageServerState::Running { server, .. } = server {
|
if let LanguageServerState::Running { server, .. } = server {
|
||||||
for (token, progress) in &status.pending_work {
|
for (token, progress) in &status.pending_work {
|
||||||
|
@ -5600,7 +5794,8 @@ impl LspStore {
|
||||||
language_server: Arc<LanguageServer>,
|
language_server: Arc<LanguageServer>,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Result<ProjectTransaction> {
|
) -> Result<ProjectTransaction> {
|
||||||
let fs = this.update(cx, |this, _| this.fs.clone())?;
|
let fs = this.read_with(cx, |this, _| this.as_local().unwrap().fs.clone())?;
|
||||||
|
|
||||||
let mut operations = Vec::new();
|
let mut operations = Vec::new();
|
||||||
if let Some(document_changes) = edit.document_changes {
|
if let Some(document_changes) = edit.document_changes {
|
||||||
match document_changes {
|
match document_changes {
|
||||||
|
@ -6119,7 +6314,10 @@ impl ProjectLspAdapterDelegate {
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let worktree_id = worktree.read(cx).id();
|
let worktree_id = worktree.read(cx).id();
|
||||||
let worktree_abs_path = worktree.read(cx).abs_path();
|
let worktree_abs_path = worktree.read(cx).abs_path();
|
||||||
let load_shell_env_task = if let Some(environment) = &lsp_store.environment {
|
|
||||||
|
let load_shell_env_task = if let Some(environment) =
|
||||||
|
&lsp_store.as_local().map(|local| local.environment.clone())
|
||||||
|
{
|
||||||
environment.update(cx, |env, cx| {
|
environment.update(cx, |env, cx| {
|
||||||
env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
|
env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
|
||||||
})
|
})
|
||||||
|
@ -6127,14 +6325,23 @@ impl ProjectLspAdapterDelegate {
|
||||||
Task::ready(None).shared()
|
Task::ready(None).shared()
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(http_client) = lsp_store.http_client.clone() else {
|
let Some(http_client) = lsp_store
|
||||||
|
.as_local()
|
||||||
|
.and_then(|local| local.http_client.clone())
|
||||||
|
else {
|
||||||
panic!("ProjectLspAdapterDelegate cannot be constructedd on an ssh-remote yet")
|
panic!("ProjectLspAdapterDelegate cannot be constructedd on an ssh-remote yet")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fs = lsp_store
|
||||||
|
.as_local()
|
||||||
|
.expect("ProjectLspAdapterDelegate cannot be constructedd on an ssh-remote yet")
|
||||||
|
.fs
|
||||||
|
.clone();
|
||||||
|
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
lsp_store: cx.weak_model(),
|
lsp_store: cx.weak_model(),
|
||||||
worktree: worktree.read(cx).snapshot(),
|
worktree: worktree.read(cx).snapshot(),
|
||||||
fs: lsp_store.fs.clone(),
|
fs,
|
||||||
http_client,
|
http_client,
|
||||||
language_registry: lsp_store.languages.clone(),
|
language_registry: lsp_store.languages.clone(),
|
||||||
load_shell_env_task,
|
load_shell_env_task,
|
||||||
|
|
|
@ -643,16 +643,13 @@ impl Project {
|
||||||
|
|
||||||
let environment = ProjectEnvironment::new(&worktree_store, env, cx);
|
let environment = ProjectEnvironment::new(&worktree_store, env, cx);
|
||||||
let lsp_store = cx.new_model(|cx| {
|
let lsp_store = cx.new_model(|cx| {
|
||||||
LspStore::new(
|
LspStore::new_local(
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
worktree_store.clone(),
|
worktree_store.clone(),
|
||||||
Some(environment.clone()),
|
environment.clone(),
|
||||||
languages.clone(),
|
languages.clone(),
|
||||||
Some(client.http_client()),
|
Some(client.http_client()),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -712,17 +709,90 @@ impl Project {
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
cx: &mut AppContext,
|
cx: &mut AppContext,
|
||||||
) -> Model<Self> {
|
) -> Model<Self> {
|
||||||
let this = Self::local(client, node, user_store, languages, fs, None, cx);
|
cx.new_model(|cx: &mut ModelContext<Self>| {
|
||||||
this.update(cx, |this, cx| {
|
let (tx, rx) = mpsc::unbounded();
|
||||||
let client: AnyProtoClient = ssh.clone().into();
|
cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
|
||||||
|
.detach();
|
||||||
|
let tasks = Inventory::new(cx);
|
||||||
|
let global_snippets_dir = paths::config_dir().join("snippets");
|
||||||
|
let snippets =
|
||||||
|
SnippetProvider::new(fs.clone(), BTreeSet::from_iter([global_snippets_dir]), cx);
|
||||||
|
|
||||||
this.worktree_store.update(cx, |store, _cx| {
|
let worktree_store = cx.new_model(|_| {
|
||||||
store.set_upstream_client(client.clone());
|
let mut worktree_store = WorktreeStore::new(false, fs.clone());
|
||||||
|
worktree_store.set_upstream_client(ssh.clone().into());
|
||||||
|
worktree_store
|
||||||
});
|
});
|
||||||
this.settings_observer = cx.new_model(|cx| {
|
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
|
||||||
SettingsObserver::new_ssh(ssh.clone().into(), this.worktree_store.clone(), cx)
|
.detach();
|
||||||
|
|
||||||
|
let buffer_store =
|
||||||
|
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), None, cx));
|
||||||
|
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
|
||||||
|
.detach();
|
||||||
|
|
||||||
|
let settings_observer = cx.new_model(|cx| {
|
||||||
|
SettingsObserver::new_ssh(ssh.clone().into(), worktree_store.clone(), cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let environment = ProjectEnvironment::new(&worktree_store, None, cx);
|
||||||
|
let lsp_store = cx.new_model(|cx| {
|
||||||
|
LspStore::new_remote(
|
||||||
|
buffer_store.clone(),
|
||||||
|
worktree_store.clone(),
|
||||||
|
languages.clone(),
|
||||||
|
ssh.clone().into(),
|
||||||
|
0,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach();
|
||||||
|
|
||||||
|
let this = Self {
|
||||||
|
buffer_ordered_messages_tx: tx,
|
||||||
|
collaborators: Default::default(),
|
||||||
|
worktree_store,
|
||||||
|
buffer_store,
|
||||||
|
lsp_store,
|
||||||
|
current_lsp_settings: ProjectSettings::get_global(cx).lsp.clone(),
|
||||||
|
join_project_response_message_id: 0,
|
||||||
|
client_state: ProjectClientState::Local,
|
||||||
|
client_subscriptions: Vec::new(),
|
||||||
|
_subscriptions: vec![
|
||||||
|
cx.observe_global::<SettingsStore>(Self::on_settings_changed),
|
||||||
|
cx.on_release(Self::release),
|
||||||
|
],
|
||||||
|
active_entry: None,
|
||||||
|
snippets,
|
||||||
|
languages,
|
||||||
|
client,
|
||||||
|
user_store,
|
||||||
|
settings_observer,
|
||||||
|
fs,
|
||||||
|
ssh_session: Some(ssh.clone()),
|
||||||
|
buffers_needing_diff: Default::default(),
|
||||||
|
git_diff_debouncer: DebouncedDelay::new(),
|
||||||
|
terminals: Terminals {
|
||||||
|
local_handles: Vec::new(),
|
||||||
|
},
|
||||||
|
node: Some(node),
|
||||||
|
default_prettier: DefaultPrettier::default(),
|
||||||
|
prettiers_per_worktree: HashMap::default(),
|
||||||
|
prettier_instances: HashMap::default(),
|
||||||
|
tasks,
|
||||||
|
hosted_project_id: None,
|
||||||
|
dev_server_project_id: None,
|
||||||
|
search_history: Self::new_search_history(),
|
||||||
|
environment,
|
||||||
|
remotely_created_buffers: Default::default(),
|
||||||
|
last_formatting_failure: None,
|
||||||
|
buffers_being_formatted: Default::default(),
|
||||||
|
search_included_history: Self::new_search_history(),
|
||||||
|
search_excluded_history: Self::new_search_history(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let client: AnyProtoClient = ssh.clone().into();
|
||||||
|
|
||||||
ssh.subscribe_to_entity(SSH_PROJECT_ID, &cx.handle());
|
ssh.subscribe_to_entity(SSH_PROJECT_ID, &cx.handle());
|
||||||
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.buffer_store);
|
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.buffer_store);
|
||||||
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.worktree_store);
|
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.worktree_store);
|
||||||
|
@ -735,9 +805,8 @@ impl Project {
|
||||||
LspStore::init(&client);
|
LspStore::init(&client);
|
||||||
SettingsObserver::init(&client);
|
SettingsObserver::init(&client);
|
||||||
|
|
||||||
this.ssh_session = Some(ssh);
|
|
||||||
});
|
|
||||||
this
|
this
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remote(
|
pub async fn remote(
|
||||||
|
@ -820,16 +889,12 @@ impl Project {
|
||||||
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), Some(remote_id), cx))?;
|
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), Some(remote_id), cx))?;
|
||||||
|
|
||||||
let lsp_store = cx.new_model(|cx| {
|
let lsp_store = cx.new_model(|cx| {
|
||||||
let mut lsp_store = LspStore::new(
|
let mut lsp_store = LspStore::new_remote(
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
worktree_store.clone(),
|
worktree_store.clone(),
|
||||||
None,
|
|
||||||
languages.clone(),
|
languages.clone(),
|
||||||
Some(client.http_client()),
|
client.clone().into(),
|
||||||
fs.clone(),
|
remote_id,
|
||||||
None,
|
|
||||||
Some(client.clone().into()),
|
|
||||||
Some(remote_id),
|
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
lsp_store.set_language_server_statuses_from_proto(response.payload.language_servers);
|
lsp_store.set_language_server_statuses_from_proto(response.payload.language_servers);
|
||||||
|
@ -4785,7 +4850,7 @@ impl Project {
|
||||||
pub fn supplementary_language_servers<'a>(
|
pub fn supplementary_language_servers<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> impl '_ + Iterator<Item = (&'a LanguageServerId, &'a LanguageServerName)> {
|
) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
|
||||||
self.lsp_store.read(cx).supplementary_language_servers()
|
self.lsp_store.read(cx).supplementary_language_servers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,17 @@ impl HeadlessProject {
|
||||||
});
|
});
|
||||||
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
||||||
let lsp_store = cx.new_model(|cx| {
|
let lsp_store = cx.new_model(|cx| {
|
||||||
LspStore::new(
|
let mut lsp_store = LspStore::new_local(
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
worktree_store.clone(),
|
worktree_store.clone(),
|
||||||
Some(environment),
|
environment,
|
||||||
languages,
|
languages,
|
||||||
None,
|
None,
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
Some(session.clone().into()),
|
|
||||||
None,
|
|
||||||
Some(0),
|
|
||||||
cx,
|
cx,
|
||||||
)
|
);
|
||||||
|
lsp_store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
|
||||||
|
lsp_store
|
||||||
});
|
});
|
||||||
|
|
||||||
let client: AnyProtoClient = session.clone().into();
|
let client: AnyProtoClient = session.clone().into();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue