@@ -1,17 +1,14 @@
use anyhow::Context as _;
use gpui::{App, UpdateGlobal};
use json::json_task_context;
-pub use language::*;
use node_runtime::NodeRuntime;
-use python::{PythonContextProvider, PythonToolchainProvider};
use rust_embed::RustEmbed;
use settings::SettingsStore;
use smol::stream::StreamExt;
use std::{str, sync::Arc};
-use typescript::typescript_task_context;
use util::{asset_str, ResultExt};
-use crate::{bash::bash_task_context, rust::RustContextProvider};
+pub use language::*;
mod bash;
mod c;
@@ -49,7 +46,7 @@ pub static LANGUAGE_GIT_COMMIT: std::sync::LazyLock<Arc<Language>> =
))
});
-pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mut App) {
+pub fn init(languages: Arc<LanguageRegistry>, node: NodeRuntime, cx: &mut App) {
#[cfg(feature = "load-grammars")]
languages.register_native_grammars([
("bash", tree_sitter_bash::LANGUAGE),
@@ -74,193 +71,149 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
("gitcommit", tree_sitter_gitcommit::LANGUAGE),
]);
- // Following are a series of helper macros for registering languages.
- // Macros are used instead of a function or for loop in order to avoid
- // code duplication and improve readability as the types get quite verbose
- // to type out in some cases.
- // Additionally, the `provider` fields in LoadedLanguage
- // would have be `Copy` if we were to use a function or for-loop to register the languages
- // due to the fact that we pass an `Arc<Fn>` to `languages.register_language`
- // that loads and initializes the language lazily.
- // We avoid this entirely by using a Macro
-
- macro_rules! context_provider {
- ($name:expr) => {
- Some(Arc::new($name) as Arc<dyn ContextProvider>)
- };
- () => {
- None
- };
- }
-
- macro_rules! toolchain_provider {
- ($name:expr) => {
- Some(Arc::new($name) as Arc<dyn ToolchainLister>)
- };
- () => {
- None
- };
- }
-
- macro_rules! adapters {
- ($($item:expr),+ $(,)?) => {
- vec![
- $(Arc::new($item) as Arc<dyn LspAdapter>,)*
- ]
- };
- () => {
- vec![]
- };
- }
+ let c_lsp_adapter = Arc::new(c::CLspAdapter);
+ let css_lsp_adapter = Arc::new(css::CssLspAdapter::new(node.clone()));
+ let eslint_adapter = Arc::new(typescript::EsLintLspAdapter::new(node.clone()));
+ let go_context_provider = Arc::new(go::GoContextProvider);
+ let go_lsp_adapter = Arc::new(go::GoLspAdapter);
+ let json_context_provider = Arc::new(json_task_context());
+ let json_lsp_adapter = Arc::new(json::JsonLspAdapter::new(node.clone(), languages.clone()));
+ let node_version_lsp_adapter = Arc::new(json::NodeVersionAdapter);
+ let py_lsp_adapter = Arc::new(python::PyLspAdapter::new());
+ let python_context_provider = Arc::new(python::PythonContextProvider);
+ let python_lsp_adapter = Arc::new(python::PythonLspAdapter::new(node.clone()));
+ let python_toolchain_provider = Arc::new(python::PythonToolchainProvider::default());
+ 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::typescript_task_context());
+ let typescript_lsp_adapter = Arc::new(typescript::TypeScriptLspAdapter::new(node.clone()));
+ let vtsls_adapter = Arc::new(vtsls::VtslsLspAdapter::new(node.clone()));
+ let yaml_lsp_adapter = Arc::new(yaml::YamlLspAdapter::new(node.clone()));
+
+ let built_in_languages = [
+ LanguageInfo {
+ name: "bash",
+ context: Some(Arc::new(bash::bash_task_context())),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "c",
+ adapters: vec![c_lsp_adapter.clone()],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "cpp",
+ adapters: vec![c_lsp_adapter.clone()],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "css",
+ adapters: vec![css_lsp_adapter.clone()],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "diff",
+ adapters: vec![],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "go",
+ adapters: vec![go_lsp_adapter.clone()],
+ context: Some(go_context_provider.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "gomod",
+ adapters: vec![go_lsp_adapter.clone()],
+ context: Some(go_context_provider.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "gowork",
+ adapters: vec![go_lsp_adapter.clone()],
+ context: Some(go_context_provider.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "json",
+ adapters: vec![json_lsp_adapter.clone(), node_version_lsp_adapter.clone()],
+ context: Some(json_context_provider.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "jsonc",
+ adapters: vec![json_lsp_adapter.clone()],
+ context: Some(json_context_provider.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "markdown",
+ adapters: vec![],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "markdown-inline",
+ adapters: vec![],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "python",
+ adapters: vec![python_lsp_adapter.clone(), py_lsp_adapter.clone()],
+ context: Some(python_context_provider),
+ toolchain: Some(python_toolchain_provider),
+ },
+ LanguageInfo {
+ name: "rust",
+ adapters: vec![rust_lsp_adapter],
+ context: Some(rust_context_provider),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "tsx",
+ adapters: vec![typescript_lsp_adapter.clone(), vtsls_adapter.clone()],
+ context: Some(typescript_context.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "typescript",
+ adapters: vec![typescript_lsp_adapter.clone(), vtsls_adapter.clone()],
+ context: Some(typescript_context.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "javascript",
+ adapters: vec![typescript_lsp_adapter.clone(), vtsls_adapter.clone()],
+ context: Some(typescript_context.clone()),
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "jsdoc",
+ adapters: vec![typescript_lsp_adapter.clone(), vtsls_adapter.clone()],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "regex",
+ adapters: vec![],
+ ..Default::default()
+ },
+ LanguageInfo {
+ name: "yaml",
+ adapters: vec![yaml_lsp_adapter],
+ ..Default::default()
+ },
+ ];
- macro_rules! register_language {
- ($name:expr, adapters => $adapters:expr, context => $context:expr, toolchain => $toolchain:expr) => {
- let config = load_config($name);
- for adapter in $adapters {
- languages.register_lsp_adapter(config.name.clone(), adapter);
- }
- languages.register_language(
- config.name.clone(),
- config.grammar.clone(),
- config.matcher.clone(),
- config.hidden,
- Arc::new(move || {
- Ok(LoadedLanguage {
- config: config.clone(),
- queries: load_queries($name),
- context_provider: $context,
- toolchain_provider: $toolchain,
- })
- }),
- );
- };
- ($name:expr) => {
- register_language!($name, adapters => adapters![], context => context_provider!(), toolchain => toolchain_provider!())
- };
- ($name:expr, adapters => $adapters:expr, context => $context:expr, toolchain => $toolchain:expr) => {
- register_language!($name, adapters => $adapters, context => $context, toolchain => $toolchain)
- };
- ($name:expr, adapters => $adapters:expr, context => $context:expr) => {
- register_language!($name, adapters => $adapters, context => $context, toolchain => toolchain_provider!())
- };
- ($name:expr, adapters => $adapters:expr) => {
- register_language!($name, adapters => $adapters, context => context_provider!(), toolchain => toolchain_provider!())
- };
+ for registration in built_in_languages {
+ register_language(
+ &languages,
+ registration.name,
+ registration.adapters,
+ registration.context,
+ registration.toolchain,
+ );
}
- register_language!(
- "bash",
- adapters => adapters![],
- context => context_provider!(bash_task_context()),
- toolchain => toolchain_provider!()
- );
-
- register_language!(
- "c",
- adapters => adapters![c::CLspAdapter]
- );
- register_language!(
- "cpp",
- adapters => adapters![c::CLspAdapter]
- );
-
- register_language!(
- "css",
- adapters => adapters![css::CssLspAdapter::new(node_runtime.clone())]
- );
-
- register_language!("diff");
-
- register_language!(
- "go",
- adapters => adapters![go::GoLspAdapter],
- context => context_provider!(go::GoContextProvider)
- );
- register_language!(
- "gomod",
- adapters => adapters![go::GoLspAdapter],
- context => context_provider!(go::GoContextProvider)
- );
- register_language!(
- "gowork",
- adapters => adapters![go::GoLspAdapter],
- context => context_provider!(go::GoContextProvider)
- );
-
- register_language!(
- "json",
- adapters => adapters![
- json::JsonLspAdapter::new(node_runtime.clone(), languages.clone(),),
- json::NodeVersionAdapter,
- ],
- context => context_provider!(json_task_context())
- );
- register_language!(
- "jsonc",
- adapters => adapters![
- json::JsonLspAdapter::new(node_runtime.clone(), languages.clone(),),
- ],
- context => context_provider!(json_task_context())
- );
-
- register_language!("markdown");
- register_language!("markdown-inline");
-
- register_language!(
- "python",
- adapters => adapters![
- python::PythonLspAdapter::new(node_runtime.clone()),
- python::PyLspAdapter::new()
- ],
- context => context_provider!(PythonContextProvider),
- toolchain => toolchain_provider!(PythonToolchainProvider::default())
- );
- register_language!(
- "rust",
- adapters => adapters![rust::RustLspAdapter],
- context => context_provider!(RustContextProvider)
- );
- register_language!(
- "tsx",
- adapters => adapters![
- typescript::TypeScriptLspAdapter::new(node_runtime.clone()),
- vtsls::VtslsLspAdapter::new(node_runtime.clone()),
- ],
- context => context_provider!(typescript_task_context()),
- toolchain => toolchain_provider!()
- );
- register_language!(
- "typescript",
- adapters => adapters![
- typescript::TypeScriptLspAdapter::new(node_runtime.clone()),
- vtsls::VtslsLspAdapter::new(node_runtime.clone()),
- ],
- context => context_provider!(typescript_task_context())
- );
- register_language!(
- "javascript",
- adapters => adapters![
- typescript::TypeScriptLspAdapter::new(node_runtime.clone()),
- vtsls::VtslsLspAdapter::new(node_runtime.clone()),
- ],
- context => context_provider!(typescript_task_context())
- );
- register_language!(
- "jsdoc",
- adapters => adapters![
- typescript::TypeScriptLspAdapter::new(node_runtime.clone()),
- vtsls::VtslsLspAdapter::new(node_runtime.clone()),
- ]
- );
-
- register_language!("regex");
-
- register_language!("yaml",
- adapters => adapters![
- yaml::YamlLspAdapter::new(node_runtime.clone()),
- ]
- );
-
// Register globally available language servers.
//
// This will allow users to add support for a built-in language server (e.g., Tailwind)
@@ -278,23 +231,23 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
languages.register_available_lsp_adapter(
LanguageServerName("tailwindcss-language-server".into()),
{
- let node_runtime = node_runtime.clone();
- move || Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone()))
+ let adapter = tailwind_adapter.clone();
+ move || adapter.clone()
},
);
languages.register_available_lsp_adapter(LanguageServerName("eslint".into()), {
- let node_runtime = node_runtime.clone();
- move || Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone()))
+ let adapter = eslint_adapter.clone();
+ move || adapter.clone()
});
languages.register_available_lsp_adapter(LanguageServerName("vtsls".into()), {
- let node_runtime = node_runtime.clone();
- move || Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
+ let adapter = vtsls_adapter.clone();
+ move || adapter.clone()
});
languages.register_available_lsp_adapter(
LanguageServerName("typescript-language-server".into()),
{
- let node_runtime = node_runtime.clone();
- move || Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone()))
+ let adapter = typescript_lsp_adapter.clone();
+ move || adapter.clone()
},
);
@@ -316,18 +269,12 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
];
for language in tailwind_languages {
- languages.register_lsp_adapter(
- language.into(),
- Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
- );
+ languages.register_lsp_adapter(language.into(), tailwind_adapter.clone());
}
let eslint_languages = ["TSX", "TypeScript", "JavaScript", "Vue.js", "Svelte"];
for language in eslint_languages {
- languages.register_lsp_adapter(
- language.into(),
- Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone())),
- );
+ languages.register_lsp_adapter(language.into(), eslint_adapter.clone());
}
let mut subscription = languages.subscribe();
@@ -352,6 +299,41 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
.detach();
}
+#[derive(Default)]
+struct LanguageInfo {
+ name: &'static str,
+ adapters: Vec<Arc<dyn LspAdapter>>,
+ context: Option<Arc<dyn ContextProvider>>,
+ toolchain: Option<Arc<dyn ToolchainLister>>,
+}
+
+fn register_language(
+ languages: &LanguageRegistry,
+ name: &'static str,
+ adapters: Vec<Arc<dyn LspAdapter>>,
+ context: Option<Arc<dyn ContextProvider>>,
+ toolchain: Option<Arc<dyn ToolchainLister>>,
+) {
+ let config = load_config(name);
+ for adapter in adapters {
+ languages.register_lsp_adapter(config.name.clone(), adapter);
+ }
+ languages.register_language(
+ config.name.clone(),
+ config.grammar.clone(),
+ config.matcher.clone(),
+ config.hidden,
+ Arc::new(move || {
+ Ok(LoadedLanguage {
+ config: config.clone(),
+ queries: load_queries(name),
+ context_provider: context.clone(),
+ toolchain_provider: toolchain.clone(),
+ })
+ }),
+ );
+}
+
#[cfg(any(test, feature = "test-support"))]
pub fn language(name: &str, grammar: tree_sitter::Language) -> Arc<Language> {
Arc::new(