Extract common fields out of ProjectWorkspace variants

This commit is contained in:
Lukas Wirth 2024-04-21 17:03:02 +02:00
parent a2ed6837bc
commit ff56cb6e49
15 changed files with 248 additions and 333 deletions

View file

@ -333,9 +333,7 @@ fn load_crate_graph(
vfs: &mut vfs::Vfs, vfs: &mut vfs::Vfs,
receiver: &Receiver<vfs::loader::Message>, receiver: &Receiver<vfs::loader::Message>,
) -> RootDatabase { ) -> RootDatabase {
let (ProjectWorkspace::Cargo { toolchain, target_layout, .. } let ProjectWorkspace { toolchain, target_layout, .. } = ws;
| ProjectWorkspace::Json { toolchain, target_layout, .. }
| ProjectWorkspace::DetachedFile { toolchain, target_layout, .. }) = ws;
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
let mut db = RootDatabase::new(lru_cap); let mut db = RootDatabase::new(lru_cap);

View file

@ -116,7 +116,7 @@ impl WorkspaceBuildScripts {
} }
} }
if manifest_path.extension().map_or(false, |ext| ext == "rs") { if manifest_path.is_rust_manifest() {
cmd.arg("-Zscript"); cmd.arg("-Zscript");
} }

View file

@ -307,7 +307,7 @@ impl CargoWorkspace {
); );
} }
// The manifest is a rust file, so this means its a script manifest // The manifest is a rust file, so this means its a script manifest
if cargo_toml.extension().is_some_and(|ext| ext == "rs") { if cargo_toml.is_rust_manifest() {
// Deliberately don't set up RUSTC_BOOTSTRAP or a nightly override here, the user should // Deliberately don't set up RUSTC_BOOTSTRAP or a nightly override here, the user should
// opt into it themselves. // opt into it themselves.
other_options.push("-Zscript".to_owned()); other_options.push("-Zscript".to_owned());

View file

@ -60,16 +60,19 @@ pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: Targe
} }
pub(crate) fn cargo_config_env( pub(crate) fn cargo_config_env(
cargo_toml: &ManifestPath, manifest: &ManifestPath,
extra_env: &FxHashMap<String, String>, extra_env: &FxHashMap<String, String>,
sysroot: Option<&Sysroot>, sysroot: Option<&Sysroot>,
) -> FxHashMap<String, String> { ) -> FxHashMap<String, String> {
let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
cargo_config.envs(extra_env); cargo_config.envs(extra_env);
cargo_config cargo_config
.current_dir(cargo_toml.parent()) .current_dir(manifest.parent())
.args(["-Z", "unstable-options", "config", "get", "env"]) .args(["-Z", "unstable-options", "config", "get", "env"])
.env("RUSTC_BOOTSTRAP", "1"); .env("RUSTC_BOOTSTRAP", "1");
if manifest.is_rust_manifest() {
cargo_config.arg("-Zscript");
}
// if successful we receive `env.key.value = "value" per entry // if successful we receive `env.key.value = "value" per entry
tracing::debug!("Discovering cargo config env by {:?}", cargo_config); tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default() utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()

View file

@ -52,7 +52,7 @@ pub use crate::{
manifest_path::ManifestPath, manifest_path::ManifestPath,
project_json::{ProjectJson, ProjectJsonData}, project_json::{ProjectJson, ProjectJsonData},
sysroot::Sysroot, sysroot::Sysroot,
workspace::{FileLoader, PackageRoot, ProjectWorkspace}, workspace::{FileLoader, PackageRoot, ProjectWorkspace, ProjectWorkspaceKind},
}; };
pub use cargo_metadata::Metadata; pub use cargo_metadata::Metadata;

View file

@ -38,6 +38,10 @@ impl ManifestPath {
pub fn canonicalize(&self) -> ! { pub fn canonicalize(&self) -> ! {
(**self).canonicalize() (**self).canonicalize()
} }
pub fn is_rust_manifest(&self) -> bool {
self.file.extension().map_or(false, |ext| ext == "rs")
}
} }
impl fmt::Display for ManifestPath { impl fmt::Display for ManifestPath {

View file

@ -10,8 +10,8 @@ use serde::de::DeserializeOwned;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson,
Sysroot, WorkspaceBuildScripts, ProjectJsonData, ProjectWorkspace, Sysroot, WorkspaceBuildScripts,
}; };
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
@ -26,16 +26,18 @@ fn load_cargo_with_overrides(
let manifest_path = let manifest_path =
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap(); ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
let cargo_workspace = CargoWorkspace::new(meta, manifest_path); let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
let project_workspace = ProjectWorkspace::Cargo { let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo: cargo_workspace, cargo: cargo_workspace,
build_scripts: WorkspaceBuildScripts::default(), build_scripts: WorkspaceBuildScripts::default(),
sysroot: Err(None),
rustc: Err(None), rustc: Err(None),
rustc_cfg: Vec::new(), cargo_config_extra_env: Default::default(),
},
cfg_overrides, cfg_overrides,
sysroot: Err(None),
rustc_cfg: Vec::new(),
toolchain: None, toolchain: None,
target_layout: Err("target_data_layout not loaded".into()), target_layout: Err("target_data_layout not loaded".into()),
cargo_config_extra_env: Default::default(),
}; };
to_crate_graph(project_workspace) to_crate_graph(project_workspace)
} }
@ -48,16 +50,18 @@ fn load_cargo_with_fake_sysroot(
let manifest_path = let manifest_path =
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap(); ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
let cargo_workspace = CargoWorkspace::new(meta, manifest_path); let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
let project_workspace = ProjectWorkspace::Cargo { let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo: cargo_workspace, cargo: cargo_workspace,
build_scripts: WorkspaceBuildScripts::default(), build_scripts: WorkspaceBuildScripts::default(),
sysroot: Ok(get_fake_sysroot()),
rustc: Err(None), rustc: Err(None),
cargo_config_extra_env: Default::default(),
},
sysroot: Ok(get_fake_sysroot()),
rustc_cfg: Vec::new(), rustc_cfg: Vec::new(),
cfg_overrides: Default::default(), cfg_overrides: Default::default(),
toolchain: None, toolchain: None,
target_layout: Err("target_data_layout not loaded".into()), target_layout: Err("target_data_layout not loaded".into()),
cargo_config_extra_env: Default::default(),
}; };
project_workspace.to_crate_graph( project_workspace.to_crate_graph(
&mut { &mut {
@ -74,8 +78,8 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
let data = get_test_json_file(file); let data = get_test_json_file(file);
let project = rooted_project_json(data); let project = rooted_project_json(data);
let sysroot = Ok(get_fake_sysroot()); let sysroot = Ok(get_fake_sysroot());
let project_workspace = ProjectWorkspace::Json { let project_workspace = ProjectWorkspace {
project, kind: ProjectWorkspaceKind::Json(project),
sysroot, sysroot,
rustc_cfg: Vec::new(), rustc_cfg: Vec::new(),
toolchain: None, toolchain: None,
@ -284,16 +288,18 @@ fn smoke_test_real_sysroot_cargo() {
) )
.unwrap()); .unwrap());
let project_workspace = ProjectWorkspace::Cargo { let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo: cargo_workspace, cargo: cargo_workspace,
build_scripts: WorkspaceBuildScripts::default(), build_scripts: WorkspaceBuildScripts::default(),
sysroot,
rustc: Err(None), rustc: Err(None),
cargo_config_extra_env: Default::default(),
},
sysroot,
rustc_cfg: Vec::new(), rustc_cfg: Vec::new(),
cfg_overrides: Default::default(), cfg_overrides: Default::default(),
toolchain: None, toolchain: None,
target_layout: Err("target_data_layout not loaded".into()), target_layout: Err("target_data_layout not loaded".into()),
cargo_config_extra_env: Default::default(),
}; };
project_workspace.to_crate_graph( project_workspace.to_crate_graph(
&mut { &mut {

View file

@ -44,50 +44,39 @@ pub struct PackageRoot {
} }
#[derive(Clone)] #[derive(Clone)]
pub enum ProjectWorkspace { pub struct ProjectWorkspace {
pub kind: ProjectWorkspaceKind,
/// The sysroot loaded for this workspace.
pub sysroot: Result<Sysroot, Option<String>>,
/// Holds cfg flags for the current target. We get those by running
/// `rustc --print cfg`.
// FIXME: make this a per-crate map, as, eg, build.rs might have a
// different target.
pub rustc_cfg: Vec<CfgFlag>,
/// The toolchain version used by this workspace.
pub toolchain: Option<Version>,
/// The target data layout queried for workspace.
pub target_layout: TargetLayoutLoadResult,
/// A set of cfg overrides for this workspace.
pub cfg_overrides: CfgOverrides,
}
#[derive(Clone)]
pub enum ProjectWorkspaceKind {
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
Cargo { Cargo {
/// The workspace as returned by `cargo metadata`. /// The workspace as returned by `cargo metadata`.
cargo: CargoWorkspace, cargo: CargoWorkspace,
/// The build script results for the workspace. /// The build script results for the workspace.
build_scripts: WorkspaceBuildScripts, build_scripts: WorkspaceBuildScripts,
/// The sysroot loaded for this workspace.
sysroot: Result<Sysroot, Option<String>>,
/// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been /// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been
/// disabled or was otherwise not requested. /// disabled or was otherwise not requested.
rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>, rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
/// Holds cfg flags for the current target. We get those by running
/// `rustc --print cfg`.
// FIXME: make this a per-crate map, as, eg, build.rs might have a
// different target.
rustc_cfg: Vec<CfgFlag>,
/// A set of cfg overrides for this workspace.
cfg_overrides: CfgOverrides,
/// The toolchain version used by this workspace.
toolchain: Option<Version>,
/// The target data layout queried for workspace.
target_layout: TargetLayoutLoadResult,
/// Environment variables set in the `.cargo/config` file. /// Environment variables set in the `.cargo/config` file.
cargo_config_extra_env: FxHashMap<String, String>, cargo_config_extra_env: FxHashMap<String, String>,
}, },
/// Project workspace was manually specified using a `rust-project.json` file. /// Project workspace was manually specified using a `rust-project.json` file.
Json { Json(ProjectJson),
/// The loaded project json file.
project: ProjectJson,
/// The sysroot loaded for this workspace.
sysroot: Result<Sysroot, Option<String>>,
/// Holds cfg flags for the current target. We get those by running
/// `rustc --print cfg`.
// FIXME: make this a per-crate map, as, eg, build.rs might have a
// different target.
rustc_cfg: Vec<CfgFlag>,
/// The toolchain version used by this workspace.
toolchain: Option<Version>,
/// The target data layout queried for workspace.
target_layout: TargetLayoutLoadResult,
/// A set of cfg overrides for this workspace.
cfg_overrides: CfgOverrides,
},
// FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning. // FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
// That's not the end user experience we should strive for. // That's not the end user experience we should strive for.
// Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working. // Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working.
@ -101,37 +90,22 @@ pub enum ProjectWorkspace {
DetachedFile { DetachedFile {
/// The file in question. /// The file in question.
file: ManifestPath, file: ManifestPath,
/// The sysroot loaded for this workspace.
sysroot: Result<Sysroot, Option<String>>,
/// Holds cfg flags for the current target. We get those by running
/// `rustc --print cfg`.
// FIXME: make this a per-crate map, as, eg, build.rs might have a
// different target.
rustc_cfg: Vec<CfgFlag>,
/// The toolchain version used by this workspace.
toolchain: Option<Version>,
/// The target data layout queried for workspace.
target_layout: TargetLayoutLoadResult,
/// A set of cfg overrides for the files.
cfg_overrides: CfgOverrides,
/// Is this file a cargo script file? /// Is this file a cargo script file?
cargo_script: Option<(CargoWorkspace, WorkspaceBuildScripts)>, cargo_script: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
/// Environment variables set in the `.cargo/config` file.
cargo_config_extra_env: FxHashMap<String, String>,
}, },
} }
impl fmt::Debug for ProjectWorkspace { impl fmt::Debug for ProjectWorkspace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Make sure this isn't too verbose. // Make sure this isn't too verbose.
match self { let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self;
ProjectWorkspace::Cargo { match kind {
ProjectWorkspaceKind::Cargo {
cargo, cargo,
build_scripts: _, build_scripts: _,
sysroot,
rustc, rustc,
rustc_cfg,
cfg_overrides,
toolchain,
target_layout,
cargo_config_extra_env, cargo_config_extra_env,
} => f } => f
.debug_struct("Cargo") .debug_struct("Cargo")
@ -148,14 +122,7 @@ impl fmt::Debug for ProjectWorkspace {
.field("data_layout", &target_layout) .field("data_layout", &target_layout)
.field("cargo_config_extra_env", &cargo_config_extra_env) .field("cargo_config_extra_env", &cargo_config_extra_env)
.finish(), .finish(),
ProjectWorkspace::Json { ProjectWorkspaceKind::Json(project) => {
project,
sysroot,
rustc_cfg,
toolchain,
target_layout: data_layout,
cfg_overrides,
} => {
let mut debug_struct = f.debug_struct("Json"); let mut debug_struct = f.debug_struct("Json");
debug_struct.field("n_crates", &project.n_crates()); debug_struct.field("n_crates", &project.n_crates());
if let Ok(sysroot) = sysroot { if let Ok(sysroot) = sysroot {
@ -164,19 +131,11 @@ impl fmt::Debug for ProjectWorkspace {
debug_struct debug_struct
.field("n_rustc_cfg", &rustc_cfg.len()) .field("n_rustc_cfg", &rustc_cfg.len())
.field("toolchain", &toolchain) .field("toolchain", &toolchain)
.field("data_layout", &data_layout) .field("data_layout", &target_layout)
.field("n_cfg_overrides", &cfg_overrides.len()); .field("n_cfg_overrides", &cfg_overrides.len());
debug_struct.finish() debug_struct.finish()
} }
ProjectWorkspace::DetachedFile { ProjectWorkspaceKind::DetachedFile { file, cargo_script, cargo_config_extra_env } => f
file,
sysroot,
rustc_cfg,
toolchain,
target_layout,
cfg_overrides,
cargo_script,
} => f
.debug_struct("DetachedFiles") .debug_struct("DetachedFiles")
.field("file", &file) .field("file", &file)
.field("cargo_script", &cargo_script.is_some()) .field("cargo_script", &cargo_script.is_some())
@ -186,6 +145,7 @@ impl fmt::Debug for ProjectWorkspace {
.field("toolchain", &toolchain) .field("toolchain", &toolchain)
.field("data_layout", &target_layout) .field("data_layout", &target_layout)
.field("n_cfg_overrides", &cfg_overrides.len()) .field("n_cfg_overrides", &cfg_overrides.len())
.field("cargo_config_extra_env", &cargo_config_extra_env)
.finish(), .finish(),
} }
} }
@ -361,18 +321,20 @@ impl ProjectWorkspace {
let cargo_config_extra_env = let cargo_config_extra_env =
cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref); cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
ProjectWorkspace::Cargo { ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo, cargo,
build_scripts: WorkspaceBuildScripts::default(), build_scripts: WorkspaceBuildScripts::default(),
sysroot,
rustc, rustc,
cargo_config_extra_env,
},
sysroot,
rustc_cfg, rustc_cfg,
cfg_overrides, cfg_overrides,
toolchain, toolchain,
target_layout: data_layout target_layout: data_layout
.map(Arc::from) .map(Arc::from)
.map_err(|it| Arc::from(it.to_string())), .map_err(|it| Arc::from(it.to_string())),
cargo_config_extra_env,
} }
} }
}; };
@ -425,8 +387,8 @@ impl ProjectWorkspace {
let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config); let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config);
let data_layout = target_data_layout::get(data_layout_config, target, extra_env); let data_layout = target_data_layout::get(data_layout_config, target, extra_env);
ProjectWorkspace::Json { ProjectWorkspace {
project: project_json, kind: ProjectWorkspaceKind::Json(project_json),
sysroot, sysroot,
rustc_cfg, rustc_cfg,
toolchain, toolchain,
@ -484,14 +446,19 @@ impl ProjectWorkspace {
) )
}); });
Ok(ProjectWorkspace::DetachedFile { let cargo_config_extra_env =
cargo_config_env(detached_file, &config.extra_env, sysroot_ref);
Ok(ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile {
file: detached_file.to_owned(), file: detached_file.to_owned(),
cargo_script,
cargo_config_extra_env,
},
sysroot, sysroot,
rustc_cfg, rustc_cfg,
toolchain, toolchain,
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
cfg_overrides: config.cfg_overrides.clone(), cfg_overrides: config.cfg_overrides.clone(),
cargo_script,
}) })
} }
@ -508,27 +475,22 @@ impl ProjectWorkspace {
config: &CargoConfig, config: &CargoConfig,
progress: &dyn Fn(String), progress: &dyn Fn(String),
) -> anyhow::Result<WorkspaceBuildScripts> { ) -> anyhow::Result<WorkspaceBuildScripts> {
match self { match &self.kind {
ProjectWorkspace::DetachedFile { ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. }
cargo_script: Some((cargo, _)), | ProjectWorkspaceKind::Cargo { cargo, .. } => {
toolchain,
sysroot,
..
}
| ProjectWorkspace::Cargo { cargo, toolchain, sysroot, .. } => {
WorkspaceBuildScripts::run_for_workspace( WorkspaceBuildScripts::run_for_workspace(
config, config,
cargo, cargo,
progress, progress,
toolchain, &self.toolchain,
sysroot.as_ref().ok(), self.sysroot.as_ref().ok(),
) )
.with_context(|| { .with_context(|| {
format!("Failed to run build scripts for {}", cargo.workspace_root()) format!("Failed to run build scripts for {}", cargo.workspace_root())
}) })
} }
ProjectWorkspace::DetachedFile { cargo_script: None, .. } ProjectWorkspaceKind::DetachedFile { cargo_script: None, .. }
| ProjectWorkspace::Json { .. } => Ok(WorkspaceBuildScripts::default()), | ProjectWorkspaceKind::Json { .. } => Ok(WorkspaceBuildScripts::default()),
} }
} }
@ -548,8 +510,8 @@ impl ProjectWorkspace {
let cargo_ws: Vec<_> = workspaces let cargo_ws: Vec<_> = workspaces
.iter() .iter()
.filter_map(|it| match it { .filter_map(|it| match &it.kind {
ProjectWorkspace::Cargo { cargo, .. } => Some(cargo), ProjectWorkspaceKind::Cargo { cargo, .. } => Some(cargo),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -563,8 +525,8 @@ impl ProjectWorkspace {
workspaces workspaces
.iter() .iter()
.map(|it| match it { .map(|it| match &it.kind {
ProjectWorkspace::Cargo { cargo, .. } => match outputs { ProjectWorkspaceKind::Cargo { cargo, .. } => match outputs {
Ok(outputs) => Ok(outputs.next().unwrap()), Ok(outputs) => Ok(outputs.next().unwrap()),
Err(e) => Err(e.clone()).with_context(|| { Err(e) => Err(e.clone()).with_context(|| {
format!("Failed to run build scripts for {}", cargo.workspace_root()) format!("Failed to run build scripts for {}", cargo.workspace_root())
@ -576,40 +538,33 @@ impl ProjectWorkspace {
} }
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) { pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
match self { match &mut self.kind {
ProjectWorkspace::Cargo { build_scripts, .. } ProjectWorkspaceKind::Cargo { build_scripts, .. }
| ProjectWorkspace::DetachedFile { cargo_script: Some((_, build_scripts)), .. } => { | ProjectWorkspaceKind::DetachedFile {
*build_scripts = bs cargo_script: Some((_, build_scripts)), ..
} } => *build_scripts = bs,
_ => assert_eq!(bs, WorkspaceBuildScripts::default()), _ => assert_eq!(bs, WorkspaceBuildScripts::default()),
} }
} }
pub fn workspace_definition_path(&self) -> &AbsPath { pub fn manifest_or_root(&self) -> &AbsPath {
match self { match &self.kind {
ProjectWorkspace::Cargo { cargo, .. } => cargo.workspace_root(), ProjectWorkspaceKind::Cargo { cargo, .. } => cargo.manifest_path(),
ProjectWorkspace::Json { project, .. } => project.path(), ProjectWorkspaceKind::Json(project) => project.path(),
ProjectWorkspace::DetachedFile { file, .. } => file, ProjectWorkspaceKind::DetachedFile { file, .. } => file,
} }
} }
pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> { pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
match self { match &self.sysroot {
ProjectWorkspace::Cargo { sysroot: Ok(sysroot), .. } Ok(sysroot) => sysroot.discover_proc_macro_srv(),
| ProjectWorkspace::Json { sysroot: Ok(sysroot), .. } Err(None) => Err(anyhow::format_err!(
| ProjectWorkspace::DetachedFile { sysroot: Ok(sysroot), .. } => { "cannot find proc-macro server, the workspace `{}` is missing a sysroot",
sysroot.discover_proc_macro_srv() self.manifest_or_root()
}
ProjectWorkspace::DetachedFile { .. } => {
Err(anyhow::format_err!("cannot find proc-macro server, no sysroot was found"))
}
ProjectWorkspace::Cargo { cargo, .. } => Err(anyhow::format_err!(
"cannot find proc-macro-srv, the workspace `{}` is missing a sysroot",
cargo.workspace_root()
)), )),
ProjectWorkspace::Json { project, .. } => Err(anyhow::format_err!( Err(Some(e)) => Err(anyhow::format_err!(
"cannot find proc-macro-srv, the workspace `{}` is missing a sysroot", "cannot find proc-macro server, the workspace `{}` is missing a sysroot: {e}",
project.path() self.manifest_or_root()
)), )),
} }
} }
@ -618,8 +573,8 @@ impl ProjectWorkspace {
/// The return type contains the path and whether or not /// The return type contains the path and whether or not
/// the root is a member of the current workspace /// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> { pub fn to_roots(&self) -> Vec<PackageRoot> {
let mk_sysroot = |sysroot: Result<_, _>| { let mk_sysroot = || {
sysroot.into_iter().flat_map(move |sysroot: &Sysroot| { self.sysroot.as_ref().into_iter().flat_map(move |sysroot: &Sysroot| {
let mut r = match sysroot.mode() { let mut r = match sysroot.mode() {
SysrootMode::Workspace(ws) => ws SysrootMode::Workspace(ws) => ws
.packages() .packages()
@ -653,15 +608,8 @@ impl ProjectWorkspace {
r r
}) })
}; };
match self { match &self.kind {
ProjectWorkspace::Json { ProjectWorkspaceKind::Json(project) => project
project,
sysroot,
rustc_cfg: _,
toolchain: _,
target_layout: _,
cfg_overrides: _,
} => project
.crates() .crates()
.map(|(_, krate)| PackageRoot { .map(|(_, krate)| PackageRoot {
is_local: krate.is_workspace_member, is_local: krate.is_workspace_member,
@ -670,17 +618,12 @@ impl ProjectWorkspace {
}) })
.collect::<FxHashSet<_>>() .collect::<FxHashSet<_>>()
.into_iter() .into_iter()
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
ProjectWorkspace::Cargo { ProjectWorkspaceKind::Cargo {
cargo, cargo,
sysroot,
rustc, rustc,
rustc_cfg: _,
cfg_overrides: _,
build_scripts, build_scripts,
toolchain: _,
target_layout: _,
cargo_config_extra_env: _, cargo_config_extra_env: _,
} => { } => {
cargo cargo
@ -721,7 +664,7 @@ impl ProjectWorkspace {
} }
PackageRoot { is_local, include, exclude } PackageRoot { is_local, include, exclude }
}) })
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot())
.chain(rustc.iter().map(|a| a.as_ref()).flat_map(|(rustc, _)| { .chain(rustc.iter().map(|a| a.as_ref()).flat_map(|(rustc, _)| {
rustc.packages().map(move |krate| PackageRoot { rustc.packages().map(move |krate| PackageRoot {
is_local: false, is_local: false,
@ -731,7 +674,7 @@ impl ProjectWorkspace {
})) }))
.collect() .collect()
} }
ProjectWorkspace::DetachedFile { file, cargo_script, sysroot, .. } => { ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => {
iter::once(PackageRoot { iter::once(PackageRoot {
is_local: true, is_local: true,
include: vec![file.as_ref().to_owned()], include: vec![file.as_ref().to_owned()],
@ -775,26 +718,26 @@ impl ProjectWorkspace {
PackageRoot { is_local, include, exclude } PackageRoot { is_local, include, exclude }
}) })
})) }))
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot())
.collect() .collect()
} }
} }
} }
pub fn n_packages(&self) -> usize { pub fn n_packages(&self) -> usize {
match self { match &self.kind {
ProjectWorkspace::Json { project, sysroot, .. } => { ProjectWorkspaceKind::Json(project) => {
let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
sysroot_package_len + project.n_crates() sysroot_package_len + project.n_crates()
} }
ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => { ProjectWorkspaceKind::Cargo { cargo, rustc, .. } => {
let rustc_package_len = let rustc_package_len =
rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len()); rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len());
let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
cargo.packages().len() + sysroot_package_len + rustc_package_len cargo.packages().len() + sysroot_package_len + rustc_package_len
} }
ProjectWorkspace::DetachedFile { sysroot, cargo_script, .. } => { ProjectWorkspaceKind::DetachedFile { cargo_script, .. } => {
let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
sysroot_package_len sysroot_package_len
+ cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len()) + cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len())
} }
@ -808,15 +751,9 @@ impl ProjectWorkspace {
) -> (CrateGraph, ProcMacroPaths) { ) -> (CrateGraph, ProcMacroPaths) {
let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered(); let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
let ((mut crate_graph, proc_macros), sysroot) = match self { let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
ProjectWorkspace::Json { let ((mut crate_graph, proc_macros), sysroot) = match kind {
project, ProjectWorkspaceKind::Json(project) => (
sysroot,
rustc_cfg,
toolchain: _,
target_layout: _,
cfg_overrides,
} => (
project_json_to_crate_graph( project_json_to_crate_graph(
rustc_cfg.clone(), rustc_cfg.clone(),
load, load,
@ -827,15 +764,10 @@ impl ProjectWorkspace {
), ),
sysroot, sysroot,
), ),
ProjectWorkspace::Cargo { ProjectWorkspaceKind::Cargo {
cargo, cargo,
sysroot,
rustc, rustc,
rustc_cfg,
cfg_overrides,
build_scripts, build_scripts,
toolchain: _,
target_layout: _,
cargo_config_extra_env: _, cargo_config_extra_env: _,
} => ( } => (
cargo_to_crate_graph( cargo_to_crate_graph(
@ -849,15 +781,7 @@ impl ProjectWorkspace {
), ),
sysroot, sysroot,
), ),
ProjectWorkspace::DetachedFile { ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => (
file,
sysroot,
rustc_cfg,
toolchain: _,
target_layout: _,
cfg_overrides,
cargo_script,
} => (
if let Some((cargo, build_scripts)) = cargo_script { if let Some((cargo, build_scripts)) = cargo_script {
cargo_to_crate_graph( cargo_to_crate_graph(
&mut |path| load(path), &mut |path| load(path),
@ -892,93 +816,60 @@ impl ProjectWorkspace {
} }
pub fn eq_ignore_build_data(&self, other: &Self) -> bool { pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
match (self, other) { let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides, .. } = self;
let Self {
kind: o_kind,
sysroot: o_sysroot,
rustc_cfg: o_rustc_cfg,
toolchain: o_toolchain,
target_layout: o_target_layout,
cfg_overrides: o_cfg_overrides,
..
} = other;
(match (kind, o_kind) {
( (
Self::Cargo { ProjectWorkspaceKind::Cargo {
cargo, cargo,
sysroot,
rustc, rustc,
rustc_cfg,
cfg_overrides,
toolchain,
cargo_config_extra_env, cargo_config_extra_env,
build_scripts: _, build_scripts: _,
target_layout: _,
}, },
Self::Cargo { ProjectWorkspaceKind::Cargo {
cargo: o_cargo, cargo: o_cargo,
sysroot: o_sysroot,
rustc: o_rustc, rustc: o_rustc,
rustc_cfg: o_rustc_cfg,
cfg_overrides: o_cfg_overrides,
toolchain: o_toolchain,
cargo_config_extra_env: o_cargo_config_extra_env, cargo_config_extra_env: o_cargo_config_extra_env,
build_scripts: _, build_scripts: _,
target_layout: _,
}, },
) => { ) => {
cargo == o_cargo cargo == o_cargo
&& rustc == o_rustc && rustc == o_rustc
&& rustc_cfg == o_rustc_cfg
&& cfg_overrides == o_cfg_overrides
&& toolchain == o_toolchain
&& sysroot == o_sysroot
&& cargo_config_extra_env == o_cargo_config_extra_env && cargo_config_extra_env == o_cargo_config_extra_env
} }
( (ProjectWorkspaceKind::Json(project), ProjectWorkspaceKind::Json(o_project)) => {
Self::Json {
project,
sysroot,
rustc_cfg,
toolchain,
target_layout: _,
cfg_overrides,
},
Self::Json {
project: o_project,
sysroot: o_sysroot,
rustc_cfg: o_rustc_cfg,
toolchain: o_toolchain,
target_layout: _,
cfg_overrides: o_cfg_overrides,
},
) => {
project == o_project project == o_project
&& rustc_cfg == o_rustc_cfg
&& sysroot == o_sysroot
&& toolchain == o_toolchain
&& cfg_overrides == o_cfg_overrides
} }
( (
Self::DetachedFile { ProjectWorkspaceKind::DetachedFile {
file, file,
sysroot,
rustc_cfg,
cargo_script: Some((cargo_script, _)), cargo_script: Some((cargo_script, _)),
toolchain, cargo_config_extra_env,
target_layout,
cfg_overrides,
}, },
Self::DetachedFile { ProjectWorkspaceKind::DetachedFile {
file: o_file, file: o_file,
sysroot: o_sysroot,
rustc_cfg: o_rustc_cfg,
cargo_script: Some((o_cargo_script, _)), cargo_script: Some((o_cargo_script, _)),
toolchain: o_toolchain, cargo_config_extra_env: o_cargo_config_extra_env,
target_layout: o_target_layout,
cfg_overrides: o_cfg_overrides,
}, },
) => { ) => {
file == o_file file == o_file
&& sysroot == o_sysroot && cargo_script == o_cargo_script
&& cargo_config_extra_env == o_cargo_config_extra_env
}
_ => return false,
}) && sysroot == o_sysroot
&& rustc_cfg == o_rustc_cfg && rustc_cfg == o_rustc_cfg
&& toolchain == o_toolchain && toolchain == o_toolchain
&& target_layout == o_target_layout && target_layout == o_target_layout
&& cfg_overrides == o_cfg_overrides && cfg_overrides == o_cfg_overrides
&& cargo_script == o_cargo_script
}
_ => false,
}
} }
/// Returns `true` if the project workspace is [`Json`]. /// Returns `true` if the project workspace is [`Json`].
@ -986,7 +877,7 @@ impl ProjectWorkspace {
/// [`Json`]: ProjectWorkspace::Json /// [`Json`]: ProjectWorkspace::Json
#[must_use] #[must_use]
pub fn is_json(&self) -> bool { pub fn is_json(&self) -> bool {
matches!(self, Self::Json { .. }) matches!(self.kind, ProjectWorkspaceKind::Json { .. })
} }
} }

View file

@ -11,7 +11,8 @@ use itertools::Either;
use profile::StopWatch; use profile::StopWatch;
use project_model::target_data_layout::RustcDataLayoutConfig; use project_model::target_data_layout::RustcDataLayoutConfig;
use project_model::{ use project_model::{
target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, RustLibSource, Sysroot, target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind,
RustLibSource, Sysroot,
}; };
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@ -77,14 +78,17 @@ impl Tester {
&cargo_config.extra_env, &cargo_config.extra_env,
); );
let workspace = ProjectWorkspace::DetachedFile { let workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile {
file: ManifestPath::try_from(tmp_file).unwrap(), file: ManifestPath::try_from(tmp_file).unwrap(),
cargo_script: None,
cargo_config_extra_env: Default::default(),
},
sysroot, sysroot,
rustc_cfg: vec![], rustc_cfg: vec![],
toolchain: None, toolchain: None,
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
cfg_overrides: Default::default(), cfg_overrides: Default::default(),
cargo_script: None,
}; };
let load_cargo_config = LoadCargoConfig { let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: false, load_out_dirs_from_check: false,

View file

@ -19,7 +19,8 @@ use parking_lot::{
}; };
use proc_macro_api::ProcMacroServer; use proc_macro_api::ProcMacroServer;
use project_model::{ use project_model::{
CargoWorkspace, ManifestPath, ProjectWorkspace, Target, WorkspaceBuildScripts, CargoWorkspace, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, Target,
WorkspaceBuildScripts,
}; };
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use triomphe::Arc; use triomphe::Arc;
@ -518,12 +519,13 @@ impl GlobalStateSnapshot {
let file_id = self.analysis.crate_root(crate_id).ok()?; let file_id = self.analysis.crate_root(crate_id).ok()?;
let path = self.vfs_read().file_path(file_id).clone(); let path = self.vfs_read().file_path(file_id).clone();
let path = path.as_path()?; let path = path.as_path()?;
self.workspaces.iter().find_map(|ws| match ws { self.workspaces.iter().find_map(|ws| match &ws.kind {
ProjectWorkspace::Cargo { cargo, .. } => { ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => {
cargo.target_by_root(path).map(|it| (cargo, it)) cargo.target_by_root(path).map(|it| (cargo, it))
} }
ProjectWorkspace::Json { .. } => None, ProjectWorkspaceKind::Json { .. } => None,
ProjectWorkspace::DetachedFile { .. } => None, ProjectWorkspaceKind::DetachedFile { .. } => None,
}) })
} }

View file

@ -289,17 +289,19 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
// Find all workspaces that have at least one target containing the saved file // Find all workspaces that have at least one target containing the saved file
let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| { let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
let package = match ws { let package = match &ws.kind {
project_model::ProjectWorkspace::Cargo { cargo, .. } => { project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
cargo.packages().find_map(|pkg| { | project_model::ProjectWorkspaceKind::DetachedFile {
cargo_script: Some((cargo, _)),
..
} => cargo.packages().find_map(|pkg| {
let has_target_with_root = cargo[pkg] let has_target_with_root = cargo[pkg]
.targets .targets
.iter() .iter()
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path())); .any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
has_target_with_root.then(|| cargo[pkg].name.clone()) has_target_with_root.then(|| cargo[pkg].name.clone())
}) }),
} project_model::ProjectWorkspaceKind::Json(project) => {
project_model::ProjectWorkspace::Json { project, .. } => {
if !project.crates().any(|(_, krate)| { if !project.crates().any(|(_, krate)| {
crate_root_paths.contains(&krate.root_module.as_path()) crate_root_paths.contains(&krate.root_module.as_path())
}) { }) {
@ -307,8 +309,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
} }
None None
} }
// FIXME project_model::ProjectWorkspaceKind::DetachedFile { .. } => return None,
project_model::ProjectWorkspace::DetachedFile { .. } => return None,
}; };
Some((idx, package)) Some((idx, package))
}); });

View file

@ -27,7 +27,7 @@ use lsp_types::{
SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit, SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
}; };
use paths::Utf8PathBuf; use paths::Utf8PathBuf;
use project_model::{ManifestPath, ProjectWorkspace, TargetKind}; use project_model::{ManifestPath, ProjectWorkspaceKind, TargetKind};
use serde_json::json; use serde_json::json;
use stdx::{format_to, never}; use stdx::{format_to, never};
use syntax::{algo, ast, AstNode, TextRange, TextSize}; use syntax::{algo, ast, AstNode, TextRange, TextSize};
@ -99,10 +99,7 @@ pub(crate) fn handle_analyzer_status(
format_to!( format_to!(
buf, buf,
"Workspace root folders: {:?}", "Workspace root folders: {:?}",
snap.workspaces snap.workspaces.iter().map(|ws| ws.manifest_or_root()).collect::<Vec<&AbsPath>>()
.iter()
.map(|ws| ws.workspace_definition_path())
.collect::<Vec<&AbsPath>>()
); );
} }
buf.push_str("\nAnalysis:\n"); buf.push_str("\nAnalysis:\n");
@ -228,7 +225,7 @@ pub(crate) fn handle_run_test(
}; };
let mut handles = vec![]; let mut handles = vec![];
for ws in &*state.workspaces { for ws in &*state.workspaces {
if let ProjectWorkspace::Cargo { cargo, .. } = ws { if let ProjectWorkspaceKind::Cargo { cargo, .. } = &ws.kind {
let handle = flycheck::CargoTestHandle::new( let handle = flycheck::CargoTestHandle::new(
test_path, test_path,
state.config.cargo_test_options(), state.config.cargo_test_options(),
@ -769,8 +766,10 @@ pub(crate) fn handle_parent_module(
let links: Vec<LocationLink> = snap let links: Vec<LocationLink> = snap
.workspaces .workspaces
.iter() .iter()
.filter_map(|ws| match ws { .filter_map(|ws| match &ws.kind {
ProjectWorkspace::Cargo { cargo, .. } => cargo.parent_manifests(&manifest_path), ProjectWorkspaceKind::Cargo { cargo, .. } => {
cargo.parent_manifests(&manifest_path)
}
_ => None, _ => None,
}) })
.flatten() .flatten()
@ -1758,13 +1757,13 @@ pub(crate) fn handle_open_docs(
let _p = tracing::span!(tracing::Level::INFO, "handle_open_docs").entered(); let _p = tracing::span!(tracing::Level::INFO, "handle_open_docs").entered();
let position = from_proto::file_position(&snap, params)?; let position = from_proto::file_position(&snap, params)?;
let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws { let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
ProjectWorkspace::Cargo { cargo, sysroot, .. } ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspace::DetachedFile { cargo_script: Some((cargo, _)), sysroot, .. } => { | ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => {
Some((cargo, sysroot.as_ref().ok())) Some((cargo, ws.sysroot.as_ref().ok()))
} }
ProjectWorkspace::Json { .. } => None, ProjectWorkspaceKind::Json { .. } => None,
ProjectWorkspace::DetachedFile { .. } => None, ProjectWorkspaceKind::DetachedFile { .. } => None,
}); });
let (cargo, sysroot) = match ws_and_sysroot { let (cargo, sysroot) = match ws_and_sysroot {

View file

@ -25,7 +25,7 @@ use ide_db::{
use itertools::Itertools; use itertools::Itertools;
use load_cargo::{load_proc_macro, ProjectFolders}; use load_cargo::{load_proc_macro, ProjectFolders};
use proc_macro_api::ProcMacroServer; use proc_macro_api::ProcMacroServer;
use project_model::{ManifestPath, ProjectWorkspace, WorkspaceBuildScripts}; use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
use stdx::{format_to, thread::ThreadIntent}; use stdx::{format_to, thread::ThreadIntent};
use triomphe::Arc; use triomphe::Arc;
use vfs::{AbsPath, AbsPathBuf, ChangeKind}; use vfs::{AbsPath, AbsPathBuf, ChangeKind};
@ -151,9 +151,7 @@ impl GlobalState {
} }
for ws in self.workspaces.iter() { for ws in self.workspaces.iter() {
let (ProjectWorkspace::Cargo { sysroot, .. } let sysroot = ws.sysroot.as_ref();
| ProjectWorkspace::Json { sysroot, .. }
| ProjectWorkspace::DetachedFile { sysroot, .. }) = ws;
match sysroot { match sysroot {
Err(None) => (), Err(None) => (),
Err(Some(e)) => { Err(Some(e)) => {
@ -169,7 +167,7 @@ impl GlobalState {
} }
} }
} }
if let ProjectWorkspace::Cargo { rustc: Err(Some(e)), .. } = ws { if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
status.health = lsp_ext::Health::Warning; status.health = lsp_ext::Health::Warning;
message.push_str(e); message.push_str(e);
message.push_str("\n\n"); message.push_str("\n\n");
@ -501,18 +499,23 @@ impl GlobalState {
None => ws.find_sysroot_proc_macro_srv()?, None => ws.find_sysroot_proc_macro_srv()?,
}; };
let env = let env = match &ws.kind {
match ws { ProjectWorkspaceKind::Cargo { cargo_config_extra_env, .. }
ProjectWorkspace::Cargo { cargo_config_extra_env, sysroot, .. } => { | ProjectWorkspaceKind::DetachedFile {
cargo_config_extra_env cargo_script: Some(_),
cargo_config_extra_env,
..
} => cargo_config_extra_env
.iter() .iter()
.chain(self.config.extra_env()) .chain(self.config.extra_env())
.map(|(a, b)| (a.clone(), b.clone())) .map(|(a, b)| (a.clone(), b.clone()))
.chain(sysroot.as_ref().map(|it| { .chain(
("RUSTUP_TOOLCHAIN".to_owned(), it.root().to_string()) ws.sysroot
})) .as_ref()
.collect() .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), it.root().to_string())),
} )
.collect(),
_ => Default::default(), _ => Default::default(),
}; };
tracing::info!("Using proc-macro server at {path}"); tracing::info!("Using proc-macro server at {path}");
@ -561,8 +564,8 @@ impl GlobalState {
self.detached_files = self self.detached_files = self
.workspaces .workspaces
.iter() .iter()
.filter_map(|ws| match ws { .filter_map(|ws| match &ws.kind {
ProjectWorkspace::DetachedFile { file, .. } => Some(file.clone()), ProjectWorkspaceKind::DetachedFile { file, .. } => Some(file.clone()),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -671,26 +674,29 @@ impl GlobalState {
self.workspaces self.workspaces
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(id, w)| match w { .filter_map(|(id, ws)| match &ws.kind {
ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some(( ProjectWorkspaceKind::Cargo { cargo, .. } => Some((
id, id,
cargo.workspace_root(), cargo.workspace_root(),
sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()), ws.sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
)), )),
ProjectWorkspace::Json { project, sysroot, .. } => { ProjectWorkspaceKind::Json(project) => {
// Enable flychecks for json projects if a custom flycheck command was supplied // Enable flychecks for json projects if a custom flycheck command was supplied
// in the workspace configuration. // in the workspace configuration.
match config { match config {
FlycheckConfig::CustomCommand { .. } => Some(( FlycheckConfig::CustomCommand { .. } => Some((
id, id,
project.path(), project.path(),
sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()), ws.sysroot
.as_ref()
.ok()
.map(|sysroot| sysroot.root().to_owned()),
)), )),
_ => None, _ => None,
} }
} }
// FIXME // FIXME
ProjectWorkspace::DetachedFile { .. } => None, ProjectWorkspaceKind::DetachedFile { .. } => None,
}) })
.map(|(id, root, sysroot_root)| { .map(|(id, root, sysroot_root)| {
let sender = sender.clone(); let sender = sender.clone();
@ -729,9 +735,7 @@ pub fn ws_to_crate_graph(
let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env); let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env);
let num_layouts = layouts.len(); let num_layouts = layouts.len();
let num_toolchains = toolchains.len(); let num_toolchains = toolchains.len();
let (ProjectWorkspace::Cargo { toolchain, target_layout, .. } let ProjectWorkspace { toolchain, target_layout, .. } = ws;
| ProjectWorkspace::Json { toolchain, target_layout, .. }
| ProjectWorkspace::DetachedFile { toolchain, target_layout, .. }) = ws;
let mapping = crate_graph.extend( let mapping = crate_graph.extend(
other, other,

View file

@ -1,7 +1,8 @@
use std::path::PathBuf; use std::path::PathBuf;
use project_model::{ use project_model::{
CargoWorkspace, ManifestPath, Metadata, ProjectWorkspace, Sysroot, WorkspaceBuildScripts, CargoWorkspace, ManifestPath, Metadata, ProjectWorkspace, ProjectWorkspaceKind, Sysroot,
WorkspaceBuildScripts,
}; };
use rust_analyzer::ws_to_crate_graph; use rust_analyzer::ws_to_crate_graph;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -13,16 +14,18 @@ fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
let manifest_path = let manifest_path =
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap(); ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
let cargo_workspace = CargoWorkspace::new(meta, manifest_path); let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
ProjectWorkspace::Cargo { ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo: cargo_workspace, cargo: cargo_workspace,
build_scripts: WorkspaceBuildScripts::default(), build_scripts: WorkspaceBuildScripts::default(),
sysroot: Ok(get_fake_sysroot()),
rustc: Err(None), rustc: Err(None),
cargo_config_extra_env: Default::default(),
},
sysroot: Ok(get_fake_sysroot()),
rustc_cfg: Vec::new(), rustc_cfg: Vec::new(),
cfg_overrides: Default::default(), cfg_overrides: Default::default(),
toolchain: None, toolchain: None,
target_layout: Err("target_data_layout not loaded".into()), target_layout: Err("target_data_layout not loaded".into()),
cargo_config_extra_env: Default::default(),
} }
} }

View file

@ -150,7 +150,7 @@ use dependency2::Spam;
) )
.with_config(serde_json::json!({ .with_config(serde_json::json!({
"cargo": { "sysroot": null }, "cargo": { "sysroot": null },
"detachedFiles": ["/src/lib.rs"], "linkedProjects": ["src/lib.rs"],
})) }))
.server() .server()
.wait_until_workspace_is_loaded(); .wait_until_workspace_is_loaded();