Eliminate unnecessary macros in languages crate (#26813)
I vibe coded this in Zed, dawg. This avoids a number of cases where we created multiple copies of the same lsp adapter. Now we clone the Arcs. Release Notes: - N/A
This commit is contained in:
parent
a0ee84d3ac
commit
52567f4b72
1 changed files with 187 additions and 205 deletions
|
@ -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
|
||||
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()));
|
||||
|
||||
macro_rules! context_provider {
|
||||
($name:expr) => {
|
||||
Some(Arc::new($name) as Arc<dyn ContextProvider>)
|
||||
};
|
||||
() => {
|
||||
None
|
||||
};
|
||||
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()
|
||||
},
|
||||
];
|
||||
|
||||
for registration in built_in_languages {
|
||||
register_language(
|
||||
&languages,
|
||||
registration.name,
|
||||
registration.adapters,
|
||||
registration.context,
|
||||
registration.toolchain,
|
||||
);
|
||||
}
|
||||
|
||||
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![]
|
||||
};
|
||||
}
|
||||
|
||||
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!())
|
||||
};
|
||||
}
|
||||
|
||||
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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue