Sets up infra for fixing #46881. Follow-up to the approach discussed in #36802 (comment). The initial problem: Go table tests weren't being detected reliably in larger files. The old approach created one tree-sitter match per table row, which hit the cursor match limit (64) and caused rows to be silently dropped. The suggested fix was to use query repetition to capture all rows in a single match, then post-process in Rust. But this hit another problem: some captured rows aren't valid runnables (e.g., when a struct has multiple string fields and the query can't tell which one is the test name). Tree-sitter predicates can't validate subsets of captures within a match, that logic needs to happen in Rust. This PR adds a `RunnableResolver` trait that lets languages post-process multi-capture matches. When a query uses `@_run_item` to mark item boundaries, we split the captures into per-item groups and pass them to the resolver. The resolver can then: - Pick which `@run` to use: e.g., compare field names against `t.Run(tc.name, ...)` to find the right string field. - Return per-item extras: only the captures that correspond to the chosen `@run`. Release Notes: - N/A
54 lines
2.1 KiB
Rust
54 lines
2.1 KiB
Rust
use std::{path::PathBuf, sync::Arc};
|
|
|
|
use crate::{Buffer, LanguageToolchainStore, Location, RunnableResolver};
|
|
|
|
use anyhow::Result;
|
|
use collections::HashMap;
|
|
use fs::Fs;
|
|
use gpui::{App, Entity, Task};
|
|
use lsp::LanguageServerName;
|
|
use task::{TaskTemplates, TaskVariables};
|
|
|
|
/// Language Contexts are used by Zed tasks to extract information about the source file where the tasks are supposed to be scheduled from.
|
|
/// Multiple context providers may be used together: by default, Zed provides a base [`BasicContextProvider`] context that fills all non-custom [`VariableName`] variants.
|
|
///
|
|
/// The context will be used to fill data for the tasks, and filter out the ones that do not have the variables required.
|
|
pub trait ContextProvider: Send + Sync {
|
|
/// Builds a specific context to be placed on top of the basic one (replacing all conflicting entries) and to be used for task resolving later.
|
|
fn build_context(
|
|
&self,
|
|
_variables: &TaskVariables,
|
|
_location: ContextLocation<'_>,
|
|
_project_env: Option<HashMap<String, String>>,
|
|
_toolchains: Arc<dyn LanguageToolchainStore>,
|
|
_cx: &mut App,
|
|
) -> Task<Result<TaskVariables>> {
|
|
let _ = _location;
|
|
Task::ready(Ok(TaskVariables::default()))
|
|
}
|
|
|
|
/// Provides all tasks, associated with the current language.
|
|
fn associated_tasks(&self, _: Option<Entity<Buffer>>, _: &App) -> Task<Option<TaskTemplates>> {
|
|
Task::ready(None)
|
|
}
|
|
|
|
/// A language server name, that can return tasks using LSP (ext) for this language.
|
|
fn lsp_task_source(&self) -> Option<LanguageServerName> {
|
|
None
|
|
}
|
|
|
|
/// A resolver for runnable queries that group captures with `@run_item`.
|
|
/// For each group, the resolver picks which `@run` range and extra captures
|
|
/// to surface. Without a resolver, grouped matches emit no runnables.
|
|
fn runnable_resolver(&self) -> Option<Arc<dyn RunnableResolver>> {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Metadata about the place in the project we gather the context for.
|
|
pub struct ContextLocation<'a> {
|
|
pub fs: Option<Arc<dyn Fs>>,
|
|
pub worktree_root: Option<PathBuf>,
|
|
pub file_location: &'a Location,
|
|
}
|