Compare commits

...
Sign in to create a new pull request.

7 commits

Author SHA1 Message Date
Piotr Osiewicz
e0a20690fb Add LanguageTaskBuilder and move languages to macro-based declarations 2024-02-28 16:46:10 +01:00
Piotr Osiewicz
e9613e552a Merge branch 'main' into dynamic-runnables 2024-02-28 12:45:19 +01:00
Piotr Osiewicz
91b011a2c6 Add new lsp capabilities 2024-02-27 18:36:41 +01:00
Piotr Osiewicz
24677b11ed Merge branch 'main' into dynamic-runnables 2024-02-27 17:16:11 +01:00
Piotr Osiewicz
c70cb5a911 Progress on DocumentSymbol request 2024-02-27 17:15:58 +01:00
Piotr Osiewicz
b884658e49 Merge branch 'main' into dynamic-runnables 2024-02-27 12:47:03 +01:00
Piotr Osiewicz
f0f49db969 WIP: TestSource 2024-02-26 16:01:47 +01:00
17 changed files with 388 additions and 112 deletions

5
Cargo.lock generated
View file

@ -9101,6 +9101,7 @@ dependencies = [
"collections",
"futures 0.3.28",
"gpui",
"project_core",
"schemars",
"serde",
"serde_json_lenient",
@ -9112,11 +9113,15 @@ name = "tasks_ui"
version = "0.1.0"
dependencies = [
"anyhow",
"editor",
"fuzzy",
"gpui",
"language",
"lsp",
"menu",
"picker",
"project",
"project_core",
"serde",
"task",
"ui",

View file

@ -108,13 +108,32 @@ pub trait ToLspPosition {
/// A name of a language server.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct LanguageServerName(pub Arc<str>);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Location {
pub buffer: Model<Buffer>,
pub range: Range<Anchor>,
}
pub enum LanguageTaskKind {
RunFile,
TestAtLine,
TestFile,
TestPackage,
TestWorkspace,
}
pub struct LanguageTask {}
pub trait LanguageTaskBuilder: Sync + Send + 'static {
fn task_for(
&self,
kind: LanguageTaskKind,
buffer: Model<Buffer>,
path: &Path,
cx: &mut AppContext,
) -> Option<Task<LanguageTask>>;
}
/// Represents a Language Server, with certain cached sync properties.
/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
/// once at startup, and caches the results.
@ -656,6 +675,7 @@ pub struct Language {
pub(crate) grammar: Option<Arc<Grammar>>,
pub(crate) adapters: Vec<Arc<CachedLspAdapter>>,
pub(crate) task_builder: Option<Arc<dyn LanguageTaskBuilder>>,
#[cfg(any(test, feature = "test-support"))]
fake_adapter: Option<(
futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,
@ -779,6 +799,7 @@ impl Language {
#[cfg(any(test, feature = "test-support"))]
fake_adapter: None,
task_builder: None,
}
}

View file

@ -122,210 +122,236 @@ pub fn init(
("dart", tree_sitter_dart::language()),
]);
let language = |asset_dir_name: &'static str, adapters| {
let config = load_config(asset_dir_name);
// let language = |asset_dir_name: &'static str, adapters| {
// let config = load_config(asset_dir_name);
// languages.register_language(
// config.name.clone(),
// config.grammar.clone(),
// config.matcher.clone(),
// adapters,
// move || Ok((config.clone(), load_queries(asset_dir_name))),
// )
// };
macro_rules! language {
($name:literal) => {
let config = load_config($name);
languages.register_language(
config.name.clone(),
config.grammar.clone(),
config.matcher.clone(),
adapters,
move || Ok((config.clone(), load_queries(asset_dir_name))),
)
vec![],
move || Ok((config.clone(), load_queries($name))),
);
};
language(
($name:literal, $adapters:expr) => {
let config = load_config($name);
languages.register_language(
config.name.clone(),
config.grammar.clone(),
config.matcher.clone(),
$adapters,
move || Ok((config.clone(), load_queries($name))),
);
};
}
language!(
"astro",
vec![
Arc::new(astro::AstroLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language("bash", vec![]);
language("c", vec![Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>]);
language("clojure", vec![Arc::new(clojure::ClojureLspAdapter)]);
language("cpp", vec![Arc::new(c::CLspAdapter)]);
language("csharp", vec![Arc::new(csharp::OmniSharpAdapter {})]);
language(
language!("bash");
language!("c", vec![Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>]);
language!("clojure", vec![Arc::new(clojure::ClojureLspAdapter)]);
language!("cpp", vec![Arc::new(c::CLspAdapter)]);
language!("csharp", vec![Arc::new(csharp::OmniSharpAdapter {})]);
language!(
"css",
vec![
Arc::new(css::CssLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"dockerfile",
vec![Arc::new(dockerfile::DockerfileLspAdapter::new(
node_runtime.clone(),
))],
))]
);
match &ElixirSettings::get(None, cx).lsp {
elixir::ElixirLspSetting::ElixirLs => language(
elixir::ElixirLspSetting::ElixirLs => {
language!(
"elixir",
vec![
Arc::new(elixir::ElixirLspAdapter),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
),
elixir::ElixirLspSetting::NextLs => {
language("elixir", vec![Arc::new(elixir::NextLspAdapter)])
]
);
}
elixir::ElixirLspSetting::Local { path, arguments } => language(
elixir::ElixirLspSetting::NextLs => {
language!("elixir", vec![Arc::new(elixir::NextLspAdapter)]);
}
elixir::ElixirLspSetting::Local { path, arguments } => {
language!(
"elixir",
vec![Arc::new(elixir::LocalLspAdapter {
path: path.clone(),
arguments: arguments.clone(),
})],
),
})]
);
}
language("gitcommit", vec![]);
language("erlang", vec![Arc::new(erlang::ErlangLspAdapter)]);
}
language!("gitcommit");
language!("erlang", vec![Arc::new(erlang::ErlangLspAdapter)]);
language("gleam", vec![Arc::new(gleam::GleamLspAdapter)]);
language("go", vec![Arc::new(go::GoLspAdapter)]);
language("gomod", vec![]);
language("gowork", vec![]);
language("zig", vec![Arc::new(zig::ZlsAdapter)]);
language(
language!("gleam", vec![Arc::new(gleam::GleamLspAdapter)]);
language!("go", vec![Arc::new(go::GoLspAdapter)]);
language!("gomod");
language!("gowork");
language!("zig", vec![Arc::new(zig::ZlsAdapter)]);
language!(
"heex",
vec![
Arc::new(elixir::ElixirLspAdapter),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"json",
vec![Arc::new(json::JsonLspAdapter::new(
node_runtime.clone(),
languages.clone(),
))],
))]
);
language("markdown", vec![]);
language(
language!("markdown");
language!(
"python",
vec![Arc::new(python::PythonLspAdapter::new(
node_runtime.clone(),
))],
))]
);
language("rust", vec![Arc::new(rust::RustLspAdapter)]);
language("toml", vec![Arc::new(toml::TaploLspAdapter)]);
language!("rust", vec![Arc::new(rust::RustLspAdapter)]);
language!("toml", vec![Arc::new(toml::TaploLspAdapter)]);
match &DenoSettings::get(None, cx).enable {
true => {
language(
language!(
"tsx",
vec![
Arc::new(deno::DenoLspAdapter::new()),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language("typescript", vec![Arc::new(deno::DenoLspAdapter::new())]);
language(
language!("typescript", vec![Arc::new(deno::DenoLspAdapter::new())]);
language!(
"javascript",
vec![
Arc::new(deno::DenoLspAdapter::new()),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
}
false => {
language(
language!(
"tsx",
vec![
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"typescript",
vec![
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"javascript",
vec![
Arc::new(typescript::TypeScriptLspAdapter::new(node_runtime.clone())),
Arc::new(typescript::EsLintLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
}
}
language("haskell", vec![Arc::new(haskell::HaskellLanguageServer {})]);
language(
language!("haskell", vec![Arc::new(haskell::HaskellLanguageServer {})]);
language!(
"html",
vec![
Arc::new(html::HtmlLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language("ruby", vec![Arc::new(ruby::RubyLanguageServer)]);
language(
language!("ruby", vec![Arc::new(ruby::RubyLanguageServer)]);
language!(
"erb",
vec![
Arc::new(ruby::RubyLanguageServer),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language("scheme", vec![]);
language("racket", vec![]);
language("lua", vec![Arc::new(lua::LuaLspAdapter)]);
language(
language!("scheme");
language!("racket");
language!("lua", vec![Arc::new(lua::LuaLspAdapter)]);
language!(
"yaml",
vec![Arc::new(yaml::YamlLspAdapter::new(node_runtime.clone()))],
vec![Arc::new(yaml::YamlLspAdapter::new(node_runtime.clone()))]
);
language(
language!(
"svelte",
vec![
Arc::new(svelte::SvelteLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"php",
vec![
Arc::new(php::IntelephenseLspAdapter::new(node_runtime.clone())),
Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
],
]
);
language(
language!(
"purescript",
vec![Arc::new(purescript::PurescriptLspAdapter::new(
node_runtime.clone(),
))],
))]
);
language(
language!(
"elm",
vec![Arc::new(elm::ElmLspAdapter::new(node_runtime.clone()))],
vec![Arc::new(elm::ElmLspAdapter::new(node_runtime.clone()))]
);
language("glsl", vec![]);
language("nix", vec![]);
language("nu", vec![Arc::new(nu::NuLanguageServer {})]);
language("ocaml", vec![Arc::new(ocaml::OCamlLspAdapter)]);
language("ocaml-interface", vec![Arc::new(ocaml::OCamlLspAdapter)]);
language(
language!("glsl");
language!("nix");
language!("nu", vec![Arc::new(nu::NuLanguageServer {})]);
language!("ocaml", vec![Arc::new(ocaml::OCamlLspAdapter)]);
language!("ocaml-interface", vec![Arc::new(ocaml::OCamlLspAdapter)]);
language!(
"vue",
vec![Arc::new(vue::VueLspAdapter::new(node_runtime.clone()))],
vec![Arc::new(vue::VueLspAdapter::new(node_runtime.clone()))]
);
language("uiua", vec![Arc::new(uiua::UiuaLanguageServer {})]);
language("proto", vec![]);
language("terraform", vec![Arc::new(terraform::TerraformLspAdapter)]);
language(
language!("uiua", vec![Arc::new(uiua::UiuaLanguageServer {})]);
language!("proto");
language!("terraform", vec![Arc::new(terraform::TerraformLspAdapter)]);
language!(
"terraform-vars",
vec![Arc::new(terraform::TerraformLspAdapter)],
vec![Arc::new(terraform::TerraformLspAdapter)]
);
language("hcl", vec![]);
language(
language!("hcl", vec![]);
language!(
"prisma",
vec![Arc::new(prisma::PrismaLspAdapter::new(
node_runtime.clone(),
))],
))]
);
language("dart", vec![Arc::new(dart::DartLanguageServer {})]);
language!("dart", vec![Arc::new(dart::DartLanguageServer {})]);
}
#[cfg(any(test, feature = "test-support"))]

View file

@ -600,6 +600,20 @@ impl LanguageServer {
related_document_support: Some(true),
dynamic_registration: None,
}),
document_symbol: Some(DocumentSymbolClientCapabilities {
dynamic_registration: None,
symbol_kind: Some(SymbolKindCapability {
value_set: Some(vec![
SymbolKind::FUNCTION,
SymbolKind::PACKAGE,
SymbolKind::MODULE,
SymbolKind::FILE,
SymbolKind::NAMESPACE
]),
}),
hierarchical_document_symbol_support: Some(true),
..Default::default()
}),
..Default::default()
}),
experimental: Some(json!({

View file

@ -17,8 +17,8 @@ use language::{
Unclipped,
};
use lsp::{
CompletionListItemDefaultsEditRange, DocumentHighlightKind, LanguageServer, LanguageServerId,
OneOf, ServerCapabilities,
CompletionListItemDefaultsEditRange, DocumentHighlightKind, DocumentSymbol,
DocumentSymbolResponse, LanguageServer, LanguageServerId, OneOf, ServerCapabilities,
};
use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc};
use text::{BufferId, LineEnding};
@ -141,6 +141,8 @@ pub(crate) struct InlayHints {
pub range: Range<Anchor>,
}
pub(crate) struct DocumentSymbols;
pub(crate) struct FormattingOptions {
tab_size: u32,
}
@ -2480,3 +2482,94 @@ impl LspCommand for InlayHints {
BufferId::new(message.buffer_id)
}
}
#[async_trait(?Send)]
impl LspCommand for DocumentSymbols {
type Response = Vec<DocumentSymbol>;
type LspRequest = lsp::DocumentSymbolRequest;
// todo: add proto support
type ProtoRequest = proto::InlayHints;
fn check_capabilities(&self, server_capabilities: &lsp::ServerCapabilities) -> bool {
let Some(document_symbol_capabilities) = &server_capabilities.document_symbol_provider
else {
dbg!("Sadge");
return false;
};
match document_symbol_capabilities {
lsp::OneOf::Left(enabled) => dbg!(*enabled),
lsp::OneOf::Right(_) => true,
}
}
fn to_lsp(
&self,
path: &Path,
buffer: &Buffer,
_: &Arc<LanguageServer>,
_: &AppContext,
) -> lsp::DocumentSymbolParams {
dbg!("to_lsp");
lsp::DocumentSymbolParams {
text_document: lsp::TextDocumentIdentifier {
uri: lsp::Url::from_file_path(path).unwrap(),
},
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
}
}
async fn response_from_lsp(
self,
message: Option<DocumentSymbolResponse>,
project: Model<Project>,
buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<DocumentSymbol>> {
dbg!("response_from_lsp");
let message = message.context("Invalid DocumentSymbolResponse")?;
dbg!(message);
return Ok(vec![]);
// match message {
// DocumentSymbolResponse::Flat(contents) => {}
// DocumentSymbolResponse::Nested(contents) => {}
// }
}
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
todo!();
}
async fn from_proto(
message: proto::InlayHints,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
todo!();
}
fn response_to_proto(
response: Vec<lsp::DocumentSymbol>,
_: &mut Project,
_: PeerId,
buffer_version: &clock::Global,
_: &mut AppContext,
) -> proto::InlayHintsResponse {
todo!();
}
async fn response_from_proto(
self,
message: proto::InlayHintsResponse,
_: Model<Project>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<lsp::DocumentSymbol>> {
todo!();
}
fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
BufferId::new(message.buffer_id)
}
}

View file

@ -45,7 +45,7 @@ use log::error;
use lsp::{
DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,
DocumentHighlightKind, LanguageServer, LanguageServerBinary, LanguageServerId,
MessageActionItem, OneOf,
MessageActionItem, OneOf, SymbolInformation,
};
use lsp_command::*;
use node_runtime::NodeRuntime;
@ -4911,6 +4911,18 @@ impl Project {
self.hover_impl(buffer, position, cx)
}
pub fn document_symbols(
&self,
buffer: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<lsp::DocumentSymbol>>> {
self.request_lsp(
buffer.clone(),
LanguageServerToQuery::Primary,
DocumentSymbols,
cx,
)
}
#[inline(never)]
fn completions_impl(
&self,

View file

@ -3,6 +3,7 @@
use std::{any::TypeId, path::Path, sync::Arc};
use gpui::{AppContext, Context, Model, ModelContext, Subscription};
use project_core::{Location, ProjectPath};
use task::{Source, Task, TaskId};
/// Inventory tracks available tasks for a given project.
@ -55,7 +56,7 @@ impl Inventory {
}
/// Pulls its sources to list runanbles for the path given (up to the source to decide what to return for no path).
pub fn list_tasks(&self, path: Option<&Path>, cx: &mut AppContext) -> Vec<Arc<dyn Task>> {
pub fn list_tasks(&self, path: Option<&Location>, cx: &mut AppContext) -> Vec<Arc<dyn Task>> {
let mut tasks = Vec::new();
for source in &self.sources {
tasks.extend(

View file

@ -1,11 +1,14 @@
use std::path::Path;
use std::ops::Range;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::{path::Path, sync::Arc};
use language::DiagnosticEntry;
use gpui::Model;
use language::{Buffer, DiagnosticEntry};
use lsp::{DiagnosticSeverity, LanguageServerId};
use rpc::proto;
use serde::Serialize;
use worktree::WorktreeId;
mod ignore;
pub mod project_settings;
@ -79,3 +82,15 @@ impl DiagnosticSummary {
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct ProjectPath {
pub worktree_id: WorktreeId,
pub path: Arc<Path>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Location {
pub buffer: Model<Buffer>,
pub range: Range<language::Anchor>,
}

View file

@ -10,6 +10,7 @@ anyhow.workspace = true
collections.workspace = true
futures.workspace = true
gpui.workspace = true
project_core.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json_lenient.workspace = true

View file

@ -6,6 +6,7 @@ pub mod static_source;
use collections::HashMap;
use gpui::ModelContext;
use project_core::Location;
use std::any::Any;
use std::path::{Path, PathBuf};
use std::sync::Arc;
@ -62,7 +63,7 @@ pub trait Source: Any {
/// Collects all tasks available for scheduling, for the path given.
fn tasks_for_path(
&mut self,
path: Option<&Path>,
path: Option<&Location>,
cx: &mut ModelContext<Box<dyn Source>>,
) -> Vec<Arc<dyn Task>>;
}

View file

@ -4,6 +4,7 @@ use std::sync::Arc;
use crate::{Source, SpawnInTerminal, Task, TaskId};
use gpui::{AppContext, Context, Model};
use project_core::{Location, ProjectPath};
/// A storage and source of tasks generated out of user command prompt inputs.
pub struct OneshotSource {
@ -73,7 +74,7 @@ impl Source for OneshotSource {
fn tasks_for_path(
&mut self,
_path: Option<&std::path::Path>,
_path: Option<&Location>,
_cx: &mut gpui::ModelContext<Box<dyn Source>>,
) -> Vec<Arc<dyn Task>> {
self.tasks.clone()

View file

@ -8,6 +8,7 @@ use std::{
use collections::HashMap;
use futures::StreamExt;
use gpui::{AppContext, Context, Model, ModelContext, Subscription};
use project_core::Location;
use schemars::{gen::SchemaSettings, JsonSchema};
use serde::{Deserialize, Serialize};
use util::ResultExt;
@ -184,7 +185,7 @@ impl StaticSource {
impl Source for StaticSource {
fn tasks_for_path(
&mut self,
_: Option<&Path>,
_: Option<&Location>,
_: &mut ModelContext<Box<dyn Source>>,
) -> Vec<Arc<dyn Task>> {
self.tasks

View file

@ -7,11 +7,15 @@ license = "GPL-3.0-or-later"
[dependencies]
anyhow.workspace = true
editor.workspace = true
fuzzy.workspace = true
gpui.workspace = true
language.workspace = true
lsp.workspace = true
menu.workspace = true
picker.workspace = true
project.workspace = true
project_core.workspace = true
task.workspace = true
serde.workspace = true
ui.workspace = true

View file

@ -7,6 +7,8 @@ use util::ResultExt;
use workspace::Workspace;
mod modal;
mod tests_source;
pub use tests_source::TestSource;
pub fn init(cx: &mut AppContext) {
cx.observe_new_views(

View file

@ -1,5 +1,6 @@
use std::sync::Arc;
use editor::Anchor;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
actions, rems, AppContext, DismissEvent, EventEmitter, FocusableView, InteractiveElement,
@ -7,7 +8,8 @@ use gpui::{
VisualContext, WeakView,
};
use picker::{Picker, PickerDelegate};
use project::Inventory;
use project::{Inventory, Item};
use project_core::Location;
use task::{oneshot_source::OneshotSource, Task};
use ui::{v_flex, HighlightedLabel, ListItem, ListItemSpacing, Selectable, WindowContext};
use util::ResultExt;
@ -129,10 +131,24 @@ impl PickerDelegate for TasksModalDelegate {
cx.spawn(move |picker, mut cx| async move {
let Some(candidates) = picker
.update(&mut cx, |picker, cx| {
let editor = picker
.delegate
.workspace
.update(cx, |this, cx| this.active_item_as::<editor::Editor>(cx))
.ok()
.flatten();
let buffer =
(|| Some(editor.clone()?.read(cx).buffer().read(cx).as_singleton()?))();
let range = (|| Some(editor?.read(cx).selections.first_anchor()))();
let path = buffer.zip(range).map(|(buffer, _)| Location {
buffer,
range: language::Anchor::MIN..language::Anchor::MAX,
});
//let path = path.as_deref();
picker.delegate.candidates = picker
.delegate
.inventory
.update(cx, |inventory, cx| inventory.list_tasks(None, cx));
.update(cx, |inventory, cx| inventory.list_tasks(path.as_ref(), cx));
picker
.delegate
.candidates

View file

@ -0,0 +1,60 @@
use anyhow::Result;
use gpui::{AppContext, Model, Task, WeakModel};
use language::Buffer;
use project::Project;
use project_core::Location;
use task::Source;
use ui::Context;
/// Returns runnables for tests at current cursor, module and file.
pub struct TestSource {
project: WeakModel<Project>,
all_tasks_for: Option<(WeakModel<Buffer>, Task<Result<Vec<lsp::DocumentSymbol>>>)>,
}
impl TestSource {
pub fn new(project: WeakModel<Project>, cx: &mut AppContext) -> Model<Box<dyn Source>> {
cx.new_model(|_| {
Box::new(Self {
project,
all_tasks_for: None,
}) as _
})
}
}
impl Source for TestSource {
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn tasks_for_path(
&mut self,
_path: Option<&Location>,
cx: &mut gpui::ModelContext<Box<dyn Source>>,
) -> Vec<std::sync::Arc<dyn task::Task>> {
if let Some(path) = _path {
self.project.update(cx, move |_, cx| {
let p = path.buffer.clone();
cx.spawn(|this, mut cx| async move {
dbg!("Heyyo");
dbg!(
this.update(&mut cx, |this, cx| this.document_symbols(&p, cx))
.ok()?
.await
);
dbg!("Hey");
Some(())
})
.detach();
});
// self.all_tasks_for = Some((
// path.buffer.downgrade(),
// self.project.update(cx, |this, cx| {
// this.document_symbols(&path.buffer, cx).shared()
// }),
// ));
}
vec![]
}
}

View file

@ -28,6 +28,7 @@ use settings::{
};
use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc};
use task::{oneshot_source::OneshotSource, static_source::StaticSource};
use tasks_ui::TestSource;
use terminal_view::terminal_panel::{self, TerminalPanel};
use util::{
asset_str,
@ -160,13 +161,15 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
app_state.fs.clone(),
paths::TASKS.clone(),
);
let static_source = StaticSource::new(tasks_file_rx, cx);
let oneshot_source = OneshotSource::new(cx);
let tests_source = TestSource::new(project.downgrade(), cx);
project.update(cx, |project, cx| {
project.task_inventory().update(cx, |inventory, cx| {
inventory.add_source(oneshot_source, cx);
inventory.add_source(static_source, cx);
inventory.add_source(tests_source, cx);
})
});
}