use ssh lsp store (#17655)
Release Notes: - ssh remoting: Added support for booting langauge servers (in limited circumstances) --------- Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
130f19d8f9
commit
36eb1c15ea
45 changed files with 1553 additions and 671 deletions
|
@ -86,7 +86,7 @@ impl SignatureHelp {
|
|||
} else {
|
||||
let markdown = markdown.join(str_for_join);
|
||||
let language_name = language
|
||||
.map(|n| n.name().to_lowercase())
|
||||
.map(|n| n.name().0.to_lowercase())
|
||||
.unwrap_or_default();
|
||||
|
||||
let markdown = if function_options_count >= 2 {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -107,7 +107,7 @@ pub use buffer_store::ProjectTransaction;
|
|||
pub use lsp_store::{
|
||||
DiagnosticSummary, LanguageServerLogType, LanguageServerProgress, LanguageServerPromptRequest,
|
||||
LanguageServerStatus, LanguageServerToQuery, LspStore, LspStoreEvent,
|
||||
ProjectLspAdapterDelegate, SERVER_PROGRESS_THROTTLE_TIMEOUT,
|
||||
SERVER_PROGRESS_THROTTLE_TIMEOUT,
|
||||
};
|
||||
|
||||
const MAX_PROJECT_SEARCH_HISTORY_SIZE: usize = 500;
|
||||
|
@ -643,16 +643,13 @@ impl Project {
|
|||
|
||||
let environment = ProjectEnvironment::new(&worktree_store, env, cx);
|
||||
let lsp_store = cx.new_model(|cx| {
|
||||
LspStore::new(
|
||||
LspStore::new_local(
|
||||
buffer_store.clone(),
|
||||
worktree_store.clone(),
|
||||
Some(environment.clone()),
|
||||
environment.clone(),
|
||||
languages.clone(),
|
||||
Some(client.http_client()),
|
||||
fs.clone(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
@ -712,17 +709,90 @@ impl Project {
|
|||
fs: Arc<dyn Fs>,
|
||||
cx: &mut AppContext,
|
||||
) -> Model<Self> {
|
||||
let this = Self::local(client, node, user_store, languages, fs, None, cx);
|
||||
this.update(cx, |this, cx| {
|
||||
let client: AnyProtoClient = ssh.clone().into();
|
||||
cx.new_model(|cx: &mut ModelContext<Self>| {
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
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| {
|
||||
store.set_upstream_client(client.clone());
|
||||
let worktree_store = cx.new_model(|_| {
|
||||
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| {
|
||||
SettingsObserver::new_ssh(ssh.clone().into(), this.worktree_store.clone(), cx)
|
||||
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
|
||||
.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_ssh(
|
||||
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, &this.buffer_store);
|
||||
ssh.subscribe_to_entity(SSH_PROJECT_ID, &this.worktree_store);
|
||||
|
@ -735,9 +805,8 @@ impl Project {
|
|||
LspStore::init(&client);
|
||||
SettingsObserver::init(&client);
|
||||
|
||||
this.ssh_session = Some(ssh);
|
||||
});
|
||||
this
|
||||
this
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn remote(
|
||||
|
@ -820,16 +889,12 @@ impl Project {
|
|||
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), Some(remote_id), cx))?;
|
||||
|
||||
let lsp_store = cx.new_model(|cx| {
|
||||
let mut lsp_store = LspStore::new(
|
||||
let mut lsp_store = LspStore::new_remote(
|
||||
buffer_store.clone(),
|
||||
worktree_store.clone(),
|
||||
None,
|
||||
languages.clone(),
|
||||
Some(client.http_client()),
|
||||
fs.clone(),
|
||||
None,
|
||||
Some(client.clone().into()),
|
||||
Some(remote_id),
|
||||
client.clone().into(),
|
||||
remote_id,
|
||||
cx,
|
||||
);
|
||||
lsp_store.set_language_server_statuses_from_proto(response.payload.language_servers);
|
||||
|
@ -1125,8 +1190,7 @@ impl Project {
|
|||
if let Some(language) = buffer_language {
|
||||
if settings.enable_language_server {
|
||||
if let Some(file) = buffer_file {
|
||||
language_servers_to_start
|
||||
.push((file.worktree.clone(), Arc::clone(language)));
|
||||
language_servers_to_start.push((file.worktree.clone(), language.name()));
|
||||
}
|
||||
}
|
||||
language_formatters_to_check
|
||||
|
@ -1144,7 +1208,7 @@ impl Project {
|
|||
let language = languages.iter().find_map(|l| {
|
||||
let adapter = self
|
||||
.languages
|
||||
.lsp_adapters(l)
|
||||
.lsp_adapters(&l.name())
|
||||
.iter()
|
||||
.find(|adapter| adapter.name == started_lsp_name)?
|
||||
.clone();
|
||||
|
@ -1165,11 +1229,11 @@ impl Project {
|
|||
) {
|
||||
(None, None) => {}
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
language_servers_to_restart.push((worktree, Arc::clone(language)));
|
||||
language_servers_to_restart.push((worktree, language.name()));
|
||||
}
|
||||
(Some(current_lsp_settings), Some(new_lsp_settings)) => {
|
||||
if current_lsp_settings != new_lsp_settings {
|
||||
language_servers_to_restart.push((worktree, Arc::clone(language)));
|
||||
language_servers_to_restart.push((worktree, language.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4777,7 +4841,7 @@ impl Project {
|
|||
pub fn supplementary_language_servers<'a>(
|
||||
&'a self,
|
||||
cx: &'a AppContext,
|
||||
) -> impl '_ + Iterator<Item = (&'a LanguageServerId, &'a LanguageServerName)> {
|
||||
) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
|
||||
self.lsp_store.read(cx).supplementary_language_servers()
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use worktree::{PathChange, UpdatedEntriesSet, Worktree, WorktreeId};
|
|||
|
||||
use crate::worktree_store::{WorktreeStore, WorktreeStoreEvent};
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct ProjectSettings {
|
||||
/// Configuration for language servers.
|
||||
///
|
||||
|
|
|
@ -6,7 +6,7 @@ use http_client::Url;
|
|||
use language::{
|
||||
language_settings::{AllLanguageSettings, LanguageSettingsContent},
|
||||
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticSet, FakeLspAdapter,
|
||||
LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, ToPoint,
|
||||
LanguageConfig, LanguageMatcher, LanguageName, LineEnding, OffsetRangeExt, Point, ToPoint,
|
||||
};
|
||||
use lsp::{DiagnosticSeverity, NumberOrString};
|
||||
use parking_lot::Mutex;
|
||||
|
@ -1559,7 +1559,7 @@ async fn test_toggling_enable_language_server(cx: &mut gpui::TestAppContext) {
|
|||
SettingsStore::update_global(cx, |settings, cx| {
|
||||
settings.update_user_settings::<AllLanguageSettings>(cx, |settings| {
|
||||
settings.languages.insert(
|
||||
Arc::from("Rust"),
|
||||
"Rust".into(),
|
||||
LanguageSettingsContent {
|
||||
enable_language_server: Some(false),
|
||||
..Default::default()
|
||||
|
@ -1578,14 +1578,14 @@ async fn test_toggling_enable_language_server(cx: &mut gpui::TestAppContext) {
|
|||
SettingsStore::update_global(cx, |settings, cx| {
|
||||
settings.update_user_settings::<AllLanguageSettings>(cx, |settings| {
|
||||
settings.languages.insert(
|
||||
Arc::from("Rust"),
|
||||
LanguageName::new("Rust"),
|
||||
LanguageSettingsContent {
|
||||
enable_language_server: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
settings.languages.insert(
|
||||
Arc::from("JavaScript"),
|
||||
LanguageName::new("JavaScript"),
|
||||
LanguageSettingsContent {
|
||||
enable_language_server: Some(false),
|
||||
..Default::default()
|
||||
|
@ -2983,7 +2983,7 @@ async fn test_save_as(cx: &mut gpui::TestAppContext) {
|
|||
buffer.edit([(0..0, "abc")], None, cx);
|
||||
assert!(buffer.is_dirty());
|
||||
assert!(!buffer.has_conflict());
|
||||
assert_eq!(buffer.language().unwrap().name().as_ref(), "Plain Text");
|
||||
assert_eq!(buffer.language().unwrap().name(), "Plain Text".into());
|
||||
});
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
|
@ -3006,7 +3006,7 @@ async fn test_save_as(cx: &mut gpui::TestAppContext) {
|
|||
);
|
||||
assert!(!buffer.is_dirty());
|
||||
assert!(!buffer.has_conflict());
|
||||
assert_eq!(buffer.language().unwrap().name().as_ref(), "Rust");
|
||||
assert_eq!(buffer.language().unwrap().name(), "Rust".into());
|
||||
});
|
||||
|
||||
let opened_buffer = project
|
||||
|
@ -5308,7 +5308,7 @@ fn json_lang() -> Arc<Language> {
|
|||
fn js_lang() -> Arc<Language> {
|
||||
Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
name: Arc::from("JavaScript"),
|
||||
name: "JavaScript".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["js".to_string()],
|
||||
..Default::default()
|
||||
|
|
|
@ -161,7 +161,7 @@ impl Inventory {
|
|||
cx: &AppContext,
|
||||
) -> Vec<(TaskSourceKind, TaskTemplate)> {
|
||||
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language {
|
||||
name: language.name(),
|
||||
name: language.name().0,
|
||||
});
|
||||
let language_tasks = language
|
||||
.and_then(|language| language.context_provider()?.associated_tasks(file, cx))
|
||||
|
@ -207,7 +207,7 @@ impl Inventory {
|
|||
.as_ref()
|
||||
.and_then(|location| location.buffer.read(cx).language_at(location.range.start));
|
||||
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language {
|
||||
name: language.name(),
|
||||
name: language.name().0,
|
||||
});
|
||||
let file = location
|
||||
.as_ref()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue