Add support for projects managed with Yarn (#13644)
TODO: - [ ] File a PR with Yarn to add Zed to the list of supported IDEs. Fixes: https://github.com/zed-industries/zed/issues/10107 Fixes: https://github.com/zed-industries/zed/issues/13706 Release Notes: - Improved experience in projects using Yarn. Run `yarn dlx @yarnpkg/sdks base` in the root of your project in order to elevate your experience. --------- Co-authored-by: Saurabh <79586784+m4saurabh@users.noreply.github.com>
This commit is contained in:
parent
291d64c803
commit
2727f55772
9 changed files with 320 additions and 24 deletions
|
@ -11,6 +11,7 @@ pub mod terminals;
|
|||
#[cfg(test)]
|
||||
mod project_tests;
|
||||
pub mod search_history;
|
||||
mod yarn;
|
||||
|
||||
use anyhow::{anyhow, bail, Context as _, Result};
|
||||
use async_trait::async_trait;
|
||||
|
@ -116,6 +117,7 @@ use util::{
|
|||
NumericPrefixWithSuffix, ResultExt, TryFutureExt as _,
|
||||
};
|
||||
use worktree::{CreatedEntry, RemoteWorktreeClient, Snapshot, Traversal};
|
||||
use yarn::YarnPathStore;
|
||||
|
||||
pub use fs::*;
|
||||
pub use language::Location;
|
||||
|
@ -231,6 +233,7 @@ pub struct Project {
|
|||
dev_server_project_id: Option<client::DevServerProjectId>,
|
||||
search_history: SearchHistory,
|
||||
snippets: Model<SnippetProvider>,
|
||||
yarn: Model<YarnPathStore>,
|
||||
}
|
||||
|
||||
pub enum LanguageServerToQuery {
|
||||
|
@ -728,6 +731,7 @@ impl Project {
|
|||
let global_snippets_dir = paths::config_dir().join("snippets");
|
||||
let snippets =
|
||||
SnippetProvider::new(fs.clone(), BTreeSet::from_iter([global_snippets_dir]), cx);
|
||||
let yarn = YarnPathStore::new(fs.clone(), cx);
|
||||
Self {
|
||||
worktrees: Vec::new(),
|
||||
worktrees_reordered: false,
|
||||
|
@ -753,6 +757,7 @@ impl Project {
|
|||
_maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
|
||||
_maintain_workspace_config: Self::maintain_workspace_config(cx),
|
||||
active_entry: None,
|
||||
yarn,
|
||||
snippets,
|
||||
languages,
|
||||
client,
|
||||
|
@ -853,6 +858,7 @@ impl Project {
|
|||
let global_snippets_dir = paths::config_dir().join("snippets");
|
||||
let snippets =
|
||||
SnippetProvider::new(fs.clone(), BTreeSet::from_iter([global_snippets_dir]), cx);
|
||||
let yarn = YarnPathStore::new(fs.clone(), cx);
|
||||
// BIG CAUTION NOTE: The order in which we initialize fields here matters and it should match what's done in Self::local.
|
||||
// Otherwise, you might run into issues where worktree id on remote is different than what's on local host.
|
||||
// That's because Worktree's identifier is entity id, which should probably be changed.
|
||||
|
@ -891,6 +897,7 @@ impl Project {
|
|||
languages,
|
||||
user_store: user_store.clone(),
|
||||
snippets,
|
||||
yarn,
|
||||
fs,
|
||||
next_entry_id: Default::default(),
|
||||
next_diagnostic_group_id: Default::default(),
|
||||
|
@ -2163,23 +2170,51 @@ impl Project {
|
|||
/// LanguageServerName is owned, because it is inserted into a map
|
||||
pub fn open_local_buffer_via_lsp(
|
||||
&mut self,
|
||||
abs_path: lsp::Url,
|
||||
mut abs_path: lsp::Url,
|
||||
language_server_id: LanguageServerId,
|
||||
language_server_name: LanguageServerName,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<Model<Buffer>>> {
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
// Escape percent-encoded string.
|
||||
let current_scheme = abs_path.scheme().to_owned();
|
||||
let _ = abs_path.set_scheme("file");
|
||||
|
||||
let abs_path = abs_path
|
||||
.to_file_path()
|
||||
.map_err(|_| anyhow!("can't convert URI to path"))?;
|
||||
let (worktree, relative_path) = if let Some(result) =
|
||||
this.update(&mut cx, |this, cx| this.find_local_worktree(&abs_path, cx))?
|
||||
{
|
||||
result
|
||||
let p = abs_path.clone();
|
||||
let yarn_worktree = this
|
||||
.update(&mut cx, move |this, cx| {
|
||||
this.yarn.update(cx, |_, cx| {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let t = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.process_path(&p, ¤t_scheme, cx)
|
||||
})
|
||||
.ok()?;
|
||||
t.await
|
||||
})
|
||||
})
|
||||
})?
|
||||
.await;
|
||||
let (worktree_root_target, known_relative_path) =
|
||||
if let Some((zip_root, relative_path)) = yarn_worktree {
|
||||
(zip_root, Some(relative_path))
|
||||
} else {
|
||||
(Arc::<Path>::from(abs_path.as_path()), None)
|
||||
};
|
||||
let (worktree, relative_path) = if let Some(result) = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.find_local_worktree(&worktree_root_target, cx)
|
||||
})? {
|
||||
let relative_path =
|
||||
known_relative_path.unwrap_or_else(|| Arc::<Path>::from(result.1));
|
||||
(result.0, relative_path)
|
||||
} else {
|
||||
let worktree = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.create_local_worktree(&abs_path, false, cx)
|
||||
this.create_local_worktree(&worktree_root_target, false, cx)
|
||||
})?
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
|
@ -2189,12 +2224,17 @@ impl Project {
|
|||
);
|
||||
})
|
||||
.ok();
|
||||
(worktree, PathBuf::new())
|
||||
let worktree_root = worktree.update(&mut cx, |this, _| this.abs_path())?;
|
||||
let relative_path = if let Some(known_path) = known_relative_path {
|
||||
known_path
|
||||
} else {
|
||||
abs_path.strip_prefix(worktree_root)?.into()
|
||||
};
|
||||
(worktree, relative_path)
|
||||
};
|
||||
|
||||
let project_path = ProjectPath {
|
||||
worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?,
|
||||
path: relative_path.into(),
|
||||
path: relative_path,
|
||||
};
|
||||
this.update(&mut cx, |this, cx| this.open_buffer(project_path, cx))?
|
||||
.await
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue