languages: Pass fs into the init function (#38007)

Piotr Osiewicz and Cole Miller created

Release Notes:

- N/A

---------

Co-authored-by: Cole Miller <cole@zed.dev>

Change summary

Cargo.lock                                             |  1 
crates/eval/src/eval.rs                                |  2 
crates/language/src/language.rs                        |  6 -
crates/language/src/task_context.rs                    |  7 -
crates/language_extension/src/extension_lsp_adapter.rs |  6 -
crates/languages/src/css.rs                            |  4 
crates/languages/src/go.rs                             | 10 -
crates/languages/src/json.rs                           |  5 
crates/languages/src/lib.rs                            | 12 +
crates/languages/src/python.rs                         |  7 -
crates/languages/src/rust.rs                           |  2 
crates/languages/src/tailwind.rs                       |  4 
crates/languages/src/typescript.rs                     | 32 ++++---
crates/languages/src/vtsls.rs                          | 13 +-
crates/languages/src/yaml.rs                           |  4 
crates/markdown/Cargo.toml                             |  1 
crates/markdown/examples/markdown.rs                   |  3 
crates/markdown/examples/markdown_as_child.rs          |  3 
crates/project/src/lsp_store.rs                        | 54 ++---------
crates/project/src/project.rs                          |  5 -
crates/project/src/task_inventory.rs                   | 28 +----
crates/project/src/task_store.rs                       |  6 
crates/remote_server/src/headless_project.rs           |  3 
crates/zed/src/main.rs                                 |  2 
crates/zed/src/zed.rs                                  |  3 
crates/zeta_cli/src/headless.rs                        |  2 
26 files changed, 75 insertions(+), 150 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -9945,6 +9945,7 @@ dependencies = [
  "assets",
  "base64 0.22.1",
  "env_logger 0.11.8",
+ "fs",
  "futures 0.3.31",
  "gpui",
  "language",

crates/eval/src/eval.rs 🔗

@@ -419,7 +419,7 @@ pub fn init(cx: &mut App) -> Arc<AgentAppState> {
     language_extension::init(LspAccess::Noop, extension_host_proxy, languages.clone());
     language_model::init(client.clone(), cx);
     language_models::init(user_store.clone(), client.clone(), cx);
-    languages::init(languages.clone(), node_runtime.clone(), cx);
+    languages::init(languages.clone(), fs.clone(), node_runtime.clone(), cx);
     prompt_store::init(cx);
     terminal_view::init(cx);
     let stdout_is_a_pty = false;

crates/language/src/language.rs 🔗

@@ -27,7 +27,6 @@ use crate::language_settings::SoftWrap;
 use anyhow::{Context as _, Result};
 use async_trait::async_trait;
 use collections::{HashMap, HashSet, IndexSet};
-use fs::Fs;
 use futures::Future;
 use gpui::{App, AsyncApp, Entity, SharedString, Task};
 pub use highlight_map::HighlightMap;
@@ -511,7 +510,6 @@ pub trait LspAdapter: 'static + Send + Sync {
     /// Returns initialization options that are going to be sent to a LSP server as a part of [`lsp::InitializeParams`]
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<Value>> {
         Ok(None)
@@ -519,7 +517,6 @@ pub trait LspAdapter: 'static + Send + Sync {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         _cx: &mut AsyncApp,
@@ -530,7 +527,6 @@ pub trait LspAdapter: 'static + Send + Sync {
     async fn additional_initialization_options(
         self: Arc<Self>,
         _target_language_server_id: LanguageServerName,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<Value>> {
         Ok(None)
@@ -539,7 +535,6 @@ pub trait LspAdapter: 'static + Send + Sync {
     async fn additional_workspace_configuration(
         self: Arc<Self>,
         _target_language_server_id: LanguageServerName,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
         _cx: &mut AsyncApp,
     ) -> Result<Option<Value>> {
@@ -2261,7 +2256,6 @@ impl LspAdapter for FakeLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<Value>> {
         Ok(self.initialization_options.clone())

crates/language/src/task_context.rs 🔗

@@ -37,12 +37,7 @@ pub trait ContextProvider: Send + Sync {
     }
 
     /// Provides all tasks, associated with the current language.
-    fn associated_tasks(
-        &self,
-        _: Arc<dyn Fs>,
-        _: Option<Arc<dyn File>>,
-        _: &App,
-    ) -> Task<Option<TaskTemplates>> {
+    fn associated_tasks(&self, _: Option<Arc<dyn File>>, _: &App) -> Task<Option<TaskTemplates>> {
         Task::ready(None)
     }
 

crates/language_extension/src/extension_lsp_adapter.rs 🔗

@@ -8,7 +8,6 @@ use anyhow::{Context as _, Result};
 use async_trait::async_trait;
 use collections::{HashMap, HashSet};
 use extension::{Extension, ExtensionLanguageServerProxy, WorktreeDelegate};
-use fs::Fs;
 use futures::{Future, FutureExt, future::join_all};
 use gpui::{App, AppContext, AsyncApp, Task};
 use language::{
@@ -264,7 +263,6 @@ impl LspAdapter for ExtensionLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         let delegate = Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _;
@@ -287,7 +285,6 @@ impl LspAdapter for ExtensionLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         _cx: &mut AsyncApp,
@@ -309,7 +306,6 @@ impl LspAdapter for ExtensionLspAdapter {
     async fn additional_initialization_options(
         self: Arc<Self>,
         target_language_server_id: LanguageServerName,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         let delegate = Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _;
@@ -335,7 +331,7 @@ impl LspAdapter for ExtensionLspAdapter {
     async fn additional_workspace_configuration(
         self: Arc<Self>,
         target_language_server_id: LanguageServerName,
-        _: &dyn Fs,
+
         delegate: &Arc<dyn LspAdapterDelegate>,
 
         _cx: &mut AsyncApp,

crates/languages/src/css.rs 🔗

@@ -5,7 +5,7 @@ use gpui::AsyncApp;
 use language::{LspAdapter, LspAdapterDelegate, Toolchain};
 use lsp::{LanguageServerBinary, LanguageServerName};
 use node_runtime::{NodeRuntime, VersionStrategy};
-use project::{Fs, lsp_store::language_server_settings};
+use project::lsp_store::language_server_settings;
 use serde_json::json;
 use smol::fs;
 use std::{
@@ -133,7 +133,6 @@ impl LspAdapter for CssLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         Ok(Some(json!({
@@ -143,7 +142,6 @@ impl LspAdapter for CssLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,

crates/languages/src/go.rs 🔗

@@ -6,7 +6,7 @@ use gpui::{App, AsyncApp, Task};
 use http_client::github::latest_github_release;
 pub use language::*;
 use lsp::{LanguageServerBinary, LanguageServerName};
-use project::Fs;
+
 use regex::Regex;
 use serde_json::json;
 use smol::fs;
@@ -200,7 +200,6 @@ impl super::LspAdapter for GoLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         Ok(Some(json!({
@@ -568,12 +567,7 @@ impl ContextProvider for GoContextProvider {
         )))
     }
 
-    fn associated_tasks(
-        &self,
-        _: Arc<dyn Fs>,
-        _: Option<Arc<dyn File>>,
-        _: &App,
-    ) -> Task<Option<TaskTemplates>> {
+    fn associated_tasks(&self, _: Option<Arc<dyn File>>, _: &App) -> Task<Option<TaskTemplates>> {
         let package_cwd = if GO_PACKAGE_TASK_VARIABLE.template_value() == "." {
             None
         } else {

crates/languages/src/json.rs 🔗

@@ -13,7 +13,7 @@ use language::{
 };
 use lsp::{LanguageServerBinary, LanguageServerName};
 use node_runtime::{NodeRuntime, VersionStrategy};
-use project::{Fs, lsp_store::language_server_settings};
+use project::lsp_store::language_server_settings;
 use serde_json::{Value, json};
 use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
 use smol::{
@@ -46,7 +46,6 @@ pub(crate) struct JsonTaskProvider;
 impl ContextProvider for JsonTaskProvider {
     fn associated_tasks(
         &self,
-        _: Arc<dyn Fs>,
         file: Option<Arc<dyn language::File>>,
         cx: &App,
     ) -> gpui::Task<Option<TaskTemplates>> {
@@ -393,7 +392,6 @@ impl LspAdapter for JsonLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         Ok(Some(json!({
@@ -403,7 +401,6 @@ impl LspAdapter for JsonLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,

crates/languages/src/lib.rs 🔗

@@ -1,6 +1,7 @@
 use anyhow::Context as _;
 use gpui::{App, SharedString, UpdateGlobal};
 use node_runtime::NodeRuntime;
+use project::Fs;
 use python::PyprojectTomlManifestProvider;
 use rust::CargoManifestProvider;
 use rust_embed::RustEmbed;
@@ -53,7 +54,7 @@ pub static LANGUAGE_GIT_COMMIT: std::sync::LazyLock<Arc<Language>> =
         ))
     });
 
-pub fn init(languages: Arc<LanguageRegistry>, node: NodeRuntime, cx: &mut App) {
+pub fn init(languages: Arc<LanguageRegistry>, fs: Arc<dyn Fs>, node: NodeRuntime, cx: &mut App) {
     #[cfg(feature = "load-grammars")]
     languages.register_native_grammars([
         ("bash", tree_sitter_bash::LANGUAGE),
@@ -94,9 +95,12 @@ pub fn init(languages: Arc<LanguageRegistry>, node: NodeRuntime, cx: &mut App) {
     let rust_context_provider = Arc::new(rust::RustContextProvider);
     let rust_lsp_adapter = Arc::new(rust::RustLspAdapter);
     let tailwind_adapter = Arc::new(tailwind::TailwindLspAdapter::new(node.clone()));
-    let typescript_context = Arc::new(typescript::TypeScriptContextProvider::new());
-    let typescript_lsp_adapter = Arc::new(typescript::TypeScriptLspAdapter::new(node.clone()));
-    let vtsls_adapter = Arc::new(vtsls::VtslsLspAdapter::new(node.clone()));
+    let typescript_context = Arc::new(typescript::TypeScriptContextProvider::new(fs.clone()));
+    let typescript_lsp_adapter = Arc::new(typescript::TypeScriptLspAdapter::new(
+        node.clone(),
+        fs.clone(),
+    ));
+    let vtsls_adapter = Arc::new(vtsls::VtslsLspAdapter::new(node.clone(), fs.clone()));
     let yaml_lsp_adapter = Arc::new(yaml::YamlLspAdapter::new(node));
 
     let built_in_languages = [

crates/languages/src/python.rs 🔗

@@ -119,7 +119,6 @@ impl LspAdapter for PythonLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<Value>> {
         // Provide minimal initialization options
@@ -324,7 +323,7 @@ impl LspAdapter for PythonLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
+
         adapter: &Arc<dyn LspAdapterDelegate>,
         toolchain: Option<Toolchain>,
         cx: &mut AsyncApp,
@@ -471,7 +470,6 @@ impl ContextProvider for PythonContextProvider {
 
     fn associated_tasks(
         &self,
-        _: Arc<dyn Fs>,
         file: Option<Arc<dyn language::File>>,
         cx: &App,
     ) -> Task<Option<TaskTemplates>> {
@@ -1270,7 +1268,6 @@ impl LspAdapter for PyLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         adapter: &Arc<dyn LspAdapterDelegate>,
         toolchain: Option<Toolchain>,
         cx: &mut AsyncApp,
@@ -1405,7 +1402,6 @@ impl LspAdapter for BasedPyrightLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<Value>> {
         // Provide minimal initialization options
@@ -1576,7 +1572,6 @@ impl LspAdapter for BasedPyrightLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         adapter: &Arc<dyn LspAdapterDelegate>,
         toolchain: Option<Toolchain>,
         cx: &mut AsyncApp,

crates/languages/src/rust.rs 🔗

@@ -7,7 +7,6 @@ use http_client::github::AssetKind;
 use http_client::github::{GitHubLspBinaryVersion, latest_github_release};
 pub use language::*;
 use lsp::{InitializeParams, LanguageServerBinary};
-use project::Fs;
 use project::lsp_store::rust_analyzer_ext::CARGO_DIAGNOSTICS_SOURCE_NAME;
 use project::project_settings::ProjectSettings;
 use regex::Regex;
@@ -632,7 +631,6 @@ impl ContextProvider for RustContextProvider {
 
     fn associated_tasks(
         &self,
-        _: Arc<dyn Fs>,
         file: Option<Arc<dyn language::File>>,
         cx: &App,
     ) -> Task<Option<TaskTemplates>> {

crates/languages/src/tailwind.rs 🔗

@@ -6,7 +6,7 @@ use gpui::AsyncApp;
 use language::{LanguageName, LspAdapter, LspAdapterDelegate, Toolchain};
 use lsp::{LanguageServerBinary, LanguageServerName};
 use node_runtime::{NodeRuntime, VersionStrategy};
-use project::{Fs, lsp_store::language_server_settings};
+use project::lsp_store::language_server_settings;
 use serde_json::{Value, json};
 use smol::fs;
 use std::{
@@ -138,7 +138,6 @@ impl LspAdapter for TailwindLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         Ok(Some(json!({
@@ -154,7 +153,6 @@ impl LspAdapter for TailwindLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,

crates/languages/src/typescript.rs 🔗

@@ -27,8 +27,8 @@ use util::{ResultExt, fs::remove_matching, maybe};
 
 use crate::{PackageJson, PackageJsonData, github_download::download_server_binary};
 
-#[derive(Debug)]
 pub(crate) struct TypeScriptContextProvider {
+    fs: Arc<dyn Fs>,
     last_package_json: PackageJsonContents,
 }
 
@@ -253,8 +253,9 @@ impl PackageJsonData {
 }
 
 impl TypeScriptContextProvider {
-    pub fn new() -> Self {
+    pub fn new(fs: Arc<dyn Fs>) -> Self {
         Self {
+            fs,
             last_package_json: PackageJsonContents::default(),
         }
     }
@@ -358,7 +359,6 @@ async fn detect_package_manager(
 impl ContextProvider for TypeScriptContextProvider {
     fn associated_tasks(
         &self,
-        fs: Arc<dyn Fs>,
         file: Option<Arc<dyn File>>,
         cx: &App,
     ) -> Task<Option<TaskTemplates>> {
@@ -369,8 +369,12 @@ impl ContextProvider for TypeScriptContextProvider {
             return Task::ready(None);
         };
         let file_relative_path = file.path().clone();
-        let package_json_data =
-            self.combined_package_json_data(fs.clone(), &worktree_root, &file_relative_path, cx);
+        let package_json_data = self.combined_package_json_data(
+            self.fs.clone(),
+            &worktree_root,
+            &file_relative_path,
+            cx,
+        );
 
         cx.background_spawn(async move {
             let mut task_templates = TaskTemplates(Vec::new());
@@ -514,6 +518,7 @@ fn replace_test_name_parameters(test_name: &str) -> String {
 }
 
 pub struct TypeScriptLspAdapter {
+    fs: Arc<dyn Fs>,
     node: NodeRuntime,
 }
 
@@ -523,10 +528,10 @@ impl TypeScriptLspAdapter {
     const SERVER_NAME: LanguageServerName =
         LanguageServerName::new_static("typescript-language-server");
     const PACKAGE_NAME: &str = "typescript";
-    pub fn new(node: NodeRuntime) -> Self {
-        TypeScriptLspAdapter { node }
+    pub fn new(node: NodeRuntime, fs: Arc<dyn Fs>) -> Self {
+        TypeScriptLspAdapter { fs, node }
     }
-    async fn tsdk_path(fs: &dyn Fs, adapter: &Arc<dyn LspAdapterDelegate>) -> Option<&'static str> {
+    async fn tsdk_path(&self, adapter: &Arc<dyn LspAdapterDelegate>) -> Option<&'static str> {
         let is_yarn = adapter
             .read_text_file(PathBuf::from(".yarn/sdks/typescript/lib/typescript.js"))
             .await
@@ -538,7 +543,8 @@ impl TypeScriptLspAdapter {
             "node_modules/typescript/lib"
         };
 
-        if fs
+        if self
+            .fs
             .is_dir(&adapter.worktree_root_path().join(tsdk_path))
             .await
         {
@@ -696,10 +702,9 @@ impl LspAdapter for TypeScriptLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        fs: &dyn Fs,
         adapter: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
-        let tsdk_path = Self::tsdk_path(fs, adapter).await;
+        let tsdk_path = self.tsdk_path(adapter).await;
         Ok(Some(json!({
             "provideFormatter": true,
             "hostInfo": "zed",
@@ -721,7 +726,7 @@ impl LspAdapter for TypeScriptLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
+
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,
@@ -821,7 +826,6 @@ impl LspAdapter for EsLintLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,
@@ -1145,7 +1149,7 @@ mod tests {
         )
         .await;
 
-        let provider = TypeScriptContextProvider::new();
+        let provider = TypeScriptContextProvider::new(fs.clone());
         let package_json_data = cx
             .update(|cx| {
                 provider.combined_package_json_data(

crates/languages/src/vtsls.rs 🔗

@@ -21,6 +21,7 @@ fn typescript_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
 
 pub struct VtslsLspAdapter {
     node: NodeRuntime,
+    fs: Arc<dyn Fs>,
 }
 
 impl VtslsLspAdapter {
@@ -30,11 +31,11 @@ impl VtslsLspAdapter {
     const TYPESCRIPT_PACKAGE_NAME: &'static str = "typescript";
     const TYPESCRIPT_TSDK_PATH: &'static str = "node_modules/typescript/lib";
 
-    pub fn new(node: NodeRuntime) -> Self {
-        VtslsLspAdapter { node }
+    pub fn new(node: NodeRuntime, fs: Arc<dyn Fs>) -> Self {
+        VtslsLspAdapter { node, fs }
     }
 
-    async fn tsdk_path(fs: &dyn Fs, adapter: &Arc<dyn LspAdapterDelegate>) -> Option<&'static str> {
+    async fn tsdk_path(&self, adapter: &Arc<dyn LspAdapterDelegate>) -> Option<&'static str> {
         let is_yarn = adapter
             .read_text_file(PathBuf::from(".yarn/sdks/typescript/lib/typescript.js"))
             .await
@@ -46,7 +47,8 @@ impl VtslsLspAdapter {
             Self::TYPESCRIPT_TSDK_PATH
         };
 
-        if fs
+        if self
+            .fs
             .is_dir(&adapter.worktree_root_path().join(tsdk_path))
             .await
         {
@@ -210,12 +212,11 @@ impl LspAdapter for VtslsLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        fs: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,
     ) -> Result<Value> {
-        let tsdk_path = Self::tsdk_path(fs, delegate).await;
+        let tsdk_path = self.tsdk_path(delegate).await;
         let config = serde_json::json!({
             "tsdk": tsdk_path,
             "suggest": {

crates/languages/src/yaml.rs 🔗

@@ -5,7 +5,7 @@ use gpui::AsyncApp;
 use language::{LspAdapter, LspAdapterDelegate, Toolchain, language_settings::AllLanguageSettings};
 use lsp::{LanguageServerBinary, LanguageServerName};
 use node_runtime::{NodeRuntime, VersionStrategy};
-use project::{Fs, lsp_store::language_server_settings};
+use project::lsp_store::language_server_settings;
 use serde_json::Value;
 use settings::{Settings, SettingsLocation};
 use smol::fs;
@@ -132,7 +132,7 @@ impl LspAdapter for YamlLspAdapter {
 
     async fn workspace_configuration(
         self: Arc<Self>,
-        _: &dyn Fs,
+
         delegate: &Arc<dyn LspAdapterDelegate>,
         _: Option<Toolchain>,
         cx: &mut AsyncApp,

crates/markdown/Cargo.toml 🔗

@@ -35,6 +35,7 @@ workspace-hack.workspace = true
 [dev-dependencies]
 assets.workspace = true
 env_logger.workspace = true
+fs = {workspace = true, features = ["test-support"]}
 gpui = { workspace = true, features = ["test-support"] }
 languages = { workspace = true, features = ["load-grammars"] }
 node_runtime.workspace = true

crates/markdown/examples/markdown.rs 🔗

@@ -47,10 +47,11 @@ pub fn main() {
         let node_runtime = NodeRuntime::unavailable();
         theme::init(LoadThemes::JustBase, cx);
 
+        let fs = fs::FakeFs::new(cx.background_executor().clone());
         let language_registry = LanguageRegistry::new(cx.background_executor().clone());
         language_registry.set_theme(cx.theme().clone());
         let language_registry = Arc::new(language_registry);
-        languages::init(language_registry.clone(), node_runtime, cx);
+        languages::init(language_registry.clone(), fs, node_runtime, cx);
         Assets.load_fonts(cx).unwrap();
 
         cx.activate(true);

crates/markdown/examples/markdown_as_child.rs 🔗

@@ -30,7 +30,8 @@ pub fn main() {
 
         let node_runtime = NodeRuntime::unavailable();
         let language_registry = Arc::new(LanguageRegistry::new(cx.background_executor().clone()));
-        languages::init(language_registry, node_runtime, cx);
+        let fs = fs::FakeFs::new(cx.background_executor().clone());
+        languages::init(language_registry, fs, node_runtime, cx);
         theme::init(LoadThemes::JustBase, cx);
         Assets.load_fonts(cx).unwrap();
 

crates/project/src/lsp_store.rs 🔗

@@ -361,7 +361,7 @@ impl LocalLspStore {
             let adapter = adapter.clone();
             let lsp_store = self.weak.clone();
             let pending_workspace_folders = pending_workspace_folders.clone();
-            let fs = self.fs.clone();
+
             let pull_diagnostics = ProjectSettings::get_global(cx)
                 .diagnostics
                 .lsp_pull_diagnostics
@@ -372,7 +372,6 @@ impl LocalLspStore {
 
                     let workspace_config = Self::workspace_configuration_for_adapter(
                         adapter.adapter.clone(),
-                        fs.as_ref(),
                         &delegate,
                         toolchain,
                         cx,
@@ -381,7 +380,6 @@ impl LocalLspStore {
 
                     let mut initialization_options = Self::initialization_options_for_adapter(
                         adapter.adapter.clone(),
-                        fs.as_ref(),
                         &delegate,
                     )
                     .await?;
@@ -403,7 +401,6 @@ impl LocalLspStore {
 
                     Self::setup_lsp_messages(
                         lsp_store.clone(),
-                        fs,
                         &language_server,
                         delegate.clone(),
                         adapter.clone(),
@@ -568,7 +565,7 @@ impl LocalLspStore {
 
     fn setup_lsp_messages(
         this: WeakEntity<LspStore>,
-        fs: Arc<dyn Fs>,
+
         language_server: &LanguageServer,
         delegate: Arc<dyn LspAdapterDelegate>,
         adapter: Arc<CachedLspAdapter>,
@@ -623,12 +620,11 @@ impl LocalLspStore {
                 let adapter = adapter.adapter.clone();
                 let delegate = delegate.clone();
                 let this = this.clone();
-                let fs = fs.clone();
+
                 move |params, cx| {
                     let adapter = adapter.clone();
                     let delegate = delegate.clone();
                     let this = this.clone();
-                    let fs = fs.clone();
                     let mut cx = cx.clone();
                     async move {
                         let toolchain_for_id = this
@@ -642,7 +638,6 @@ impl LocalLspStore {
                             .context("Expected the LSP store to be in a local mode")?;
                         let workspace_config = Self::workspace_configuration_for_adapter(
                             adapter.clone(),
-                            fs.as_ref(),
                             &delegate,
                             toolchain_for_id,
                             &mut cx,
@@ -3370,11 +3365,10 @@ impl LocalLspStore {
 
     async fn initialization_options_for_adapter(
         adapter: Arc<dyn LspAdapter>,
-        fs: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         let Some(mut initialization_config) =
-            adapter.clone().initialization_options(fs, delegate).await?
+            adapter.clone().initialization_options(delegate).await?
         else {
             return Ok(None);
         };
@@ -3385,7 +3379,7 @@ impl LocalLspStore {
             }
             if let Ok(Some(target_config)) = other_adapter
                 .clone()
-                .additional_initialization_options(adapter.name(), fs, delegate)
+                .additional_initialization_options(adapter.name(), delegate)
                 .await
             {
                 merge_json_value_into(target_config.clone(), &mut initialization_config);
@@ -3395,20 +3389,15 @@ impl LocalLspStore {
         Ok(Some(initialization_config))
     }
 
-    fn toolchain_store(&self) -> &Entity<LocalToolchainStore> {
-        &self.toolchain_store
-    }
-
     async fn workspace_configuration_for_adapter(
         adapter: Arc<dyn LspAdapter>,
-        fs: &dyn Fs,
         delegate: &Arc<dyn LspAdapterDelegate>,
         toolchain: Option<Toolchain>,
         cx: &mut AsyncApp,
     ) -> Result<serde_json::Value> {
         let mut workspace_config = adapter
             .clone()
-            .workspace_configuration(fs, delegate, toolchain, cx)
+            .workspace_configuration(delegate, toolchain, cx)
             .await?;
 
         for other_adapter in delegate.registered_lsp_adapters() {
@@ -3417,7 +3406,7 @@ impl LocalLspStore {
             }
             if let Ok(Some(target_config)) = other_adapter
                 .clone()
-                .additional_workspace_configuration(adapter.name(), fs, delegate, cx)
+                .additional_workspace_configuration(adapter.name(), delegate, cx)
                 .await
             {
                 merge_json_value_into(target_config.clone(), &mut workspace_config);
@@ -3705,10 +3694,7 @@ impl LspStore {
 
         let _maintain_workspace_config = {
             let (sender, receiver) = watch::channel();
-            (
-                Self::maintain_workspace_config(fs.clone(), receiver, cx),
-                sender,
-            )
+            (Self::maintain_workspace_config(receiver, cx), sender)
         };
 
         Self {
@@ -3795,7 +3781,6 @@ impl LspStore {
         languages: Arc<LanguageRegistry>,
         upstream_client: AnyProtoClient,
         project_id: u64,
-        fs: Arc<dyn Fs>,
         cx: &mut Context<Self>,
     ) -> Self {
         cx.subscribe(&buffer_store, Self::on_buffer_store_event)
@@ -3805,7 +3790,7 @@ impl LspStore {
         subscribe_to_binary_statuses(&languages, cx).detach();
         let _maintain_workspace_config = {
             let (sender, receiver) = watch::channel();
-            (Self::maintain_workspace_config(fs, receiver, cx), sender)
+            (Self::maintain_workspace_config(receiver, cx), sender)
         };
         Self {
             mode: LspStoreMode::Remote(RemoteLspStore {
@@ -4045,19 +4030,11 @@ impl LspStore {
                 return;
             };
 
-            let Ok(Some((fs, _))) = this.read_with(cx, |this, _| {
-                let local = this.as_local()?;
-                let toolchain_store = local.toolchain_store().clone();
-                Some((local.fs.clone(), toolchain_store))
-            }) else {
-                return;
-            };
             for (adapter, server, delegate) in servers {
                 adapter.clear_zed_json_schema_cache().await;
 
                 let Some(json_workspace_config) = LocalLspStore::workspace_configuration_for_adapter(
                         adapter,
-                        fs.as_ref(),
                         &delegate,
                         None,
                         cx,
@@ -7358,11 +7335,7 @@ impl LspStore {
         None
     }
 
-    async fn refresh_workspace_configurations(
-        lsp_store: &WeakEntity<Self>,
-        fs: Arc<dyn Fs>,
-        cx: &mut AsyncApp,
-    ) {
+    async fn refresh_workspace_configurations(lsp_store: &WeakEntity<Self>, cx: &mut AsyncApp) {
         maybe!(async move {
             let mut refreshed_servers = HashSet::default();
             let servers = lsp_store
@@ -7398,8 +7371,6 @@ impl LspStore {
                                 LanguageServerState::Running {
                                     adapter, server, ..
                                 } => {
-                                    let fs = fs.clone();
-
                                     let adapter = adapter.clone();
                                     let server = server.clone();
                                     refreshed_servers.insert(server.name());
@@ -7408,7 +7379,6 @@ impl LspStore {
                                         let settings =
                                             LocalLspStore::workspace_configuration_for_adapter(
                                                 adapter.adapter.clone(),
-                                                fs.as_ref(),
                                                 &delegate,
                                                 toolchain,
                                                 cx,
@@ -7445,7 +7415,6 @@ impl LspStore {
     }
 
     fn maintain_workspace_config(
-        fs: Arc<dyn Fs>,
         external_refresh_requests: watch::Receiver<()>,
         cx: &mut Context<Self>,
     ) -> Task<Result<()>> {
@@ -7471,7 +7440,7 @@ impl LspStore {
                 })
                 .ok();
 
-                Self::refresh_workspace_configurations(&this, fs.clone(), cx).await;
+                Self::refresh_workspace_configurations(&this, cx).await;
             }
 
             drop(settings_observation);
@@ -12618,7 +12587,6 @@ impl LspAdapter for SshLspAdapter {
 
     async fn initialization_options(
         self: Arc<Self>,
-        _: &dyn Fs,
         _: &Arc<dyn LspAdapterDelegate>,
     ) -> Result<Option<serde_json::Value>> {
         let Some(options) = &self.initialization_options else {

crates/project/src/project.rs 🔗

@@ -1132,7 +1132,6 @@ impl Project {
 
             let task_store = cx.new(|cx| {
                 TaskStore::local(
-                    fs.clone(),
                     buffer_store.downgrade(),
                     worktree_store.clone(),
                     toolchain_store.read(cx).as_language_toolchain_store(),
@@ -1290,7 +1289,6 @@ impl Project {
             });
             let task_store = cx.new(|cx| {
                 TaskStore::remote(
-                    fs.clone(),
                     buffer_store.downgrade(),
                     worktree_store.clone(),
                     toolchain_store.read(cx).as_language_toolchain_store(),
@@ -1321,7 +1319,6 @@ impl Project {
                     languages.clone(),
                     remote_proto.clone(),
                     REMOTE_SERVER_PROJECT_ID,
-                    fs.clone(),
                     cx,
                 )
             });
@@ -1540,7 +1537,6 @@ impl Project {
                 languages.clone(),
                 client.clone().into(),
                 remote_id,
-                fs.clone(),
                 cx,
             )
         })?;
@@ -1548,7 +1544,6 @@ impl Project {
         let task_store = cx.new(|cx| {
             if run_tasks {
                 TaskStore::remote(
-                    fs.clone(),
                     buffer_store.downgrade(),
                     worktree_store.clone(),
                     Arc::new(EmptyToolchainStore),

crates/project/src/task_inventory.rs 🔗

@@ -11,7 +11,6 @@ use std::{
 use anyhow::Result;
 use collections::{HashMap, HashSet, VecDeque};
 use dap::DapRegistry;
-use fs::Fs;
 use gpui::{App, AppContext as _, Context, Entity, SharedString, Task, WeakEntity};
 use itertools::Itertools;
 use language::{
@@ -40,7 +39,6 @@ pub struct DebugScenarioContext {
 
 /// Inventory tracks available tasks for a given project.
 pub struct Inventory {
-    fs: Arc<dyn Fs>,
     last_scheduled_tasks: VecDeque<(TaskSourceKind, ResolvedTask)>,
     last_scheduled_scenarios: VecDeque<(DebugScenario, DebugScenarioContext)>,
     templates_from_settings: InventoryFor<TaskTemplate>,
@@ -242,9 +240,8 @@ impl TaskSourceKind {
 }
 
 impl Inventory {
-    pub fn new(fs: Arc<dyn Fs>, cx: &mut App) -> Entity<Self> {
+    pub fn new(cx: &mut App) -> Entity<Self> {
         cx.new(|_| Self {
-            fs,
             last_scheduled_tasks: VecDeque::default(),
             last_scheduled_scenarios: VecDeque::default(),
             templates_from_settings: InventoryFor::default(),
@@ -387,7 +384,6 @@ impl Inventory {
         cx: &App,
     ) -> Task<Vec<(TaskSourceKind, TaskTemplate)>> {
         let global_tasks = self.global_templates_from_settings().collect::<Vec<_>>();
-        let fs = self.fs.clone();
         let mut worktree_tasks = worktree
             .into_iter()
             .flat_map(|worktree| self.worktree_templates_from_settings(worktree))
@@ -404,7 +400,7 @@ impl Inventory {
             .and_then(|language| {
                 language
                     .context_provider()
-                    .map(|provider| provider.associated_tasks(fs, file, cx))
+                    .map(|provider| provider.associated_tasks(file, cx))
             });
         cx.background_spawn(async move {
             if let Some(t) = language_tasks {
@@ -432,7 +428,6 @@ impl Inventory {
         Vec<(TaskSourceKind, ResolvedTask)>,
         Vec<(TaskSourceKind, ResolvedTask)>,
     )> {
-        let fs = self.fs.clone();
         let worktree = task_contexts.worktree();
         let location = task_contexts.location();
         let language = location.and_then(|location| location.buffer.read(cx).language());
@@ -489,7 +484,7 @@ impl Inventory {
             .and_then(|language| {
                 language
                     .context_provider()
-                    .map(|provider| provider.associated_tasks(fs, file, cx))
+                    .map(|provider| provider.associated_tasks(file, cx))
             });
         let worktree_tasks = worktree
             .into_iter()
@@ -1088,19 +1083,13 @@ impl ContextProviderWithTasks {
 }
 
 impl ContextProvider for ContextProviderWithTasks {
-    fn associated_tasks(
-        &self,
-        _: Arc<dyn Fs>,
-        _: Option<Arc<dyn File>>,
-        _: &App,
-    ) -> Task<Option<TaskTemplates>> {
+    fn associated_tasks(&self, _: Option<Arc<dyn File>>, _: &App) -> Task<Option<TaskTemplates>> {
         Task::ready(Some(self.templates.clone()))
     }
 }
 
 #[cfg(test)]
 mod tests {
-    use fs::FakeFs;
     use gpui::TestAppContext;
     use paths::tasks_file;
     use pretty_assertions::assert_eq;
@@ -1115,8 +1104,7 @@ mod tests {
     #[gpui::test]
     async fn test_task_list_sorting(cx: &mut TestAppContext) {
         init_test(cx);
-        let fs = FakeFs::new(cx.executor());
-        let inventory = cx.update(|cx| Inventory::new(fs, cx));
+        let inventory = cx.update(|cx| Inventory::new(cx));
         let initial_tasks = resolved_task_names(&inventory, None, cx).await;
         assert!(
             initial_tasks.is_empty(),
@@ -1296,8 +1284,7 @@ mod tests {
     #[gpui::test]
     async fn test_reloading_debug_scenarios(cx: &mut TestAppContext) {
         init_test(cx);
-        let fs = FakeFs::new(cx.executor());
-        let inventory = cx.update(|cx| Inventory::new(fs, cx));
+        let inventory = cx.update(|cx| Inventory::new(cx));
         inventory.update(cx, |inventory, _| {
             inventory
                 .update_file_based_scenarios(
@@ -1406,8 +1393,7 @@ mod tests {
     #[gpui::test]
     async fn test_inventory_static_task_filters(cx: &mut TestAppContext) {
         init_test(cx);
-        let fs = FakeFs::new(cx.executor());
-        let inventory = cx.update(|cx| Inventory::new(fs, cx));
+        let inventory = cx.update(|cx| Inventory::new(cx));
         let common_name = "common_task_name";
         let worktree_1 = WorktreeId::from_usize(1);
         let worktree_2 = WorktreeId::from_usize(2);

crates/project/src/task_store.rs 🔗

@@ -159,7 +159,6 @@ impl TaskStore {
     }
 
     pub fn local(
-        fs: Arc<dyn Fs>,
         buffer_store: WeakEntity<BufferStore>,
         worktree_store: Entity<WorktreeStore>,
         toolchain_store: Arc<dyn LanguageToolchainStore>,
@@ -171,7 +170,7 @@ impl TaskStore {
                 downstream_client: None,
                 environment,
             },
-            task_inventory: Inventory::new(fs, cx),
+            task_inventory: Inventory::new(cx),
             buffer_store,
             toolchain_store,
             worktree_store,
@@ -179,7 +178,6 @@ impl TaskStore {
     }
 
     pub fn remote(
-        fs: Arc<dyn Fs>,
         buffer_store: WeakEntity<BufferStore>,
         worktree_store: Entity<WorktreeStore>,
         toolchain_store: Arc<dyn LanguageToolchainStore>,
@@ -192,7 +190,7 @@ impl TaskStore {
                 upstream_client,
                 project_id,
             },
-            task_inventory: Inventory::new(fs, cx),
+            task_inventory: Inventory::new(cx),
             buffer_store,
             toolchain_store,
             worktree_store,

crates/remote_server/src/headless_project.rs 🔗

@@ -85,7 +85,7 @@ impl HeadlessProject {
         cx: &mut Context<Self>,
     ) -> Self {
         debug_adapter_extension::init(proxy.clone(), cx);
-        languages::init(languages.clone(), node_runtime.clone(), cx);
+        languages::init(languages.clone(), fs.clone(), node_runtime.clone(), cx);
 
         let worktree_store = cx.new(|cx| {
             let mut store = WorktreeStore::local(true, fs.clone());
@@ -153,7 +153,6 @@ impl HeadlessProject {
 
         let task_store = cx.new(|cx| {
             let mut task_store = TaskStore::local(
-                fs.clone(),
                 buffer_store.downgrade(),
                 worktree_store.clone(),
                 toolchain_store.read(cx).as_language_toolchain_store(),

crates/zed/src/main.rs 🔗

@@ -460,7 +460,7 @@ pub fn main() {
 
         debug_adapter_extension::init(extension_host_proxy.clone(), cx);
         language::init(cx);
-        languages::init(languages.clone(), node_runtime.clone(), cx);
+        languages::init(languages.clone(), fs.clone(), node_runtime.clone(), cx);
         let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
         let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
 

crates/zed/src/zed.rs 🔗

@@ -4589,6 +4589,7 @@ mod tests {
 
     #[gpui::test]
     async fn test_bundled_languages(cx: &mut TestAppContext) {
+        let fs = fs::FakeFs::new(cx.background_executor.clone());
         env_logger::builder().is_test(true).try_init().ok();
         let settings = cx.update(SettingsStore::test);
         cx.set_global(settings);
@@ -4596,7 +4597,7 @@ mod tests {
         let languages = Arc::new(languages);
         let node_runtime = node_runtime::NodeRuntime::unavailable();
         cx.update(|cx| {
-            languages::init(languages.clone(), node_runtime, cx);
+            languages::init(languages.clone(), fs, node_runtime, cx);
         });
         for name in languages.language_names() {
             languages

crates/zeta_cli/src/headless.rs 🔗

@@ -110,7 +110,7 @@ pub fn init(cx: &mut App) -> ZetaCliAppState {
     language_extension::init(LspAccess::Noop, extension_host_proxy, languages.clone());
     language_model::init(client.clone(), cx);
     language_models::init(user_store.clone(), client.clone(), cx);
-    languages::init(languages.clone(), node_runtime.clone(), cx);
+    languages::init(languages.clone(), fs.clone(), node_runtime.clone(), cx);
     prompt_store::init(cx);
     terminal_view::init(cx);