diff --git a/Cargo.lock b/Cargo.lock index 9c41daa031..66d6379691 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9951,7 +9951,7 @@ dependencies = [ [[package]] name = "tree-sitter" version = "0.20.10" -source = "git+https://github.com/tree-sitter/tree-sitter?rev=3b0159d25559b603af566ade3c83d930bf466db1#3b0159d25559b603af566ade3c83d930bf466db1" +source = "git+https://github.com/tree-sitter/tree-sitter?rev=b5f461a69bf3df7298b1903574d506179e6390b0#b5f461a69bf3df7298b1903574d506179e6390b0" dependencies = [ "cc", "regex", @@ -11554,7 +11554,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.115.0" +version = "0.115.3" dependencies = [ "activity_indicator", "ai", diff --git a/Cargo.toml b/Cargo.toml index 03a854b77f..e0a7e311d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -200,7 +200,7 @@ tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", re tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"} [patch.crates-io] -tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "3b0159d25559b603af566ade3c83d930bf466db1" } +tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "b5f461a69bf3df7298b1903574d506179e6390b0" } async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" } # TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457 diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index ef6a655bdc..2a8d19f882 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -530,12 +530,17 @@ "alt-cmd-shift-c": "project_panel::CopyRelativePath", "f2": "project_panel::Rename", "enter": "project_panel::Rename", - "space": "project_panel::Open", "backspace": "project_panel::Delete", "alt-cmd-r": "project_panel::RevealInFinder", "alt-shift-f": "project_panel::NewSearchInDirectory" } }, + { + "context": "ProjectPanel && not_editing", + "bindings": { + "space": "project_panel::Open" + } + }, { "context": "CollabPanel && not_editing", "bindings": { diff --git a/crates/collab/src/api.rs b/crates/collab/src/api.rs index a84fcf328b..8d286388cf 100644 --- a/crates/collab/src/api.rs +++ b/crates/collab/src/api.rs @@ -116,12 +116,13 @@ struct CreateUserResponse { #[derive(Debug, Deserialize)] struct Panic { version: String, + release_channel: String, text: String, } #[instrument(skip(panic))] async fn trace_panic(panic: Json) -> Result<()> { - tracing::error!(version = %panic.version, text = %panic.text, "panic report"); + tracing::error!(version = %panic.version, release_channel = %panic.release_channel, text = %panic.text, "panic report"); Ok(()) } diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index fa7c4fe67d..c5820b5395 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -3941,7 +3941,7 @@ async fn test_collaborating_with_diagnostics( // Ensure client B observes the new diagnostics. project_b.read_with(cx_b, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), &[( ProjectPath { worktree_id, @@ -3961,14 +3961,14 @@ async fn test_collaborating_with_diagnostics( let project_c = client_c.build_remote_project(project_id, cx_c).await; let project_c_diagnostic_summaries = Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| { - project.diagnostic_summaries(cx).collect::>() + project.diagnostic_summaries(false, cx).collect::>() }))); project_c.update(cx_c, |_, cx| { let summaries = project_c_diagnostic_summaries.clone(); cx.subscribe(&project_c, { move |p, _, event, cx| { if let project::Event::DiskBasedDiagnosticsFinished { .. } = event { - *summaries.borrow_mut() = p.diagnostic_summaries(cx).collect(); + *summaries.borrow_mut() = p.diagnostic_summaries(false, cx).collect(); } } }) @@ -4018,7 +4018,7 @@ async fn test_collaborating_with_diagnostics( deterministic.run_until_parked(); project_b.read_with(cx_b, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), [( ProjectPath { worktree_id, @@ -4034,7 +4034,7 @@ async fn test_collaborating_with_diagnostics( }); project_c.read_with(cx_c, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), [( ProjectPath { worktree_id, @@ -4097,13 +4097,22 @@ async fn test_collaborating_with_diagnostics( ); deterministic.run_until_parked(); project_a.read_with(cx_a, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); project_b.read_with(cx_b, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); project_c.read_with(cx_c, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); } diff --git a/crates/collab2/src/tests/integration_tests.rs b/crates/collab2/src/tests/integration_tests.rs index e579c384e3..2268a51f2b 100644 --- a/crates/collab2/src/tests/integration_tests.rs +++ b/crates/collab2/src/tests/integration_tests.rs @@ -3688,7 +3688,7 @@ async fn test_collaborating_with_diagnostics( project_b.read_with(cx_b, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), &[( ProjectPath { worktree_id, @@ -3708,14 +3708,14 @@ async fn test_collaborating_with_diagnostics( let project_c = client_c.build_remote_project(project_id, cx_c).await; let project_c_diagnostic_summaries = Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| { - project.diagnostic_summaries(cx).collect::>() + project.diagnostic_summaries(false, cx).collect::>() }))); project_c.update(cx_c, |_, cx| { let summaries = project_c_diagnostic_summaries.clone(); cx.subscribe(&project_c, { move |p, _, event, cx| { if let project::Event::DiskBasedDiagnosticsFinished { .. } = event { - *summaries.borrow_mut() = p.diagnostic_summaries(cx).collect(); + *summaries.borrow_mut() = p.diagnostic_summaries(false, cx).collect(); } } }) @@ -3766,7 +3766,7 @@ async fn test_collaborating_with_diagnostics( project_b.read_with(cx_b, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), [( ProjectPath { worktree_id, @@ -3783,7 +3783,7 @@ async fn test_collaborating_with_diagnostics( project_c.read_with(cx_c, |project, cx| { assert_eq!( - project.diagnostic_summaries(cx).collect::>(), + project.diagnostic_summaries(false, cx).collect::>(), [( ProjectPath { worktree_id, @@ -3844,15 +3844,24 @@ async fn test_collaborating_with_diagnostics( executor.run_until_parked(); project_a.read_with(cx_a, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); project_b.read_with(cx_b, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); project_c.read_with(cx_c, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).collect::>(), []) + assert_eq!( + project.diagnostic_summaries(false, cx).collect::>(), + [] + ) }); } diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 4748f63e5d..9ff3c04de8 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -126,7 +126,7 @@ impl View for ProjectDiagnosticsEditor { json!({ "project": json!({ "language_servers": project.language_server_statuses().collect::>(), - "summary": project.diagnostic_summary(cx), + "summary": project.diagnostic_summary(false, cx), }), "summary": self.summary, "paths_to_update": self.paths_to_update.iter().map(|(server_id, paths)| @@ -195,7 +195,7 @@ impl ProjectDiagnosticsEditor { }); let project = project_handle.read(cx); - let summary = project.diagnostic_summary(cx); + let summary = project.diagnostic_summary(false, cx); let mut this = Self { project: project_handle, summary, @@ -241,7 +241,7 @@ impl ProjectDiagnosticsEditor { let mut new_summaries: HashMap> = self .project .read(cx) - .diagnostic_summaries(cx) + .diagnostic_summaries(false, cx) .fold(HashMap::default(), |mut summaries, (path, server_id, _)| { summaries.entry(server_id).or_default().insert(path); summaries @@ -320,7 +320,7 @@ impl ProjectDiagnosticsEditor { .context("rechecking diagnostics for paths")?; this.update(&mut cx, |this, cx| { - this.summary = this.project.read(cx).diagnostic_summary(cx); + this.summary = this.project.read(cx).diagnostic_summary(false, cx); cx.emit(Event::TitleChanged); })?; anyhow::Ok(()) diff --git a/crates/diagnostics/src/items.rs b/crates/diagnostics/src/items.rs index 8d3c2fedd6..86d8d01db1 100644 --- a/crates/diagnostics/src/items.rs +++ b/crates/diagnostics/src/items.rs @@ -34,19 +34,19 @@ impl DiagnosticIndicator { } project::Event::DiskBasedDiagnosticsFinished { language_server_id } | project::Event::LanguageServerRemoved(language_server_id) => { - this.summary = project.read(cx).diagnostic_summary(cx); + this.summary = project.read(cx).diagnostic_summary(false, cx); this.in_progress_checks.remove(language_server_id); cx.notify(); } project::Event::DiagnosticsUpdated { .. } => { - this.summary = project.read(cx).diagnostic_summary(cx); + this.summary = project.read(cx).diagnostic_summary(false, cx); cx.notify(); } _ => {} }) .detach(); Self { - summary: project.read(cx).diagnostic_summary(cx), + summary: project.read(cx).diagnostic_summary(false, cx), in_progress_checks: project .read(cx) .language_servers_running_disk_based_diagnostics() diff --git a/crates/diagnostics2/src/diagnostics.rs b/crates/diagnostics2/src/diagnostics.rs index dc7f0a1f3f..0a0f4da893 100644 --- a/crates/diagnostics2/src/diagnostics.rs +++ b/crates/diagnostics2/src/diagnostics.rs @@ -165,7 +165,7 @@ impl ProjectDiagnosticsEditor { }); let project = project_handle.read(cx); - let summary = project.diagnostic_summary(cx); + let summary = project.diagnostic_summary(false, cx); let mut this = Self { project: project_handle, summary, @@ -252,7 +252,7 @@ impl ProjectDiagnosticsEditor { let mut new_summaries: HashMap> = self .project .read(cx) - .diagnostic_summaries(cx) + .diagnostic_summaries(false, cx) .fold(HashMap::default(), |mut summaries, (path, server_id, _)| { summaries.entry(server_id).or_default().insert(path); summaries @@ -332,7 +332,7 @@ impl ProjectDiagnosticsEditor { .context("rechecking diagnostics for paths")?; this.update(&mut cx, |this, cx| { - this.summary = this.project.read(cx).diagnostic_summary(cx); + this.summary = this.project.read(cx).diagnostic_summary(false, cx); cx.emit(ItemEvent::UpdateTab); cx.emit(ItemEvent::UpdateBreadcrumbs); })?; diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index ac24b7ad50..92b0641dea 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -77,13 +77,13 @@ impl DiagnosticIndicator { project::Event::DiskBasedDiagnosticsFinished { language_server_id } | project::Event::LanguageServerRemoved(language_server_id) => { - this.summary = project.read(cx).diagnostic_summary(cx); + this.summary = project.read(cx).diagnostic_summary(false, cx); this.in_progress_checks.remove(language_server_id); cx.notify(); } project::Event::DiagnosticsUpdated { .. } => { - this.summary = project.read(cx).diagnostic_summary(cx); + this.summary = project.read(cx).diagnostic_summary(false, cx); cx.notify(); } @@ -92,7 +92,7 @@ impl DiagnosticIndicator { .detach(); Self { - summary: project.read(cx).diagnostic_summary(cx), + summary: project.read(cx).diagnostic_summary(false, cx), in_progress_checks: project .read(cx) .language_servers_running_disk_based_diagnostics() diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index b7a4a387ab..156b062df8 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -518,6 +518,7 @@ impl PickerDelegate for FileFinderDelegate { } fn update_matches(&mut self, raw_query: String, cx: &mut ViewContext) -> Task<()> { + let raw_query = raw_query.trim(); if raw_query.is_empty() { let project = self.project.read(cx); self.latest_search_id = post_inc(&mut self.search_count); @@ -539,7 +540,6 @@ impl PickerDelegate for FileFinderDelegate { cx.notify(); Task::ready(()) } else { - let raw_query = &raw_query; let query = PathLikeWithPosition::parse_str(raw_query, |path_like_str| { Ok::<_, std::convert::Infallible>(FileSearchQuery { raw_query: raw_query.to_owned(), @@ -735,6 +735,7 @@ mod tests { cx.dispatch_action(window.into(), Toggle); let finder = cx.read(|cx| workspace.read(cx).modal::().unwrap()); + finder .update(cx, |finder, cx| { finder.delegate_mut().update_matches("bna".to_string(), cx) @@ -743,7 +744,6 @@ mod tests { finder.read_with(cx, |finder, _| { assert_eq!(finder.delegate().matches.len(), 2); }); - let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); cx.dispatch_action(window.into(), SelectNext); cx.dispatch_action(window.into(), Confirm); @@ -762,6 +762,49 @@ mod tests { "bandana" ); }); + + for bandana_query in [ + "bandana", + " bandana", + "bandana ", + " bandana ", + " ndan ", + " band ", + ] { + finder + .update(cx, |finder, cx| { + finder + .delegate_mut() + .update_matches(bandana_query.to_string(), cx) + }) + .await; + finder.read_with(cx, |finder, _| { + assert_eq!( + finder.delegate().matches.len(), + 1, + "Wrong number of matches for bandana query '{bandana_query}'" + ); + }); + let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone()); + cx.dispatch_action(window.into(), SelectNext); + cx.dispatch_action(window.into(), Confirm); + active_pane + .condition(cx, |pane, _| pane.active_item().is_some()) + .await; + cx.read(|cx| { + let active_item = active_pane.read(cx).active_item().unwrap(); + assert_eq!( + active_item + .as_any() + .downcast_ref::() + .unwrap() + .read(cx) + .title(cx), + "bandana", + "Wrong match for bandana query '{bandana_query}'" + ); + }); + } } #[gpui::test] diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 2f7b26dfb5..8f47881ea5 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -552,6 +552,7 @@ impl PickerDelegate for FileFinderDelegate { raw_query: String, cx: &mut ViewContext>, ) -> Task<()> { + let raw_query = raw_query.trim(); if raw_query.is_empty() { let project = self.project.read(cx); self.latest_search_id = post_inc(&mut self.search_count); @@ -573,7 +574,6 @@ impl PickerDelegate for FileFinderDelegate { cx.notify(); Task::ready(()) } else { - let raw_query = &raw_query; let query = PathLikeWithPosition::parse_str(raw_query, |path_like_str| { Ok::<_, std::convert::Infallible>(FileSearchQuery { raw_query: raw_query.to_owned(), @@ -768,18 +768,49 @@ mod tests { let (picker, workspace, cx) = build_find_picker(project, cx); cx.simulate_input("bna"); - picker.update(cx, |picker, _| { assert_eq!(picker.delegate.matches.len(), 2); }); - cx.dispatch_action(SelectNext); cx.dispatch_action(Confirm); - cx.read(|cx| { let active_editor = workspace.read(cx).active_item_as::(cx).unwrap(); assert_eq!(active_editor.read(cx).title(cx), "bandana"); }); + + for bandana_query in [ + "bandana", + " bandana", + "bandana ", + " bandana ", + " ndan ", + " band ", + ] { + picker + .update(cx, |picker, cx| { + picker + .delegate + .update_matches(bandana_query.to_string(), cx) + }) + .await; + picker.update(cx, |picker, _| { + assert_eq!( + picker.delegate.matches.len(), + 1, + "Wrong number of matches for bandana query '{bandana_query}'" + ); + }); + cx.dispatch_action(SelectNext); + cx.dispatch_action(Confirm); + cx.read(|cx| { + let active_editor = workspace.read(cx).active_item_as::(cx).unwrap(); + assert_eq!( + active_editor.read(cx).title(cx), + "bandana", + "Wrong match for bandana query '{bandana_query}'" + ); + }); + } } #[gpui::test] diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index af7504529c..811e549406 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -197,8 +197,12 @@ impl CachedLspAdapter { self.adapter.code_action_kinds() } - pub fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> { - self.adapter.workspace_configuration(cx) + pub fn workspace_configuration( + &self, + workspace_root: &Path, + cx: &mut AppContext, + ) -> BoxFuture<'static, Value> { + self.adapter.workspace_configuration(workspace_root, cx) } pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) { @@ -312,7 +316,7 @@ pub trait LspAdapter: 'static + Send + Sync { None } - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> BoxFuture<'static, Value> { futures::future::ready(serde_json::json!({})).boxed() } diff --git a/crates/language2/src/language2.rs b/crates/language2/src/language2.rs index 5c17592f0c..8fdf524f69 100644 --- a/crates/language2/src/language2.rs +++ b/crates/language2/src/language2.rs @@ -200,8 +200,12 @@ impl CachedLspAdapter { self.adapter.code_action_kinds() } - pub fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> { - self.adapter.workspace_configuration(cx) + pub fn workspace_configuration( + &self, + workspace_root: &Path, + cx: &mut AppContext, + ) -> BoxFuture<'static, Value> { + self.adapter.workspace_configuration(workspace_root, cx) } pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) { @@ -315,7 +319,7 @@ pub trait LspAdapter: 'static + Send + Sync { None } - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> BoxFuture<'static, Value> { futures::future::ready(serde_json::json!({})).boxed() } diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 98fd81f012..dc5b63d222 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -429,8 +429,8 @@ impl LanguageServer { let root_uri = Url::from_file_path(&self.root_path).unwrap(); #[allow(deprecated)] let params = InitializeParams { - process_id: Default::default(), - root_path: Default::default(), + process_id: None, + root_path: None, root_uri: Some(root_uri.clone()), initialization_options: options, capabilities: ClientCapabilities { @@ -451,12 +451,15 @@ impl LanguageServer { inlay_hint: Some(InlayHintWorkspaceClientCapabilities { refresh_support: Some(true), }), + diagnostic: Some(DiagnosticWorkspaceClientCapabilities { + refresh_support: None, + }), ..Default::default() }), text_document: Some(TextDocumentClientCapabilities { definition: Some(GotoCapability { link_support: Some(true), - ..Default::default() + dynamic_registration: None, }), code_action: Some(CodeActionClientCapabilities { code_action_literal_support: Some(CodeActionLiteralSupport { @@ -501,7 +504,7 @@ impl LanguageServer { }), hover: Some(HoverClientCapabilities { content_format: Some(vec![MarkupKind::Markdown]), - ..Default::default() + dynamic_registration: None, }), inlay_hint: Some(InlayHintClientCapabilities { resolve_support: Some(InlayHintResolveClientCapabilities { @@ -515,6 +518,20 @@ impl LanguageServer { }), dynamic_registration: Some(false), }), + publish_diagnostics: Some(PublishDiagnosticsClientCapabilities { + related_information: Some(true), + ..Default::default() + }), + formatting: Some(DynamicRegistrationClientCapabilities { + dynamic_registration: None, + }), + on_type_formatting: Some(DynamicRegistrationClientCapabilities { + dynamic_registration: None, + }), + diagnostic: Some(DiagnosticClientCapabilities { + related_document_support: Some(true), + dynamic_registration: None, + }), ..Default::default() }), experimental: Some(json!({ @@ -524,15 +541,15 @@ impl LanguageServer { work_done_progress: Some(true), ..Default::default() }), - ..Default::default() + general: None, }, - trace: Default::default(), + trace: None, workspace_folders: Some(vec![WorkspaceFolder { uri: root_uri, name: Default::default(), }]), - client_info: Default::default(), - locale: Default::default(), + client_info: None, + locale: None, }; let response = self.request::(params).await?; diff --git a/crates/lsp2/src/lsp2.rs b/crates/lsp2/src/lsp2.rs index 356d029c58..788c424373 100644 --- a/crates/lsp2/src/lsp2.rs +++ b/crates/lsp2/src/lsp2.rs @@ -434,8 +434,8 @@ impl LanguageServer { let root_uri = Url::from_file_path(&self.root_path).unwrap(); #[allow(deprecated)] let params = InitializeParams { - process_id: Default::default(), - root_path: Default::default(), + process_id: None, + root_path: None, root_uri: Some(root_uri.clone()), initialization_options: options, capabilities: ClientCapabilities { @@ -456,12 +456,15 @@ impl LanguageServer { inlay_hint: Some(InlayHintWorkspaceClientCapabilities { refresh_support: Some(true), }), + diagnostic: Some(DiagnosticWorkspaceClientCapabilities { + refresh_support: None, + }), ..Default::default() }), text_document: Some(TextDocumentClientCapabilities { definition: Some(GotoCapability { link_support: Some(true), - ..Default::default() + dynamic_registration: None, }), code_action: Some(CodeActionClientCapabilities { code_action_literal_support: Some(CodeActionLiteralSupport { @@ -503,7 +506,7 @@ impl LanguageServer { }), hover: Some(HoverClientCapabilities { content_format: Some(vec![MarkupKind::Markdown]), - ..Default::default() + dynamic_registration: None, }), inlay_hint: Some(InlayHintClientCapabilities { resolve_support: Some(InlayHintResolveClientCapabilities { @@ -517,6 +520,20 @@ impl LanguageServer { }), dynamic_registration: Some(false), }), + publish_diagnostics: Some(PublishDiagnosticsClientCapabilities { + related_information: Some(true), + ..Default::default() + }), + formatting: Some(DynamicRegistrationClientCapabilities { + dynamic_registration: None, + }), + on_type_formatting: Some(DynamicRegistrationClientCapabilities { + dynamic_registration: None, + }), + diagnostic: Some(DiagnosticClientCapabilities { + related_document_support: Some(true), + dynamic_registration: None, + }), ..Default::default() }), experimental: Some(json!({ @@ -526,15 +543,15 @@ impl LanguageServer { work_done_progress: Some(true), ..Default::default() }), - ..Default::default() + general: None, }, - trace: Default::default(), + trace: None, workspace_folders: Some(vec![WorkspaceFolder { uri: root_uri, name: Default::default(), }]), - client_info: Default::default(), - locale: Default::default(), + client_info: None, + locale: None, }; let response = self.request::(params).await?; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a2ad82585e..21d64fe91f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2641,8 +2641,9 @@ impl Project { }); for (adapter, server) in servers { - let workspace_config = - cx.update(|cx| adapter.workspace_configuration(cx)).await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(server.root_path(), cx)) + .await; server .notify::( lsp::DidChangeConfigurationParams { @@ -2753,7 +2754,7 @@ impl Project { stderr_capture.clone(), language.clone(), adapter.clone(), - worktree_path, + Arc::clone(&worktree_path), ProjectLspAdapterDelegate::new(self, cx), cx, ) { @@ -2776,6 +2777,7 @@ impl Project { cx.spawn_weak(|this, mut cx| async move { let result = Self::setup_and_insert_language_server( this, + &worktree_path, override_options, pending_server, adapter.clone(), @@ -2891,6 +2893,7 @@ impl Project { async fn setup_and_insert_language_server( this: WeakModelHandle, + worktree_path: &Path, override_initialization_options: Option, pending_server: PendingLanguageServer, adapter: Arc, @@ -2903,6 +2906,7 @@ impl Project { this, override_initialization_options, pending_server, + worktree_path, adapter.clone(), server_id, cx, @@ -2932,11 +2936,14 @@ impl Project { this: WeakModelHandle, override_options: Option, pending_server: PendingLanguageServer, + worktree_path: &Path, adapter: Arc, server_id: LanguageServerId, cx: &mut AsyncAppContext, ) -> Result> { - let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx)).await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(worktree_path, cx)) + .await; let language_server = pending_server.task.await?; language_server @@ -2964,11 +2971,14 @@ impl Project { language_server .on_request::({ let adapter = adapter.clone(); + let worktree_path = worktree_path.to_path_buf(); move |params, mut cx| { let adapter = adapter.clone(); + let worktree_path = worktree_path.clone(); async move { - let workspace_config = - cx.update(|cx| adapter.workspace_configuration(cx)).await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(&worktree_path, cx)) + .await; Ok(params .items .into_iter() @@ -6523,9 +6533,15 @@ impl Project { }) } - pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary { + pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary { let mut summary = DiagnosticSummary::default(); - for (_, _, path_summary) in self.diagnostic_summaries(cx) { + for (_, _, path_summary) in + self.diagnostic_summaries(include_ignored, cx) + .filter(|(path, _, _)| { + let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored); + include_ignored || worktree == Some(false) + }) + { summary.error_count += path_summary.error_count; summary.warning_count += path_summary.warning_count; } @@ -6534,6 +6550,7 @@ impl Project { pub fn diagnostic_summaries<'a>( &'a self, + include_ignored: bool, cx: &'a AppContext, ) -> impl Iterator + 'a { self.visible_worktrees(cx).flat_map(move |worktree| { @@ -6544,6 +6561,10 @@ impl Project { .map(move |(path, server_id, summary)| { (ProjectPath { worktree_id, path }, server_id, summary) }) + .filter(move |(path, _, _)| { + let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored); + include_ignored || worktree == Some(false) + }) }) } diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 264c1ff7b5..5d061b868f 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -806,7 +806,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { } #[gpui::test] -async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { +async fn test_omitted_diagnostics(cx: &mut gpui::TestAppContext) { init_test(cx); let fs = FakeFs::new(cx.background()); @@ -814,7 +814,12 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { "/root", json!({ "dir": { + ".git": { + "HEAD": "ref: refs/heads/main", + }, + ".gitignore": "b.rs", "a.rs": "let a = 1;", + "b.rs": "let b = 2;", }, "other.rs": "let b = c;" }), @@ -822,6 +827,13 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { .await; let project = Project::test(fs, ["/root/dir".as_ref()], cx).await; + let (worktree, _) = project + .update(cx, |project, cx| { + project.find_or_create_local_worktree("/root/dir", true, cx) + }) + .await + .unwrap(); + let main_worktree_id = worktree.read_with(cx, |tree, _| tree.id()); let (worktree, _) = project .update(cx, |project, cx| { @@ -829,12 +841,30 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { }) .await .unwrap(); - let worktree_id = worktree.read_with(cx, |tree, _| tree.id()); + let other_worktree_id = worktree.read_with(cx, |tree, _| tree.id()); + let server_id = LanguageServerId(0); project.update(cx, |project, cx| { project .update_diagnostics( - LanguageServerId(0), + server_id, + lsp::PublishDiagnosticsParams { + uri: Url::from_file_path("/root/dir/b.rs").unwrap(), + version: None, + diagnostics: vec![lsp::Diagnostic { + range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 5)), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "unused variable 'b'".to_string(), + ..Default::default() + }], + }, + &[], + cx, + ) + .unwrap(); + project + .update_diagnostics( + server_id, lsp::PublishDiagnosticsParams { uri: Url::from_file_path("/root/other.rs").unwrap(), version: None, @@ -851,11 +881,34 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { .unwrap(); }); - let buffer = project - .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx)) + let main_ignored_buffer = project + .update(cx, |project, cx| { + project.open_buffer((main_worktree_id, "b.rs"), cx) + }) .await .unwrap(); - buffer.read_with(cx, |buffer, _| { + main_ignored_buffer.read_with(cx, |buffer, _| { + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); + assert_eq!( + chunks + .iter() + .map(|(s, d)| (s.as_str(), *d)) + .collect::>(), + &[ + ("let ", None), + ("b", Some(DiagnosticSeverity::ERROR)), + (" = 2;", None), + ], + "Gigitnored buffers should still get in-buffer diagnostics", + ); + }); + let other_buffer = project + .update(cx, |project, cx| { + project.open_buffer((other_worktree_id, ""), cx) + }) + .await + .unwrap(); + other_buffer.read_with(cx, |buffer, _| { let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks @@ -866,13 +919,29 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { ("let b = ", None), ("c", Some(DiagnosticSeverity::ERROR)), (";", None), - ] + ], + "Buffers from hidden projects should still get in-buffer diagnostics" ); }); project.read_with(cx, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).next(), None); - assert_eq!(project.diagnostic_summary(cx).error_count, 0); + assert_eq!(project.diagnostic_summaries(false, cx).next(), None); + assert_eq!( + project.diagnostic_summaries(true, cx).collect::>(), + vec![( + ProjectPath { + worktree_id: main_worktree_id, + path: Arc::from(Path::new("b.rs")), + }, + server_id, + DiagnosticSummary { + error_count: 1, + warning_count: 0, + } + )] + ); + assert_eq!(project.diagnostic_summary(false, cx).error_count, 0); + assert_eq!(project.diagnostic_summary(true, cx).error_count, 1); }); } @@ -1145,7 +1214,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp }); project.read_with(cx, |project, cx| { assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 1, warning_count: 0, @@ -1171,7 +1240,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp }); project.read_with(cx, |project, cx| { assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 0, warning_count: 0, @@ -1763,7 +1832,7 @@ async fn test_diagnostics_from_multiple_language_servers(cx: &mut gpui::TestAppC .unwrap(); assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 2, warning_count: 0, diff --git a/crates/project2/src/project2.rs b/crates/project2/src/project2.rs index d2cc4fe406..12940dd2c4 100644 --- a/crates/project2/src/project2.rs +++ b/crates/project2/src/project2.rs @@ -2677,8 +2677,9 @@ impl Project { })?; for (adapter, server) in servers { - let workspace_config = - cx.update(|cx| adapter.workspace_configuration(cx))?.await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(server.root_path(), cx))? + .await; server .notify::( lsp::DidChangeConfigurationParams { @@ -2790,7 +2791,7 @@ impl Project { stderr_capture.clone(), language.clone(), adapter.clone(), - worktree_path, + Arc::clone(&worktree_path), ProjectLspAdapterDelegate::new(self, cx), cx, ) { @@ -2822,6 +2823,7 @@ impl Project { cx.spawn(move |this, mut cx| async move { let result = Self::setup_and_insert_language_server( this.clone(), + &worktree_path, initialization_options, pending_server, adapter.clone(), @@ -2942,6 +2944,7 @@ impl Project { async fn setup_and_insert_language_server( this: WeakModel, + worktree_path: &Path, initialization_options: Option, pending_server: PendingLanguageServer, adapter: Arc, @@ -2954,6 +2957,7 @@ impl Project { this.clone(), initialization_options, pending_server, + worktree_path, adapter.clone(), server_id, cx, @@ -2983,11 +2987,14 @@ impl Project { this: WeakModel, initialization_options: Option, pending_server: PendingLanguageServer, + worktree_path: &Path, adapter: Arc, server_id: LanguageServerId, cx: &mut AsyncAppContext, ) -> Result> { - let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx))?.await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(worktree_path, cx))? + .await; let language_server = pending_server.task.await?; language_server @@ -3016,11 +3023,14 @@ impl Project { language_server .on_request::({ let adapter = adapter.clone(); + let worktree_path = worktree_path.to_path_buf(); move |params, cx| { let adapter = adapter.clone(); + let worktree_path = worktree_path.clone(); async move { - let workspace_config = - cx.update(|cx| adapter.workspace_configuration(cx))?.await; + let workspace_config = cx + .update(|cx| adapter.workspace_configuration(&worktree_path, cx))? + .await; Ok(params .items .into_iter() @@ -6596,9 +6606,15 @@ impl Project { }) } - pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary { + pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary { let mut summary = DiagnosticSummary::default(); - for (_, _, path_summary) in self.diagnostic_summaries(cx) { + for (_, _, path_summary) in + self.diagnostic_summaries(include_ignored, cx) + .filter(|(path, _, _)| { + let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored); + include_ignored || worktree == Some(false) + }) + { summary.error_count += path_summary.error_count; summary.warning_count += path_summary.warning_count; } @@ -6607,17 +6623,23 @@ impl Project { pub fn diagnostic_summaries<'a>( &'a self, + include_ignored: bool, cx: &'a AppContext, ) -> impl Iterator + 'a { - self.visible_worktrees(cx).flat_map(move |worktree| { - let worktree = worktree.read(cx); - let worktree_id = worktree.id(); - worktree - .diagnostic_summaries() - .map(move |(path, server_id, summary)| { - (ProjectPath { worktree_id, path }, server_id, summary) - }) - }) + self.visible_worktrees(cx) + .flat_map(move |worktree| { + let worktree = worktree.read(cx); + let worktree_id = worktree.id(); + worktree + .diagnostic_summaries() + .map(move |(path, server_id, summary)| { + (ProjectPath { worktree_id, path }, server_id, summary) + }) + }) + .filter(move |(path, _, _)| { + let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored); + include_ignored || worktree == Some(false) + }) } pub fn disk_based_diagnostics_started( diff --git a/crates/project2/src/project_tests.rs b/crates/project2/src/project_tests.rs index 53b2f6ba1f..4dfb8004e3 100644 --- a/crates/project2/src/project_tests.rs +++ b/crates/project2/src/project_tests.rs @@ -823,7 +823,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { } #[gpui::test] -async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { +async fn test_omitted_diagnostics(cx: &mut gpui::TestAppContext) { init_test(cx); let fs = FakeFs::new(cx.executor()); @@ -831,7 +831,12 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { "/root", json!({ "dir": { + ".git": { + "HEAD": "ref: refs/heads/main", + }, + ".gitignore": "b.rs", "a.rs": "let a = 1;", + "b.rs": "let b = 2;", }, "other.rs": "let b = c;" }), @@ -839,6 +844,13 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { .await; let project = Project::test(fs, ["/root/dir".as_ref()], cx).await; + let (worktree, _) = project + .update(cx, |project, cx| { + project.find_or_create_local_worktree("/root/dir", true, cx) + }) + .await + .unwrap(); + let main_worktree_id = worktree.read_with(cx, |tree, _| tree.id()); let (worktree, _) = project .update(cx, |project, cx| { @@ -846,12 +858,30 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { }) .await .unwrap(); - let worktree_id = worktree.update(cx, |tree, _| tree.id()); + let other_worktree_id = worktree.update(cx, |tree, _| tree.id()); + let server_id = LanguageServerId(0); project.update(cx, |project, cx| { project .update_diagnostics( - LanguageServerId(0), + server_id, + lsp::PublishDiagnosticsParams { + uri: Url::from_file_path("/root/dir/b.rs").unwrap(), + version: None, + diagnostics: vec![lsp::Diagnostic { + range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 5)), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "unused variable 'b'".to_string(), + ..Default::default() + }], + }, + &[], + cx, + ) + .unwrap(); + project + .update_diagnostics( + server_id, lsp::PublishDiagnosticsParams { uri: Url::from_file_path("/root/other.rs").unwrap(), version: None, @@ -868,11 +898,34 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { .unwrap(); }); - let buffer = project - .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx)) + let main_ignored_buffer = project + .update(cx, |project, cx| { + project.open_buffer((main_worktree_id, "b.rs"), cx) + }) .await .unwrap(); - buffer.update(cx, |buffer, _| { + main_ignored_buffer.update(cx, |buffer, _| { + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); + assert_eq!( + chunks + .iter() + .map(|(s, d)| (s.as_str(), *d)) + .collect::>(), + &[ + ("let ", None), + ("b", Some(DiagnosticSeverity::ERROR)), + (" = 2;", None), + ], + "Gigitnored buffers should still get in-buffer diagnostics", + ); + }); + let other_buffer = project + .update(cx, |project, cx| { + project.open_buffer((other_worktree_id, ""), cx) + }) + .await + .unwrap(); + other_buffer.update(cx, |buffer, _| { let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks @@ -883,13 +936,29 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { ("let b = ", None), ("c", Some(DiagnosticSeverity::ERROR)), (";", None), - ] + ], + "Buffers from hidden projects should still get in-buffer diagnostics" ); }); project.update(cx, |project, cx| { - assert_eq!(project.diagnostic_summaries(cx).next(), None); - assert_eq!(project.diagnostic_summary(cx).error_count, 0); + assert_eq!(project.diagnostic_summaries(false, cx).next(), None); + assert_eq!( + project.diagnostic_summaries(true, cx).collect::>(), + vec![( + ProjectPath { + worktree_id: main_worktree_id, + path: Arc::from(Path::new("b.rs")), + }, + server_id, + DiagnosticSummary { + error_count: 1, + warning_count: 0, + } + )] + ); + assert_eq!(project.diagnostic_summary(false, cx).error_count, 0); + assert_eq!(project.diagnostic_summary(true, cx).error_count, 1); }); } @@ -1162,7 +1231,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp }); project.update(cx, |project, cx| { assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 1, warning_count: 0, @@ -1188,7 +1257,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp }); project.update(cx, |project, cx| { assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 0, warning_count: 0, @@ -1777,7 +1846,7 @@ async fn test_diagnostics_from_multiple_language_servers(cx: &mut gpui::TestAppC .unwrap(); assert_eq!( - project.diagnostic_summary(cx), + project.diagnostic_summary(false, cx), DiagnosticSummary { error_count: 2, warning_count: 0, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index eb124bfca2..875d4d4f83 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1627,9 +1627,21 @@ impl View for ProjectPanel { } } - fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { + fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) { Self::reset_to_default_keymap_context(keymap); keymap.add_identifier("menu"); + + if let Some(window) = cx.active_window() { + window.read_with(cx, |cx| { + let identifier = if self.filename_editor.is_focused(cx) { + "editing" + } else { + "not_editing" + }; + + keymap.add_identifier(identifier); + }); + } } fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext) { diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 359c5a8e6b..fa3f6f85ce 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -10,8 +10,9 @@ use anyhow::{anyhow, Result}; use gpui::{ actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, - Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, Stateful, Styled, - Task, UniformListScrollHandle, View, ViewContext, VisualContext as _, WeakView, WindowContext, + KeyContext, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, Stateful, + Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext as _, WeakView, + WindowContext, }; use menu::{Confirm, SelectNext, SelectPrev}; use project::{ @@ -1403,6 +1404,22 @@ impl ProjectPanel { // ); // }) } + + fn dispatch_context(&self, cx: &ViewContext) -> KeyContext { + let mut dispatch_context = KeyContext::default(); + dispatch_context.add("ProjectPanel"); + dispatch_context.add("menu"); + + let identifier = if self.filename_editor.focus_handle(cx).is_focused(cx) { + "editing" + } else { + "not_editing" + }; + + dispatch_context.add(identifier); + + dispatch_context + } } impl Render for ProjectPanel { @@ -1415,7 +1432,8 @@ impl Render for ProjectPanel { div() .id("project-panel") .size_full() - .key_context("ProjectPanel") + .relative() + .key_context(self.dispatch_context(cx)) .on_action(cx.listener(Self::select_next)) .on_action(cx.listener(Self::select_prev)) .on_action(cx.listener(Self::expand_selected_entry)) diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 297785fe9f..d2bf8fd6d9 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.115.0" +version = "0.115.3" publish = false [lib] diff --git a/crates/zed/RELEASE_CHANNEL b/crates/zed/RELEASE_CHANNEL index 90012116c0..870bbe4e50 100644 --- a/crates/zed/RELEASE_CHANNEL +++ b/crates/zed/RELEASE_CHANNEL @@ -1 +1 @@ -dev \ No newline at end of file +stable \ No newline at end of file diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index 63f909ae2a..891c25c31f 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -105,6 +105,7 @@ impl LspAdapter for JsonLspAdapter { fn workspace_configuration( &self, + _workspace_root: &Path, cx: &mut AppContext, ) -> BoxFuture<'static, serde_json::Value> { let action_names = cx.all_action_names().collect::>(); diff --git a/crates/zed/src/languages/php.rs b/crates/zed/src/languages/php.rs index 3096fd16e6..e3d0f1c690 100644 --- a/crates/zed/src/languages/php.rs +++ b/crates/zed/src/languages/php.rs @@ -29,7 +29,6 @@ pub struct IntelephenseLspAdapter { impl IntelephenseLspAdapter { const SERVER_PATH: &'static str = "node_modules/intelephense/lib/intelephense.js"; - #[allow(unused)] pub fn new(node: Arc) -> Self { Self { node } } diff --git a/crates/zed/src/languages/tailwind.rs b/crates/zed/src/languages/tailwind.rs index 6d6006dbd4..0dfa700b01 100644 --- a/crates/zed/src/languages/tailwind.rs +++ b/crates/zed/src/languages/tailwind.rs @@ -107,7 +107,11 @@ impl LspAdapter for TailwindLspAdapter { })) } - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + _workspace_root: &Path, + _: &mut AppContext, + ) -> BoxFuture<'static, Value> { future::ready(json!({ "tailwindCSS": { "emmetCompletions": true, diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index d259afb05d..fbb14930fc 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -205,7 +205,6 @@ pub struct EsLintLspAdapter { impl EsLintLspAdapter { const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js"; - #[allow(unused)] pub fn new(node: Arc) -> Self { EsLintLspAdapter { node } } @@ -213,13 +212,23 @@ impl EsLintLspAdapter { #[async_trait] impl LspAdapter for EsLintLspAdapter { - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + workspace_root: &Path, + _: &mut AppContext, + ) -> BoxFuture<'static, Value> { future::ready(json!({ "": { "validate": "on", "rulesCustomizations": [], "run": "onType", "nodePath": null, + "workingDirectory": {"mode": "auto"}, + "workspaceFolder": { + "uri": workspace_root, + "name": workspace_root.file_name() + .unwrap_or_else(|| workspace_root.as_os_str()), + }, } })) .boxed() diff --git a/crates/zed/src/languages/yaml.rs b/crates/zed/src/languages/yaml.rs index 8b438d0949..fbed9ba78f 100644 --- a/crates/zed/src/languages/yaml.rs +++ b/crates/zed/src/languages/yaml.rs @@ -93,7 +93,11 @@ impl LspAdapter for YamlLspAdapter { ) -> Option { get_cached_server_binary(container_dir, &*self.node).await } - fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + _workspace_root: &Path, + cx: &mut AppContext, + ) -> BoxFuture<'static, Value> { let tab_size = all_language_settings(None, cx) .language(Some("YAML")) .tab_size; diff --git a/crates/zed2/src/languages/json.rs b/crates/zed2/src/languages/json.rs index f04f59cf6d..162d4c9fdb 100644 --- a/crates/zed2/src/languages/json.rs +++ b/crates/zed2/src/languages/json.rs @@ -105,6 +105,7 @@ impl LspAdapter for JsonLspAdapter { fn workspace_configuration( &self, + _workspace_root: &Path, cx: &mut AppContext, ) -> BoxFuture<'static, serde_json::Value> { let action_names = cx.all_action_names(); diff --git a/crates/zed2/src/languages/php.rs b/crates/zed2/src/languages/php.rs index 3096fd16e6..e3d0f1c690 100644 --- a/crates/zed2/src/languages/php.rs +++ b/crates/zed2/src/languages/php.rs @@ -29,7 +29,6 @@ pub struct IntelephenseLspAdapter { impl IntelephenseLspAdapter { const SERVER_PATH: &'static str = "node_modules/intelephense/lib/intelephense.js"; - #[allow(unused)] pub fn new(node: Arc) -> Self { Self { node } } diff --git a/crates/zed2/src/languages/tailwind.rs b/crates/zed2/src/languages/tailwind.rs index 6d6006dbd4..0dfa700b01 100644 --- a/crates/zed2/src/languages/tailwind.rs +++ b/crates/zed2/src/languages/tailwind.rs @@ -107,7 +107,11 @@ impl LspAdapter for TailwindLspAdapter { })) } - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + _workspace_root: &Path, + _: &mut AppContext, + ) -> BoxFuture<'static, Value> { future::ready(json!({ "tailwindCSS": { "emmetCompletions": true, diff --git a/crates/zed2/src/languages/typescript.rs b/crates/zed2/src/languages/typescript.rs index 1b96e7e702..26ad337920 100644 --- a/crates/zed2/src/languages/typescript.rs +++ b/crates/zed2/src/languages/typescript.rs @@ -205,7 +205,6 @@ pub struct EsLintLspAdapter { impl EsLintLspAdapter { const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js"; - #[allow(unused)] pub fn new(node: Arc) -> Self { EsLintLspAdapter { node } } @@ -213,13 +212,23 @@ impl EsLintLspAdapter { #[async_trait] impl LspAdapter for EsLintLspAdapter { - fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + workspace_root: &Path, + _: &mut AppContext, + ) -> BoxFuture<'static, Value> { future::ready(json!({ "": { "validate": "on", "rulesCustomizations": [], "run": "onType", "nodePath": null, + "workingDirectory": {"mode": "auto"}, + "workspaceFolder": { + "uri": workspace_root, + "name": workspace_root.file_name() + .unwrap_or_else(|| workspace_root.as_os_str()), + }, } })) .boxed() diff --git a/crates/zed2/src/languages/yaml.rs b/crates/zed2/src/languages/yaml.rs index 8b438d0949..fbed9ba78f 100644 --- a/crates/zed2/src/languages/yaml.rs +++ b/crates/zed2/src/languages/yaml.rs @@ -93,7 +93,11 @@ impl LspAdapter for YamlLspAdapter { ) -> Option { get_cached_server_binary(container_dir, &*self.node).await } - fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> { + fn workspace_configuration( + &self, + _workspace_root: &Path, + cx: &mut AppContext, + ) -> BoxFuture<'static, Value> { let tab_size = all_language_settings(None, cx) .language(Some("YAML")) .tab_size;