Drag detached files towards loading

This commit is contained in:
Kirill Bulatov 2021-05-23 20:56:54 +03:00
parent 695569d978
commit de090749d9
6 changed files with 83 additions and 11 deletions

View file

@ -50,7 +50,6 @@ pub use proc_macro_api::ProcMacroClient;
pub enum ProjectManifest {
ProjectJson(AbsPathBuf),
CargoToml(AbsPathBuf),
DetachedFile(AbsPathBuf),
}
impl ProjectManifest {

View file

@ -50,7 +50,9 @@ impl Sysroot {
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
log::debug!("Discovering sysroot for {}", cargo_toml.display());
let current_dir = cargo_toml.parent().unwrap();
let current_dir = cargo_toml.parent().ok_or_else(|| {
format_err!("Failed to find the parent directory for file {:?}", cargo_toml)
})?;
let sysroot_dir = discover_sysroot_dir(current_dir)?;
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
let res = Sysroot::load(&sysroot_src_dir)?;

View file

@ -4,7 +4,7 @@
use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
use anyhow::{Context, Result};
use anyhow::{format_err, Context, Result};
use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro};
use cargo_workspace::DepKind;
use cfg::CfgOptions;
@ -49,6 +49,8 @@ pub enum ProjectWorkspace {
},
/// Project workspace was manually specified using a `rust-project.json` file.
Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> },
/// TODO kb docs
DetachedFiles { files: Vec<AbsPathBuf>, sysroot: Sysroot, rustc_cfg: Vec<CfgFlag> },
}
impl fmt::Debug for ProjectWorkspace {
@ -75,6 +77,12 @@ impl fmt::Debug for ProjectWorkspace {
debug_struct.field("n_rustc_cfg", &rustc_cfg.len());
debug_struct.finish()
}
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => f
.debug_struct("DetachedFiles")
.field("n_files", &files.len())
.field("n_sysroot_crates", &sysroot.crates().len())
.field("n_rustc_cfg", &rustc_cfg.len())
.finish(),
}
}
}
@ -148,9 +156,6 @@ impl ProjectWorkspace {
let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref());
ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg }
}
ProjectManifest::DetachedFile(_) => {
todo!("TODO kb")
}
};
Ok(res)
@ -168,6 +173,14 @@ impl ProjectWorkspace {
Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
}
pub fn load_detached_files(detached_files: Vec<AbsPathBuf>) -> Result<ProjectWorkspace> {
let sysroot = Sysroot::discover(
&detached_files.first().ok_or_else(|| format_err!("No detached files to load"))?,
)?;
let rustc_cfg = rustc_cfg::get(None, None);
Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg })
}
/// Returns the roots for the current `ProjectWorkspace`
/// The return type contains the path and whether or not
/// the root is a member of the current workspace
@ -227,6 +240,19 @@ impl ProjectWorkspace {
})
}))
.collect(),
ProjectWorkspace::DetachedFiles { files, sysroot, .. } => files
.into_iter()
.map(|detached_file| PackageRoot {
is_member: true,
include: vec![detached_file.clone()],
exclude: Vec::new(),
})
.chain(sysroot.crates().map(|krate| PackageRoot {
is_member: false,
include: vec![sysroot[krate].root_dir().to_path_buf()],
exclude: Vec::new(),
}))
.collect(),
}
}
@ -237,6 +263,9 @@ impl ProjectWorkspace {
let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len());
cargo.packages().len() + sysroot.crates().len() + rustc_package_len
}
ProjectWorkspace::DetachedFiles { sysroot, files, .. } => {
sysroot.crates().len() + files.len()
}
}
}
@ -270,6 +299,9 @@ impl ProjectWorkspace {
rustc,
rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())),
),
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot)
}
};
if crate_graph.patch_cfg_if() {
log::debug!("Patched std to depend on cfg-if")
@ -477,6 +509,39 @@ fn cargo_to_crate_graph(
crate_graph
}
// TODO kb refactor and check for correctness
fn detached_files_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
detached_files: &[AbsPathBuf],
sysroot: &Sysroot,
) -> CrateGraph {
let _p = profile::span("detached_files_to_crate_graph");
let mut crate_graph = CrateGraph::default();
let (public_deps, _libproc_macro) =
sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
let mut cfg_options = CfgOptions::default();
cfg_options.extend(rustc_cfg);
for detached_file in detached_files {
let file_id = load(&detached_file).unwrap();
let detached_file_crate = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
None,
cfg_options.clone(),
Env::default(),
Vec::new(),
);
for (name, krate) in public_deps.iter() {
add_dep(&mut crate_graph, detached_file_crate, name.clone(), *krate);
}
}
crate_graph
}
fn handle_rustc_crates(
rustc_workspace: &CargoWorkspace,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,

View file

@ -236,7 +236,7 @@ impl Default for ConfigData {
pub struct Config {
caps: lsp_types::ClientCapabilities,
data: ConfigData,
detached_files: Vec<ProjectManifest>,
detached_files: Vec<AbsPathBuf>,
pub discovered_projects: Option<Vec<ProjectManifest>>,
pub root_path: AbsPathBuf,
}
@ -345,7 +345,6 @@ impl Config {
self.detached_files = get_field::<Vec<PathBuf>>(&mut json, "detachedFiles", None, "[]")
.into_iter()
.map(AbsPathBuf::assert)
.map(ProjectManifest::DetachedFile)
.collect();
self.data = ConfigData::from_json(json);
}
@ -399,7 +398,7 @@ impl Config {
}
}
pub fn detached_files(&self) -> &[ProjectManifest] {
pub fn detached_files(&self) -> &[AbsPathBuf] {
&self.detached_files
}

View file

@ -312,6 +312,7 @@ impl GlobalStateSnapshot {
cargo.target_by_root(&path).map(|it| (cargo, it))
}
ProjectWorkspace::Json { .. } => None,
ProjectWorkspace::DetachedFiles { .. } => None,
})
}
}

View file

@ -146,8 +146,8 @@ impl GlobalState {
log::info!("will fetch workspaces");
self.task_pool.handle.spawn_with_sender({
// TODO kb reload workspace here?
let linked_projects = self.config.linked_projects();
let detached_files = self.config.detached_files().to_vec();
let cargo_config = self.config.cargo();
move |sender| {
@ -162,7 +162,7 @@ impl GlobalState {
sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap();
let workspaces = linked_projects
let mut workspaces = linked_projects
.iter()
.map(|project| match project {
LinkedProject::ProjectManifest(manifest) => {
@ -181,6 +181,11 @@ impl GlobalState {
})
.collect::<Vec<_>>();
if !detached_files.is_empty() {
workspaces
.push(project_model::ProjectWorkspace::load_detached_files(detached_files));
}
log::info!("did fetch workspaces {:?}", workspaces);
sender
.send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces)))
@ -408,6 +413,7 @@ impl GlobalState {
_ => None,
}
}
ProjectWorkspace::DetachedFiles { .. } => None,
})
.map(|(id, root)| {
let sender = sender.clone();