Compare commits
7 commits
main
...
dynamic-ru
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e0a20690fb | ||
![]() |
e9613e552a | ||
![]() |
91b011a2c6 | ||
![]() |
24677b11ed | ||
![]() |
c70cb5a911 | ||
![]() |
b884658e49 | ||
![]() |
f0f49db969 |
17 changed files with 388 additions and 112 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
adapters,
|
||||
move || Ok((config.clone(), load_queries(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))),
|
||||
// )
|
||||
// };
|
||||
|
||||
language(
|
||||
macro_rules! language {
|
||||
($name:literal) => {
|
||||
let config = load_config($name);
|
||||
languages.register_language(
|
||||
config.name.clone(),
|
||||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
vec![],
|
||||
move || Ok((config.clone(), load_queries($name))),
|
||||
);
|
||||
};
|
||||
($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",
|
||||
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::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",
|
||||
vec![Arc::new(elixir::LocalLspAdapter {
|
||||
path: path.clone(),
|
||||
arguments: arguments.clone(),
|
||||
})]
|
||||
);
|
||||
}
|
||||
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"))]
|
||||
|
|
|
@ -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!({
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>>;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
60
crates/tasks_ui/src/tests_source.rs
Normal file
60
crates/tasks_ui/src/tests_source.rs
Normal 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![]
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue