1use crate::Location;
2
3use anyhow::Result;
4use gpui::AppContext;
5use task::{static_source::TaskDefinitions, TaskVariables, VariableName};
6
7/// Language Contexts are used by Zed tasks to extract information about source file.
8pub trait ContextProvider: Send + Sync {
9 fn build_context(&self, _: Location, _: &mut AppContext) -> Result<TaskVariables> {
10 Ok(TaskVariables::default())
11 }
12
13 fn associated_tasks(&self) -> Option<TaskDefinitions> {
14 None
15 }
16}
17
18/// A context provider that finds out what symbol is currently focused in the buffer.
19pub struct SymbolContextProvider;
20
21impl ContextProvider for SymbolContextProvider {
22 fn build_context(
23 &self,
24 location: Location,
25 cx: &mut AppContext,
26 ) -> gpui::Result<TaskVariables> {
27 let symbols = location
28 .buffer
29 .read(cx)
30 .snapshot()
31 .symbols_containing(location.range.start, None);
32 let symbol = symbols.unwrap_or_default().last().map(|symbol| {
33 let range = symbol
34 .name_ranges
35 .last()
36 .cloned()
37 .unwrap_or(0..symbol.text.len());
38 symbol.text[range].to_string()
39 });
40 Ok(TaskVariables::from_iter(
41 Some(VariableName::Symbol).zip(symbol),
42 ))
43 }
44}
45
46/// A ContextProvider that doesn't provide any task variables on it's own, though it has some associated tasks.
47pub struct ContextProviderWithTasks {
48 definitions: TaskDefinitions,
49}
50
51impl ContextProviderWithTasks {
52 pub fn new(definitions: TaskDefinitions) -> Self {
53 Self { definitions }
54 }
55}
56
57impl ContextProvider for ContextProviderWithTasks {
58 fn associated_tasks(&self) -> Option<TaskDefinitions> {
59 Some(self.definitions.clone())
60 }
61
62 fn build_context(&self, location: Location, cx: &mut AppContext) -> Result<TaskVariables> {
63 SymbolContextProvider.build_context(location, cx)
64 }
65}