Unnamed repository; edit this file 'description' to name the repository.
fix: Resolve `target-dir` more precisely
Shoyu Vanilla 6 months ago
parent f7a13f0 · commit 5f3539a
-rw-r--r--crates/project-model/src/build_dependencies.rs10
-rw-r--r--crates/project-model/src/cargo_workspace.rs34
-rw-r--r--crates/project-model/src/lib.rs2
-rw-r--r--crates/project-model/src/sysroot.rs7
-rw-r--r--crates/project-model/src/tests.rs8
-rw-r--r--crates/project-model/src/workspace.rs72
-rw-r--r--crates/rust-analyzer/src/cli/rustc_tests.rs9
-rw-r--r--crates/rust-analyzer/src/config.rs61
-rw-r--r--crates/rust-analyzer/src/flycheck.rs46
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs1
-rw-r--r--crates/rust-analyzer/src/reload.rs13
-rw-r--r--crates/rust-analyzer/src/test_runner.rs5
12 files changed, 132 insertions, 136 deletions
diff --git a/crates/project-model/src/build_dependencies.rs b/crates/project-model/src/build_dependencies.rs
index 3a682d5a4d..fedc6944f5 100644
--- a/crates/project-model/src/build_dependencies.rs
+++ b/crates/project-model/src/build_dependencies.rs
@@ -86,6 +86,7 @@ impl WorkspaceBuildScripts {
config,
&allowed_features,
workspace.manifest_path(),
+ workspace.target_directory().as_ref(),
current_dir,
sysroot,
toolchain,
@@ -106,8 +107,9 @@ impl WorkspaceBuildScripts {
let (_guard, cmd) = Self::build_command(
config,
&Default::default(),
- // This is not gonna be used anyways, so just construct a dummy here
+ // These are not gonna be used anyways, so just construct a dummy here
&ManifestPath::try_from(working_directory.clone()).unwrap(),
+ working_directory.as_ref(),
working_directory,
&Sysroot::empty(),
None,
@@ -430,6 +432,7 @@ impl WorkspaceBuildScripts {
config: &CargoConfig,
allowed_features: &FxHashSet<String>,
manifest_path: &ManifestPath,
+ target_dir: &Utf8Path,
current_dir: &AbsPath,
sysroot: &Sysroot,
toolchain: Option<&semver::Version>,
@@ -450,8 +453,9 @@ impl WorkspaceBuildScripts {
cmd.arg("--manifest-path");
cmd.arg(manifest_path);
- if let Some(target_dir) = &config.target_dir {
- cmd.arg("--target-dir").arg(target_dir);
+ if let Some(target_dir) = config.target_dir_config.target_dir(Some(target_dir)) {
+ cmd.arg("--target-dir");
+ cmd.arg(target_dir.as_ref());
}
if let Some(target) = &config.target {
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 76ba01f3a2..731104981a 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -1,7 +1,6 @@
//! See [`CargoWorkspace`].
-use std::ops;
-use std::str::from_utf8;
+use std::{borrow::Cow, ops, str::from_utf8};
use anyhow::Context;
use base_db::Env;
@@ -95,6 +94,29 @@ impl Default for CargoFeatures {
}
}
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum TargetDirectoryConfig {
+ #[default]
+ None,
+ UseSubdirectory,
+ Directory(Utf8PathBuf),
+}
+
+impl TargetDirectoryConfig {
+ pub fn target_dir<'a>(
+ &'a self,
+ ws_target_dir: Option<&'a Utf8Path>,
+ ) -> Option<Cow<'a, Utf8Path>> {
+ match self {
+ TargetDirectoryConfig::None => None,
+ TargetDirectoryConfig::UseSubdirectory => {
+ Some(Cow::Owned(ws_target_dir?.join("rust-analyzer")))
+ }
+ TargetDirectoryConfig::Directory(dir) => Some(Cow::Borrowed(dir)),
+ }
+ }
+}
+
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CargoConfig {
/// Whether to pass `--all-targets` to cargo invocations.
@@ -121,7 +143,7 @@ pub struct CargoConfig {
pub extra_env: FxHashMap<String, Option<String>>,
pub invocation_strategy: InvocationStrategy,
/// Optional path to use instead of `target` when building
- pub target_dir: Option<Utf8PathBuf>,
+ pub target_dir_config: TargetDirectoryConfig,
/// Gate `#[test]` behind `#[cfg(test)]`
pub set_test: bool,
/// Load the project without any dependencies
@@ -715,21 +737,15 @@ impl FetchMetadata {
}
}
- pub(crate) fn no_deps_metadata(&self) -> Option<&cargo_metadata::Metadata> {
- self.no_deps_result.as_ref().ok()
- }
-
/// Executes the metadata-fetching command.
///
/// A successful result may still contain a metadata error if the full fetch failed,
/// but the fallback `--no-deps` pre-fetch succeeded during command construction.
pub(crate) fn exec(
self,
- target_dir: &Utf8Path,
locked: bool,
progress: &dyn Fn(String),
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
- _ = target_dir;
let Self {
mut command,
manifest_path: _,
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index e36b904881..910bc0a96b 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -62,7 +62,7 @@ pub use crate::{
build_dependencies::{ProcMacroDylibPath, WorkspaceBuildScripts},
cargo_workspace::{
CargoConfig, CargoFeatures, CargoMetadataConfig, CargoWorkspace, Package, PackageData,
- PackageDependency, RustLibSource, Target, TargetData, TargetKind,
+ PackageDependency, RustLibSource, Target, TargetData, TargetDirectoryConfig, TargetKind,
},
manifest_path::ManifestPath,
project_json::{ProjectJson, ProjectJsonData},
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index 5cc399bfe7..920afe65d7 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -9,7 +9,7 @@ use std::{env, fs, ops::Not, path::Path, process::Command};
use anyhow::{Result, format_err};
use itertools::Itertools;
-use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
use rustc_hash::FxHashMap;
use stdx::format_to;
use toolchain::{Tool, probe_for_binary};
@@ -219,7 +219,6 @@ impl Sysroot {
&self,
sysroot_source_config: &RustSourceWorkspaceConfig,
no_deps: bool,
- target_dir: &Utf8Path,
progress: &dyn Fn(String),
) -> Option<RustLibSrcWorkspace> {
assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded");
@@ -233,7 +232,6 @@ impl Sysroot {
match self.load_library_via_cargo(
&library_manifest,
src_root,
- target_dir,
cargo_config,
no_deps,
progress,
@@ -328,7 +326,6 @@ impl Sysroot {
&self,
library_manifest: &ManifestPath,
current_dir: &AbsPath,
- target_dir: &Utf8Path,
cargo_config: &CargoMetadataConfig,
no_deps: bool,
progress: &dyn Fn(String),
@@ -345,7 +342,7 @@ impl Sysroot {
let locked = true;
let (mut res, err) =
FetchMetadata::new(library_manifest, current_dir, &cargo_config, self, no_deps)
- .exec(target_dir, locked, progress)?;
+ .exec(locked, progress)?;
// Patch out `rustc-std-workspace-*` crates to point to the real crates.
// This is done prior to `CrateGraph` construction to prevent de-duplication logic from failing.
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 711cdd11b9..1908fc0290 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -238,12 +238,8 @@ fn smoke_test_real_sysroot_cargo() {
);
let cwd = AbsPathBuf::assert_utf8(temp_dir().join("smoke_test_real_sysroot_cargo"));
std::fs::create_dir_all(&cwd).unwrap();
- let loaded_sysroot = sysroot.load_workspace(
- &RustSourceWorkspaceConfig::default_cargo(),
- false,
- &Utf8PathBuf::default(),
- &|_| (),
- );
+ let loaded_sysroot =
+ sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), false, &|_| ());
if let Some(loaded_sysroot) = loaded_sysroot {
sysroot.set_workspace(loaded_sysroot);
}
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index b88db41957..3c69625685 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -16,7 +16,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
use rustc_hash::{FxHashMap, FxHashSet};
use semver::Version;
use span::{Edition, FileId};
-use toolchain::{NO_RUSTUP_AUTO_INSTALL_ENV, Tool};
+use toolchain::Tool;
use tracing::instrument;
use tracing::{debug, error, info};
use triomphe::Arc;
@@ -295,11 +295,6 @@ impl ProjectWorkspace {
&sysroot,
*no_deps,
);
- let target_dir = config
- .target_dir
- .clone()
- .or_else(|| fetch_metadata.no_deps_metadata().map(|m| m.target_directory.clone()))
- .unwrap_or_else(|| workspace_dir.join("target").into());
// We spawn a bunch of processes to query various information about the workspace's
// toolchain and sysroot
@@ -345,7 +340,7 @@ impl ProjectWorkspace {
},
&sysroot,
*no_deps,
- ).exec(&target_dir, true, progress) {
+ ).exec(true, progress) {
Ok((meta, _error)) => {
let workspace = CargoWorkspace::new(
meta,
@@ -374,7 +369,7 @@ impl ProjectWorkspace {
})
});
- let cargo_metadata = s.spawn(|| fetch_metadata.exec(&target_dir, false, progress));
+ let cargo_metadata = s.spawn(|| fetch_metadata.exec(false, progress));
let loaded_sysroot = s.spawn(|| {
sysroot.load_workspace(
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
@@ -383,7 +378,6 @@ impl ProjectWorkspace {
toolchain.clone(),
)),
config.no_deps,
- &target_dir,
progress,
)
});
@@ -463,12 +457,6 @@ impl ProjectWorkspace {
let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
.unwrap_or_default();
let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
- let project_root = project_json.project_root();
- let target_dir = config
- .target_dir
- .clone()
- .or_else(|| cargo_target_dir(project_json.manifest()?, &config.extra_env, &sysroot))
- .unwrap_or_else(|| project_root.join("target").into());
// We spawn a bunch of processes to query various information about the workspace's
// toolchain and sysroot
@@ -486,7 +474,6 @@ impl ProjectWorkspace {
sysroot.load_workspace(
&RustSourceWorkspaceConfig::Json(*sysroot_project),
config.no_deps,
- &target_dir,
progress,
)
} else {
@@ -497,7 +484,6 @@ impl ProjectWorkspace {
toolchain.clone(),
)),
config.no_deps,
- &target_dir,
progress,
)
}
@@ -545,11 +531,6 @@ impl ProjectWorkspace {
.unwrap_or_default();
let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
let target_data = target_data::get(query_config, None, &config.extra_env);
- let target_dir = config
- .target_dir
- .clone()
- .or_else(|| cargo_target_dir(detached_file, &config.extra_env, &sysroot))
- .unwrap_or_else(|| dir.join("target").into());
let loaded_sysroot = sysroot.load_workspace(
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
@@ -558,7 +539,6 @@ impl ProjectWorkspace {
toolchain.clone(),
)),
config.no_deps,
- &target_dir,
&|_| (),
);
if let Some(loaded_sysroot) = loaded_sysroot {
@@ -579,21 +559,15 @@ impl ProjectWorkspace {
&sysroot,
config.no_deps,
);
- let target_dir = config
- .target_dir
- .clone()
- .or_else(|| fetch_metadata.no_deps_metadata().map(|m| m.target_directory.clone()))
- .unwrap_or_else(|| dir.join("target").into());
- let cargo_script =
- fetch_metadata.exec(&target_dir, false, &|_| ()).ok().map(|(ws, error)| {
- let cargo_config_extra_env =
- cargo_config_env(detached_file, &config_file, &config.extra_env);
- (
- CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env, false),
- WorkspaceBuildScripts::default(),
- error.map(Arc::new),
- )
- });
+ let cargo_script = fetch_metadata.exec(false, &|_| ()).ok().map(|(ws, error)| {
+ let cargo_config_extra_env =
+ cargo_config_env(detached_file, &config_file, &config.extra_env);
+ (
+ CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env, false),
+ WorkspaceBuildScripts::default(),
+ error.map(Arc::new),
+ )
+ });
Ok(ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile {
@@ -1902,25 +1876,3 @@ fn sysroot_metadata_config(
kind: "sysroot",
}
}
-
-fn cargo_target_dir(
- manifest: &ManifestPath,
- extra_env: &FxHashMap<String, Option<String>>,
- sysroot: &Sysroot,
-) -> Option<Utf8PathBuf> {
- let cargo = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env);
- let mut meta = cargo_metadata::MetadataCommand::new();
- meta.env(NO_RUSTUP_AUTO_INSTALL_ENV.0, NO_RUSTUP_AUTO_INSTALL_ENV.1);
- meta.cargo_path(cargo.get_program());
- meta.manifest_path(manifest);
- // `--no-deps` doesn't (over)write lockfiles as it doesn't do any package resolve.
- // So we can use it to get `target_directory` before copying lockfiles
- meta.no_deps();
- let mut other_options = vec![];
- if manifest.is_rust_manifest() {
- meta.env("RUSTC_BOOTSTRAP", "1");
- other_options.push("-Zscript".to_owned());
- }
- meta.other_options(other_options);
- meta.exec().map(|m| m.target_directory).ok()
-}
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index 20567149bb..eb28a47ec0 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -9,7 +9,6 @@ use hir::{ChangeWithProcMacros, Crate};
use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
use ide_db::base_db;
use itertools::Either;
-use paths::Utf8PathBuf;
use profile::StopWatch;
use project_model::toolchain_info::{QueryConfig, target_data};
use project_model::{
@@ -75,12 +74,8 @@ impl Tester {
};
let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
- let loaded_sysroot = sysroot.load_workspace(
- &RustSourceWorkspaceConfig::default_cargo(),
- false,
- &Utf8PathBuf::default(),
- &|_| (),
- );
+ let loaded_sysroot =
+ sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), false, &|_| ());
if let Some(loaded_sysroot) = loaded_sysroot {
sysroot.set_workspace(loaded_sysroot);
}
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 6d2907ee56..10a392a5b7 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -23,7 +23,7 @@ use itertools::{Either, Itertools};
use paths::{Utf8Path, Utf8PathBuf};
use project_model::{
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand,
- ProjectManifest, RustLibSource,
+ ProjectManifest, RustLibSource, TargetDirectoryConfig,
};
use rustc_hash::{FxHashMap, FxHashSet};
use semver::Version;
@@ -2285,7 +2285,7 @@ impl Config {
run_build_script_command: self.cargo_buildScripts_overrideCommand(source_root).clone(),
extra_args: self.cargo_extraArgs(source_root).clone(),
extra_env: self.cargo_extraEnv(source_root).clone(),
- target_dir: self.target_dir_from_config(source_root),
+ target_dir_config: self.target_dir_from_config(source_root),
set_test: *self.cfg_setTest(source_root),
no_deps: *self.cargo_noDeps(source_root),
}
@@ -2373,7 +2373,7 @@ impl Config {
extra_args: self.extra_args(source_root).clone(),
extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(),
extra_env: self.extra_env(source_root).clone(),
- target_dir: self.target_dir_from_config(source_root),
+ target_dir_config: self.target_dir_from_config(source_root),
set_test: true,
}
}
@@ -2431,7 +2431,7 @@ impl Config {
extra_args: self.check_extra_args(source_root),
extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(),
extra_env: self.check_extra_env(source_root),
- target_dir: self.target_dir_from_config(source_root),
+ target_dir_config: self.target_dir_from_config(source_root),
set_test: *self.cfg_setTest(source_root),
},
ansi_color_output: self.color_diagnostic_output(),
@@ -2439,17 +2439,12 @@ impl Config {
}
}
- fn target_dir_from_config(&self, source_root: Option<SourceRootId>) -> Option<Utf8PathBuf> {
- self.cargo_targetDir(source_root).as_ref().and_then(|target_dir| match target_dir {
- TargetDirectory::UseSubdirectory(true) => {
- let env_var = env::var("CARGO_TARGET_DIR").ok();
- let mut path = Utf8PathBuf::from(env_var.as_deref().unwrap_or("target"));
- path.push("rust-analyzer");
- Some(path)
- }
- TargetDirectory::UseSubdirectory(false) => None,
- TargetDirectory::Directory(dir) => Some(dir.clone()),
- })
+ fn target_dir_from_config(&self, source_root: Option<SourceRootId>) -> TargetDirectoryConfig {
+ match &self.cargo_targetDir(source_root) {
+ Some(TargetDirectory::UseSubdirectory(true)) => TargetDirectoryConfig::UseSubdirectory,
+ Some(TargetDirectory::UseSubdirectory(false)) | None => TargetDirectoryConfig::None,
+ Some(TargetDirectory::Directory(dir)) => TargetDirectoryConfig::Directory(dir.clone()),
+ }
}
pub fn check_on_save(&self, source_root: Option<SourceRootId>) -> bool {
@@ -3966,7 +3961,7 @@ fn doc_comment_to_string(doc: &[&str]) -> String {
#[cfg(test)]
mod tests {
- use std::fs;
+ use std::{borrow::Cow, fs};
use test_utils::{ensure_file_contents, project_root};
@@ -4101,9 +4096,13 @@ mod tests {
(config, _, _) = config.apply_change(change);
assert_eq!(config.cargo_targetDir(None), &None);
- assert!(
- matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir.is_none())
- );
+ assert!(matches!(
+ config.flycheck(None),
+ FlycheckConfig::CargoCommand {
+ options: CargoOptions { target_dir_config: TargetDirectoryConfig::None, .. },
+ ..
+ }
+ ));
}
#[test]
@@ -4119,11 +4118,16 @@ mod tests {
(config, _, _) = config.apply_change(change);
assert_eq!(config.cargo_targetDir(None), &Some(TargetDirectory::UseSubdirectory(true)));
- let target =
+ let ws_target_dir =
Utf8PathBuf::from(std::env::var("CARGO_TARGET_DIR").unwrap_or("target".to_owned()));
- assert!(
- matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(target.join("rust-analyzer")))
- );
+ assert!(matches!(
+ config.flycheck(None),
+ FlycheckConfig::CargoCommand {
+ options: CargoOptions { target_dir_config, .. },
+ ..
+ } if target_dir_config.target_dir(Some(&ws_target_dir)).map(Cow::into_owned)
+ == Some(ws_target_dir.join("rust-analyzer"))
+ ));
}
#[test]
@@ -4142,8 +4146,13 @@ mod tests {
config.cargo_targetDir(None),
&Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder")))
);
- assert!(
- matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("other_folder")))
- );
+ assert!(matches!(
+ config.flycheck(None),
+ FlycheckConfig::CargoCommand {
+ options: CargoOptions { target_dir_config, .. },
+ ..
+ } if target_dir_config.target_dir(None).map(Cow::into_owned)
+ == Some(Utf8PathBuf::from("other_folder"))
+ ));
}
}
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index 73a51bba3d..db6743d4e5 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -13,6 +13,7 @@ use crossbeam_channel::{Receiver, Sender, select_biased, unbounded};
use ide_db::FxHashSet;
use itertools::Itertools;
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
+use project_model::TargetDirectoryConfig;
use rustc_hash::FxHashMap;
use serde::Deserialize as _;
use serde_derive::Deserialize;
@@ -46,7 +47,7 @@ pub(crate) struct CargoOptions {
pub(crate) extra_args: Vec<String>,
pub(crate) extra_test_bin_args: Vec<String>,
pub(crate) extra_env: FxHashMap<String, Option<String>>,
- pub(crate) target_dir: Option<Utf8PathBuf>,
+ pub(crate) target_dir_config: TargetDirectoryConfig,
}
#[derive(Clone, Debug)]
@@ -58,7 +59,7 @@ pub(crate) enum Target {
}
impl CargoOptions {
- pub(crate) fn apply_on_command(&self, cmd: &mut Command) {
+ pub(crate) fn apply_on_command(&self, cmd: &mut Command, ws_target_dir: Option<&Utf8Path>) {
for target in &self.target_tuples {
cmd.args(["--target", target.as_str()]);
}
@@ -82,8 +83,8 @@ impl CargoOptions {
cmd.arg(self.features.join(" "));
}
}
- if let Some(target_dir) = &self.target_dir {
- cmd.arg("--target-dir").arg(target_dir);
+ if let Some(target_dir) = self.target_dir_config.target_dir(ws_target_dir) {
+ cmd.arg("--target-dir").arg(target_dir.as_ref());
}
}
}
@@ -158,6 +159,7 @@ impl FlycheckHandle {
sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
+ ws_target_dir: Option<Utf8PathBuf>,
) -> FlycheckHandle {
let actor = FlycheckActor::new(
id,
@@ -167,6 +169,7 @@ impl FlycheckHandle {
sysroot_root,
workspace_root,
manifest_path,
+ ws_target_dir,
);
let (sender, receiver) = unbounded::<StateChange>();
let thread =
@@ -314,6 +317,7 @@ struct FlycheckActor {
sender: Sender<FlycheckMessage>,
config: FlycheckConfig,
manifest_path: Option<AbsPathBuf>,
+ ws_target_dir: Option<Utf8PathBuf>,
/// Either the workspace root of the workspace we are flychecking,
/// or the project root of the project.
root: Arc<AbsPathBuf>,
@@ -355,6 +359,7 @@ impl FlycheckActor {
sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
+ ws_target_dir: Option<Utf8PathBuf>,
) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck");
FlycheckActor {
@@ -366,6 +371,7 @@ impl FlycheckActor {
root: Arc::new(workspace_root),
scope: FlycheckScope::Workspace,
manifest_path,
+ ws_target_dir,
command_handle: None,
command_receiver: None,
diagnostics_cleared_for: Default::default(),
@@ -428,15 +434,24 @@ impl FlycheckActor {
CargoCheckParser,
sender,
match &self.config {
- FlycheckConfig::CargoCommand { options, .. } => Some(
- options
- .target_dir
- .as_deref()
- .unwrap_or(
- Utf8Path::new("target").join("rust-analyzer").as_path(),
- )
- .join(format!("flycheck{}", self.id)),
- ),
+ FlycheckConfig::CargoCommand { options, .. } => {
+ let ws_target_dir =
+ self.ws_target_dir.as_ref().map(Utf8PathBuf::as_path);
+ let target_dir =
+ options.target_dir_config.target_dir(ws_target_dir);
+
+ // If `"rust-analyzer.cargo.targetDir": null`, we should use
+ // workspace's target dir instead of hard-coded fallback.
+ let target_dir = target_dir.as_deref().or(ws_target_dir);
+
+ Some(
+ target_dir
+ .unwrap_or(
+ Utf8Path::new("target").join("rust-analyzer").as_path(),
+ )
+ .join(format!("flycheck{}", self.id)),
+ )
+ }
_ => None,
},
) {
@@ -672,7 +687,10 @@ impl FlycheckActor {
cmd.arg("--keep-going");
- options.apply_on_command(&mut cmd);
+ options.apply_on_command(
+ &mut cmd,
+ self.ws_target_dir.as_ref().map(Utf8PathBuf::as_path),
+ );
cmd.args(&options.extra_args);
Some(cmd)
}
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 2976441d76..14817df376 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -264,6 +264,7 @@ pub(crate) fn handle_run_test(
path,
state.config.cargo_test_options(None),
cargo.workspace_root(),
+ Some(cargo.target_directory().as_ref()),
target,
state.test_run_sender.clone(),
)?;
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 1475f02447..bb971eb13b 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -23,6 +23,7 @@ use ide_db::{
use itertools::Itertools;
use load_cargo::{ProjectFolders, load_proc_macro};
use lsp_types::FileSystemWatcher;
+use paths::Utf8Path;
use proc_macro_api::ProcMacroClient;
use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
use stdx::{format_to, thread::ThreadIntent};
@@ -876,6 +877,7 @@ impl GlobalState {
None,
self.config.root_path().clone(),
None,
+ None,
)]
}
crate::flycheck::InvocationStrategy::PerWorkspace => {
@@ -890,13 +892,17 @@ impl GlobalState {
| ProjectWorkspaceKind::DetachedFile {
cargo: Some((cargo, _, _)),
..
- } => (cargo.workspace_root(), Some(cargo.manifest_path())),
+ } => (
+ cargo.workspace_root(),
+ Some(cargo.manifest_path()),
+ Some(cargo.target_directory()),
+ ),
ProjectWorkspaceKind::Json(project) => {
// Enable flychecks for json projects if a custom flycheck command was supplied
// in the workspace configuration.
match config {
FlycheckConfig::CustomCommand { .. } => {
- (project.path(), None)
+ (project.path(), None, None)
}
_ => return None,
}
@@ -906,7 +912,7 @@ impl GlobalState {
ws.sysroot.root().map(ToOwned::to_owned),
))
})
- .map(|(id, (root, manifest_path), sysroot_root)| {
+ .map(|(id, (root, manifest_path, target_dir), sysroot_root)| {
FlycheckHandle::spawn(
id,
next_gen,
@@ -915,6 +921,7 @@ impl GlobalState {
sysroot_root,
root.to_path_buf(),
manifest_path.map(|it| it.to_path_buf()),
+ target_dir.map(|it| AsRef::<Utf8Path>::as_ref(it).to_path_buf()),
)
})
.collect()
diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs
index 0c8658c75d..9a65e708a0 100644
--- a/crates/rust-analyzer/src/test_runner.rs
+++ b/crates/rust-analyzer/src/test_runner.rs
@@ -2,7 +2,7 @@
//! thread and report the result of each test in a channel.
use crossbeam_channel::Sender;
-use paths::AbsPath;
+use paths::{AbsPath, Utf8Path};
use project_model::TargetKind;
use serde::Deserialize as _;
use serde_derive::Deserialize;
@@ -98,6 +98,7 @@ impl CargoTestHandle {
path: Option<&str>,
options: CargoOptions,
root: &AbsPath,
+ ws_target_dir: Option<&Utf8Path>,
test_target: TestTarget,
sender: Sender<CargoTestMessage>,
) -> std::io::Result<Self> {
@@ -123,7 +124,7 @@ impl CargoTestHandle {
cmd.arg("--no-fail-fast");
cmd.arg("--manifest-path");
cmd.arg(root.join("Cargo.toml"));
- options.apply_on_command(&mut cmd);
+ options.apply_on_command(&mut cmd, ws_target_dir);
cmd.arg("--");
if let Some(path) = path {
cmd.arg(path);