Compare commits
4 Commits
agent-past
...
language-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
217fc298ed | ||
|
|
cf304df0dc | ||
|
|
7b8463b566 | ||
|
|
241a73df54 |
@@ -15,6 +15,7 @@ mod outline;
|
||||
pub mod proto;
|
||||
mod syntax_map;
|
||||
mod task_context;
|
||||
mod toolchain;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod buffer_tests;
|
||||
@@ -61,6 +62,7 @@ use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
|
||||
use task::RunnableTag;
|
||||
pub use task_context::{ContextProvider, RunnableRange};
|
||||
use theme::SyntaxTheme;
|
||||
pub use toolchain::{Toolchain, ToolchainList, ToolchainLister};
|
||||
use tree_sitter::{self, wasmtime, Query, QueryCursor, WasmStore};
|
||||
use util::serde::default_true;
|
||||
|
||||
|
||||
32
crates/language/src/toolchain.rs
Normal file
32
crates/language/src/toolchain.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
//! Provides support for language toolchains.
|
||||
//!
|
||||
//! A language can have associated toolchains,
|
||||
//! which is a set of tools used to interact with the projects written in said language.
|
||||
//! For example, a Python project can have an associated virtual environment; a Rust project can have a toolchain override.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gpui::SharedString;
|
||||
|
||||
/// Represents a single toolchain.
|
||||
pub struct Toolchain {
|
||||
/// User-facing label
|
||||
pub label: SharedString,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ToolchainLister {
|
||||
async fn list(&self) -> ToolchainList;
|
||||
async fn activate(&self, _: Toolchain);
|
||||
}
|
||||
|
||||
type DefaultIndex = usize;
|
||||
pub struct ToolchainList {
|
||||
toolchains: Vec<Toolchain>,
|
||||
default: Option<DefaultIndex>,
|
||||
}
|
||||
|
||||
impl ToolchainList {
|
||||
pub fn toolchains(&self) -> &[Toolchain] {
|
||||
&self.toolchains
|
||||
}
|
||||
}
|
||||
@@ -405,6 +405,7 @@ fn adjust_runs(
|
||||
runs
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct GoContextProvider;
|
||||
|
||||
const GO_PACKAGE_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_PACKAGE"));
|
||||
|
||||
@@ -30,6 +30,121 @@ mod yaml;
|
||||
#[exclude = "*.rs"]
|
||||
struct LanguageDir;
|
||||
|
||||
mod dsl {
|
||||
use std::sync::Arc;
|
||||
|
||||
use language::{ContextProvider, LanguageRegistry, LspAdapter};
|
||||
|
||||
use crate::{load_config, load_queries};
|
||||
|
||||
pub(super) struct LanguageBootstrapRecipe<'a> {
|
||||
name: &'static str,
|
||||
adapters: &'a [Arc<dyn LspAdapter>],
|
||||
context_provider: Option<Box<dyn Fn() -> Arc<dyn ContextProvider> + 'static + Send + Sync>>,
|
||||
}
|
||||
impl From<&'static str> for LanguageBootstrapRecipe<'static> {
|
||||
fn from(name: &'static str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
adapters: &[],
|
||||
context_provider: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const ADAPTER_COUNT: usize>
|
||||
From<(&'static str, &'a [Arc<dyn LspAdapter>; ADAPTER_COUNT])>
|
||||
for LanguageBootstrapRecipe<'a>
|
||||
{
|
||||
fn from(value: (&'static str, &'a [Arc<dyn LspAdapter>; ADAPTER_COUNT])) -> Self {
|
||||
Self {
|
||||
name: value.0,
|
||||
adapters: value.1.as_ref(),
|
||||
context_provider: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<
|
||||
'a,
|
||||
const ADAPTER_COUNT: usize,
|
||||
T: ContextProvider + 'static,
|
||||
Callback: Fn() -> T + 'static + Send + Sync,
|
||||
>
|
||||
From<(
|
||||
&'static str,
|
||||
&'a [Arc<dyn LspAdapter>; ADAPTER_COUNT],
|
||||
Callback,
|
||||
)> for LanguageBootstrapRecipe<'a>
|
||||
{
|
||||
fn from(
|
||||
value: (
|
||||
&'static str,
|
||||
&'a [Arc<dyn LspAdapter>; ADAPTER_COUNT],
|
||||
Callback,
|
||||
),
|
||||
) -> Self {
|
||||
Self {
|
||||
name: value.0,
|
||||
adapters: value.1.as_ref(),
|
||||
context_provider: Some(Box::new(move || Arc::new((value.2)()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: ContextProvider + 'static, Callback: Fn() -> T + 'static + Send + Sync>
|
||||
From<(&'static str, Callback)> for LanguageBootstrapRecipe<'static>
|
||||
{
|
||||
fn from(value: (&'static str, Callback)) -> Self {
|
||||
Self {
|
||||
name: value.0,
|
||||
adapters: &[],
|
||||
context_provider: Some(Box::new(move || Arc::new((value.1)()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn language<'a>(
|
||||
languages: &LanguageRegistry,
|
||||
config: impl Into<LanguageBootstrapRecipe<'a>>,
|
||||
) {
|
||||
let config = config.into();
|
||||
language_impl(languages, config)
|
||||
}
|
||||
fn language_impl<'a>(
|
||||
languages: &LanguageRegistry,
|
||||
bootstrap_config: LanguageBootstrapRecipe<'a>,
|
||||
) {
|
||||
let config = load_config(bootstrap_config.name);
|
||||
for adapter in bootstrap_config.adapters {
|
||||
languages.register_lsp_adapter(config.name.clone(), adapter.clone());
|
||||
}
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
move || {
|
||||
let context_provider = if let Some(factory) = &bootstrap_config.context_provider {
|
||||
Some(factory())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok((
|
||||
config.clone(),
|
||||
load_queries(bootstrap_config.name),
|
||||
context_provider,
|
||||
))
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
type Adapter = Arc<dyn LspAdapter>;
|
||||
trait DynAdapter {
|
||||
fn create<T: LspAdapter>(inner: T) -> Adapter;
|
||||
}
|
||||
impl DynAdapter for Adapter {
|
||||
fn create<T: LspAdapter>(inner: T) -> Adapter {
|
||||
Arc::new(inner)
|
||||
}
|
||||
}
|
||||
pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mut AppContext) {
|
||||
#[cfg(feature = "load-grammars")]
|
||||
languages.register_native_grammars([
|
||||
@@ -55,134 +170,107 @@ pub fn init(languages: Arc<LanguageRegistry>, node_runtime: NodeRuntime, cx: &mu
|
||||
]);
|
||||
|
||||
macro_rules! language {
|
||||
($name:literal) => {
|
||||
let config = load_config($name);
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
move || Ok((config.clone(), load_queries($name), None)),
|
||||
);
|
||||
};
|
||||
($name:literal, $adapters:expr) => {
|
||||
let config = load_config($name);
|
||||
// typeck helper
|
||||
let adapters: Vec<Arc<dyn LspAdapter>> = $adapters;
|
||||
for adapter in adapters {
|
||||
languages.register_lsp_adapter(config.name.clone(), adapter);
|
||||
}
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
move || Ok((config.clone(), load_queries($name), None)),
|
||||
);
|
||||
};
|
||||
($name:literal, $adapters:expr, $context_provider:expr) => {
|
||||
let config = load_config($name);
|
||||
// typeck helper
|
||||
let adapters: Vec<Arc<dyn LspAdapter>> = $adapters;
|
||||
for adapter in adapters {
|
||||
languages.register_lsp_adapter(config.name.clone(), adapter);
|
||||
}
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
move || {
|
||||
Ok((
|
||||
config.clone(),
|
||||
load_queries($name),
|
||||
Some(Arc::new($context_provider)),
|
||||
))
|
||||
},
|
||||
);
|
||||
};
|
||||
($($arg:expr), *) => {
|
||||
dsl::language(&languages, ($($arg), *))
|
||||
}
|
||||
|
||||
}
|
||||
language!("bash", Vec::new(), bash_task_context());
|
||||
language!("c", vec![Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>]);
|
||||
language!("cpp", vec![Arc::new(c::CLspAdapter)]);
|
||||
language!("bash", bash_task_context);
|
||||
language!("c", &[Adapter::create(c::CLspAdapter)]);
|
||||
language!("cpp", &[Adapter::create(c::CLspAdapter)]);
|
||||
language!(
|
||||
"css",
|
||||
vec![Arc::new(css::CssLspAdapter::new(node_runtime.clone())),]
|
||||
&[Adapter::create(css::CssLspAdapter::new(
|
||||
node_runtime.clone()
|
||||
)),]
|
||||
);
|
||||
language!("diff");
|
||||
language!("go", vec![Arc::new(go::GoLspAdapter)], GoContextProvider);
|
||||
language!("gomod", vec![Arc::new(go::GoLspAdapter)], GoContextProvider);
|
||||
language!(
|
||||
"go",
|
||||
&[Adapter::create(go::GoLspAdapter)],
|
||||
GoContextProvider::default
|
||||
);
|
||||
language!(
|
||||
"gomod",
|
||||
&[Adapter::create(go::GoLspAdapter)],
|
||||
GoContextProvider::default
|
||||
);
|
||||
language!(
|
||||
"gowork",
|
||||
vec![Arc::new(go::GoLspAdapter)],
|
||||
GoContextProvider
|
||||
&[Adapter::create(go::GoLspAdapter)],
|
||||
GoContextProvider::default
|
||||
);
|
||||
|
||||
language!(
|
||||
"json",
|
||||
vec![
|
||||
Arc::new(json::JsonLspAdapter::new(
|
||||
&[
|
||||
Adapter::create(json::JsonLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
languages.clone(),
|
||||
)),
|
||||
Arc::new(json::NodeVersionAdapter)
|
||||
Adapter::create(json::NodeVersionAdapter)
|
||||
],
|
||||
json_task_context()
|
||||
json_task_context
|
||||
);
|
||||
language!(
|
||||
"jsonc",
|
||||
vec![Arc::new(json::JsonLspAdapter::new(
|
||||
&[Adapter::create(json::JsonLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
languages.clone(),
|
||||
))],
|
||||
json_task_context()
|
||||
json_task_context
|
||||
);
|
||||
language!("markdown");
|
||||
language!("markdown-inline");
|
||||
language!(
|
||||
"python",
|
||||
vec![Arc::new(python::PythonLspAdapter::new(
|
||||
&[Adapter::create(python::PythonLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
))],
|
||||
PythonContextProvider
|
||||
PythonContextProvider::default
|
||||
);
|
||||
language!(
|
||||
"rust",
|
||||
vec![Arc::new(rust::RustLspAdapter)],
|
||||
RustContextProvider
|
||||
&[Adapter::create(rust::RustLspAdapter)],
|
||||
RustContextProvider::default
|
||||
);
|
||||
language!(
|
||||
"tsx",
|
||||
vec![
|
||||
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
&[
|
||||
Adapter::create(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Adapter::create(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
],
|
||||
typescript_task_context()
|
||||
typescript_task_context
|
||||
);
|
||||
language!(
|
||||
"typescript",
|
||||
vec![
|
||||
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
&[
|
||||
Adapter::create(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Adapter::create(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
],
|
||||
typescript_task_context()
|
||||
typescript_task_context
|
||||
);
|
||||
language!(
|
||||
"javascript",
|
||||
vec![
|
||||
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
&[
|
||||
Adapter::create(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
|
||||
Adapter::create(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
],
|
||||
typescript_task_context()
|
||||
typescript_task_context
|
||||
);
|
||||
language!(
|
||||
"jsdoc",
|
||||
vec![
|
||||
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone(),)),
|
||||
Arc::new(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
&[
|
||||
Adapter::create(typescript::TypeScriptLspAdapter::new(node_runtime.clone(),)),
|
||||
Adapter::create(vtsls::VtslsLspAdapter::new(node_runtime.clone()))
|
||||
]
|
||||
);
|
||||
language!("regex");
|
||||
language!(
|
||||
"yaml",
|
||||
vec![Arc::new(yaml::YamlLspAdapter::new(node_runtime.clone()))]
|
||||
&[Adapter::create(yaml::YamlLspAdapter::new(
|
||||
node_runtime.clone()
|
||||
))]
|
||||
);
|
||||
|
||||
// Register globally available language servers.
|
||||
|
||||
@@ -227,6 +227,7 @@ async fn get_cached_server_binary(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct PythonContextProvider;
|
||||
|
||||
const PYTHON_UNITTEST_TARGET_TASK_VARIABLE: VariableName =
|
||||
|
||||
@@ -362,6 +362,7 @@ impl LspAdapter for RustLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct RustContextProvider;
|
||||
|
||||
const RUST_PACKAGE_TASK_VARIABLE: VariableName =
|
||||
|
||||
Reference in New Issue
Block a user