project: Track manifest locations per unique manifest locator (#27194)
This pull request paves way for exposing manifest tracking to extensions. - Project tree was renamed to manifest tree to better reflect it's intent (and avoid confusion). - Language server adapters now provide a name of their *manifest locator*. If multiple language servers refer to the same locator, the locating code will run just once for a given path. Release Notes: - N/A *or* Added/Fixed/Improved ... --------- Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
parent
6bced3a834
commit
05aa8880a4
10 changed files with 241 additions and 154 deletions
|
@ -11,6 +11,7 @@ mod diagnostic_set;
|
|||
mod highlight_map;
|
||||
mod language_registry;
|
||||
pub mod language_settings;
|
||||
mod manifest;
|
||||
mod outline;
|
||||
pub mod proto;
|
||||
mod syntax_map;
|
||||
|
@ -33,6 +34,7 @@ pub use highlight_map::HighlightMap;
|
|||
use http_client::HttpClient;
|
||||
pub use language_registry::{LanguageName, LoadedLanguage};
|
||||
use lsp::{CodeActionKind, InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions};
|
||||
pub use manifest::{ManifestName, ManifestProvider, ManifestQuery};
|
||||
use parking_lot::Mutex;
|
||||
use regex::Regex;
|
||||
use schemars::{
|
||||
|
@ -163,6 +165,7 @@ pub struct CachedLspAdapter {
|
|||
pub adapter: Arc<dyn LspAdapter>,
|
||||
pub reinstall_attempt_count: AtomicU64,
|
||||
cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>,
|
||||
manifest_name: OnceLock<Option<ManifestName>>,
|
||||
attach_kind: OnceLock<Attach>,
|
||||
}
|
||||
|
||||
|
@ -200,6 +203,7 @@ impl CachedLspAdapter {
|
|||
cached_binary: Default::default(),
|
||||
reinstall_attempt_count: AtomicU64::new(0),
|
||||
attach_kind: Default::default(),
|
||||
manifest_name: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -261,14 +265,10 @@ impl CachedLspAdapter {
|
|||
.cloned()
|
||||
.unwrap_or_else(|| language_name.lsp_id())
|
||||
}
|
||||
pub fn find_project_root(
|
||||
&self,
|
||||
path: &Path,
|
||||
ancestor_depth: usize,
|
||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||
) -> Option<Arc<Path>> {
|
||||
self.adapter
|
||||
.find_project_root(path, ancestor_depth, delegate)
|
||||
pub fn manifest_name(&self) -> Option<ManifestName> {
|
||||
self.manifest_name
|
||||
.get_or_init(|| self.adapter.manifest_name())
|
||||
.clone()
|
||||
}
|
||||
pub fn attach_kind(&self) -> Attach {
|
||||
*self.attach_kind.get_or_init(|| self.adapter.attach_kind())
|
||||
|
@ -542,18 +542,13 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
fn prepare_initialize_params(&self, original: InitializeParams) -> Result<InitializeParams> {
|
||||
Ok(original)
|
||||
}
|
||||
|
||||
fn attach_kind(&self) -> Attach {
|
||||
Attach::Shared
|
||||
}
|
||||
fn find_project_root(
|
||||
&self,
|
||||
|
||||
_path: &Path,
|
||||
_ancestor_depth: usize,
|
||||
_: &Arc<dyn LspAdapterDelegate>,
|
||||
) -> Option<Arc<Path>> {
|
||||
// By default all language servers are rooted at the root of the worktree.
|
||||
Some(Arc::from("".as_ref()))
|
||||
fn manifest_name(&self) -> Option<ManifestName> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Method only implemented by the default JSON language server adapter.
|
||||
|
|
48
crates/language/src/manifest.rs
Normal file
48
crates/language/src/manifest.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
use std::{borrow::Borrow, path::Path, sync::Arc};
|
||||
|
||||
use gpui::SharedString;
|
||||
|
||||
use crate::LspAdapterDelegate;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ManifestName(SharedString);
|
||||
|
||||
impl Borrow<SharedString> for ManifestName {
|
||||
fn borrow(&self) -> &SharedString {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SharedString> for ManifestName {
|
||||
fn from(value: SharedString) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ManifestName> for SharedString {
|
||||
fn from(value: ManifestName) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<SharedString> for ManifestName {
|
||||
fn as_ref(&self) -> &SharedString {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a manifest query; given a path to a file, [ManifestSearcher] is tasked with finding a path to the directory containing the manifest for that file.
|
||||
///
|
||||
/// Since parts of the path might have already been explored, there's an additional `depth` parameter that indicates to what ancestry level a given path should be explored.
|
||||
/// For example, given a path like `foo/bar/baz`, a depth of 2 would explore `foo/bar/baz` and `foo/bar`, but not `foo`.
|
||||
pub struct ManifestQuery {
|
||||
/// Path to the file, relative to worktree root.
|
||||
pub path: Arc<Path>,
|
||||
pub depth: usize,
|
||||
pub delegate: Arc<dyn LspAdapterDelegate>,
|
||||
}
|
||||
|
||||
pub trait ManifestProvider {
|
||||
fn name(&self) -> ManifestName;
|
||||
fn search(&self, query: ManifestQuery) -> Option<Arc<Path>>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue