task_context.rs

  1use crate::{LanguageRegistry, Location};
  2
  3use anyhow::Result;
  4use gpui::{AppContext, Context, Model};
  5use std::sync::Arc;
  6use task::{
  7    static_source::{tasks_for, TaskDefinitions},
  8    TaskSource, TaskVariables, VariableName,
  9};
 10
 11/// Language Contexts are used by Zed tasks to extract information about source file.
 12pub trait ContextProvider: Send + Sync {
 13    fn build_context(&self, _: Location, _: &mut AppContext) -> Result<TaskVariables> {
 14        Ok(TaskVariables::default())
 15    }
 16
 17    fn associated_tasks(&self) -> Option<TaskDefinitions> {
 18        None
 19    }
 20}
 21
 22/// A context provider that finds out what symbol is currently focused in the buffer.
 23pub struct SymbolContextProvider;
 24
 25impl ContextProvider for SymbolContextProvider {
 26    fn build_context(
 27        &self,
 28        location: Location,
 29        cx: &mut AppContext,
 30    ) -> gpui::Result<TaskVariables> {
 31        let symbols = location
 32            .buffer
 33            .read(cx)
 34            .snapshot()
 35            .symbols_containing(location.range.start, None);
 36        let symbol = symbols.unwrap_or_default().last().map(|symbol| {
 37            let range = symbol
 38                .name_ranges
 39                .last()
 40                .cloned()
 41                .unwrap_or(0..symbol.text.len());
 42            symbol.text[range].to_string()
 43        });
 44        Ok(TaskVariables::from_iter(
 45            Some(VariableName::Symbol).zip(symbol),
 46        ))
 47    }
 48}
 49
 50/// A ContextProvider that doesn't provide any task variables on it's own, though it has some associated tasks.
 51pub struct ContextProviderWithTasks {
 52    definitions: TaskDefinitions,
 53}
 54
 55impl ContextProviderWithTasks {
 56    pub fn new(definitions: TaskDefinitions) -> Self {
 57        Self { definitions }
 58    }
 59}
 60
 61impl ContextProvider for ContextProviderWithTasks {
 62    fn associated_tasks(&self) -> Option<TaskDefinitions> {
 63        Some(self.definitions.clone())
 64    }
 65
 66    fn build_context(&self, location: Location, cx: &mut AppContext) -> Result<TaskVariables> {
 67        SymbolContextProvider.build_context(location, cx)
 68    }
 69}
 70
 71/// A source that pulls in the tasks from language registry.
 72pub struct LanguageSource {
 73    languages: Arc<LanguageRegistry>,
 74}
 75
 76impl LanguageSource {
 77    pub fn new(
 78        languages: Arc<LanguageRegistry>,
 79        cx: &mut AppContext,
 80    ) -> Model<Box<dyn TaskSource>> {
 81        cx.new_model(|_| Box::new(Self { languages }) as Box<_>)
 82    }
 83}
 84
 85impl TaskSource for LanguageSource {
 86    fn as_any(&mut self) -> &mut dyn std::any::Any {
 87        self
 88    }
 89
 90    fn tasks_for_path(
 91        &mut self,
 92        _: Option<&std::path::Path>,
 93        _: &mut gpui::ModelContext<Box<dyn TaskSource>>,
 94    ) -> Vec<Arc<dyn task::Task>> {
 95        self.languages
 96            .to_vec()
 97            .into_iter()
 98            .filter_map(|language| {
 99                language
100                    .context_provider()?
101                    .associated_tasks()
102                    .map(|tasks| (tasks, language))
103            })
104            .flat_map(|(tasks, language)| {
105                let language_name = language.name();
106                let id_base = format!("buffer_source_{language_name}");
107                tasks_for(tasks, &id_base)
108            })
109            .collect()
110    }
111}