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 anyhow::Context as _;
|
||||||
use gpui::{App, UpdateGlobal};
|
use gpui::{App, UpdateGlobal};
|
||||||
use json::json_task_context;
|
use json::json_task_context;
|
||||||
pub use language::*;
|
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use python::{PythonContextProvider, PythonToolchainProvider};
|
|
||||||
use rust_embed::RustEmbed;
|
use rust_embed::RustEmbed;
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
use smol::stream::StreamExt;
|
use smol::stream::StreamExt;
|
||||||
use std::{str, sync::Arc};
|
use std::{str, sync::Arc};
|
||||||
use typescript::typescript_task_context;
|
|
||||||
use util::{asset_str, ResultExt};
|
use util::{asset_str, ResultExt};
|
||||||
|
|
||||||
use crate::{bash::bash_task_context, rust::RustContextProvider};
|
pub use language::*;
|
||||||
|
|
||||||
mod bash;
|
mod bash;
|
||||||
mod c;
|
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")]
|
#[cfg(feature = "load-grammars")]
|
||||||
languages.register_native_grammars([
|
languages.register_native_grammars([
|
||||||
("bash", tree_sitter_bash::LANGUAGE),
|
("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),
|
("gitcommit", tree_sitter_gitcommit::LANGUAGE),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Following are a series of helper macros for registering languages.
|
let c_lsp_adapter = Arc::new(c::CLspAdapter);
|
||||||
// Macros are used instead of a function or for loop in order to avoid
|
let css_lsp_adapter = Arc::new(css::CssLspAdapter::new(node.clone()));
|
||||||
// code duplication and improve readability as the types get quite verbose
|
let eslint_adapter = Arc::new(typescript::EsLintLspAdapter::new(node.clone()));
|
||||||
// to type out in some cases.
|
let go_context_provider = Arc::new(go::GoContextProvider);
|
||||||
// Additionally, the `provider` fields in LoadedLanguage
|
let go_lsp_adapter = Arc::new(go::GoLspAdapter);
|
||||||
// would have be `Copy` if we were to use a function or for-loop to register the languages
|
let json_context_provider = Arc::new(json_task_context());
|
||||||
// due to the fact that we pass an `Arc<Fn>` to `languages.register_language`
|
let json_lsp_adapter = Arc::new(json::JsonLspAdapter::new(node.clone(), languages.clone()));
|
||||||
// that loads and initializes the language lazily.
|
let node_version_lsp_adapter = Arc::new(json::NodeVersionAdapter);
|
||||||
// We avoid this entirely by using a Macro
|
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 {
|
let built_in_languages = [
|
||||||
($name:expr) => {
|
LanguageInfo {
|
||||||
Some(Arc::new($name) as Arc<dyn ContextProvider>)
|
name: "bash",
|
||||||
};
|
context: Some(Arc::new(bash::bash_task_context())),
|
||||||
() => {
|
..Default::default()
|
||||||
None
|
},
|
||||||
};
|
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.
|
// Register globally available language servers.
|
||||||
//
|
//
|
||||||
// This will allow users to add support for a built-in language server (e.g., Tailwind)
|
// 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(
|
languages.register_available_lsp_adapter(
|
||||||
LanguageServerName("tailwindcss-language-server".into()),
|
LanguageServerName("tailwindcss-language-server".into()),
|
||||||
{
|
{
|
||||||
let node_runtime = node_runtime.clone();
|
let adapter = tailwind_adapter.clone();
|
||||||
move || Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone()))
|
move || adapter.clone()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
languages.register_available_lsp_adapter(LanguageServerName("eslint".into()), {
|
languages.register_available_lsp_adapter(LanguageServerName("eslint".into()), {
|
||||||
let node_runtime = node_runtime.clone();
|
let adapter = eslint_adapter.clone();
|
||||||
move || Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone()))
|
move || adapter.clone()
|
||||||
});
|
});
|
||||||
languages.register_available_lsp_adapter(LanguageServerName("vtsls".into()), {
|
languages.register_available_lsp_adapter(LanguageServerName("vtsls".into()), {
|
||||||
let node_runtime = node_runtime.clone();
|
let adapter = vtsls_adapter.clone();
|
||||||
move || Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
move || adapter.clone()
|
||||||
});
|
});
|
||||||
languages.register_available_lsp_adapter(
|
languages.register_available_lsp_adapter(
|
||||||
LanguageServerName("typescript-language-server".into()),
|
LanguageServerName("typescript-language-server".into()),
|
||||||
{
|
{
|
||||||
let node_runtime = node_runtime.clone();
|
let adapter = typescript_lsp_adapter.clone();
|
||||||
move || Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone()))
|
move || adapter.clone()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -316,18 +269,12 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
|
||||||
];
|
];
|
||||||
|
|
||||||
for language in tailwind_languages {
|
for language in tailwind_languages {
|
||||||
languages.register_lsp_adapter(
|
languages.register_lsp_adapter(language.into(), tailwind_adapter.clone());
|
||||||
language.into(),
|
|
||||||
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let eslint_languages = ["TSX", "TypeScript", "JavaScript", "Vue.js", "Svelte"];
|
let eslint_languages = ["TSX", "TypeScript", "JavaScript", "Vue.js", "Svelte"];
|
||||||
for language in eslint_languages {
|
for language in eslint_languages {
|
||||||
languages.register_lsp_adapter(
|
languages.register_lsp_adapter(language.into(), eslint_adapter.clone());
|
||||||
language.into(),
|
|
||||||
Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone())),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut subscription = languages.subscribe();
|
let mut subscription = languages.subscribe();
|
||||||
|
@ -352,6 +299,41 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
|
||||||
.detach();
|
.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"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn language(name: &str, grammar: tree_sitter::Language) -> Arc<Language> {
|
pub fn language(name: &str, grammar: tree_sitter::Language) -> Arc<Language> {
|
||||||
Arc::new(
|
Arc::new(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue