mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-27 20:35:09 +00:00
Allow rust files to be used linkedProjects
This commit is contained in:
parent
55d9a533b3
commit
a2ed6837bc
21 changed files with 203 additions and 180 deletions
|
@ -51,6 +51,7 @@ pub trait FileLoader {
|
||||||
/// Text of the file.
|
/// Text of the file.
|
||||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
|
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
|
||||||
|
/// Crates whose root's source root is the same as the source root of `file_id`
|
||||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
|
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +105,7 @@ pub trait SourceDatabaseExt: SourceDatabase {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
||||||
|
|
||||||
|
/// Crates whose root fool is in `id`.
|
||||||
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def").entered();
|
let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def").entered();
|
||||||
let mut mods = SmallVec::new();
|
let mut mods = SmallVec::new();
|
||||||
for &crate_id in self.db.relevant_crates(file).iter() {
|
for &crate_id in self.db.relevant_crates(file).iter() {
|
||||||
// FIXME: inner items
|
// Note: `mod` declarations in block modules cannot be supported here
|
||||||
let crate_def_map = self.db.crate_def_map(crate_id);
|
let crate_def_map = self.db.crate_def_map(crate_id);
|
||||||
mods.extend(
|
mods.extend(
|
||||||
crate_def_map
|
crate_def_map
|
||||||
|
@ -129,6 +129,9 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
.map(|local_id| crate_def_map.module_id(local_id)),
|
.map(|local_id| crate_def_map.module_id(local_id)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if mods.is_empty() {
|
||||||
|
// FIXME: detached file
|
||||||
|
}
|
||||||
mods
|
mods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! rust-analyzer is lazy and doesn't compute anything unless asked. This
|
//! rust-analyzer is lazy and doesn't compute anything unless asked. This
|
||||||
//! sometimes is counter productive when, for example, the first goto definition
|
//! sometimes is counter productive when, for example, the first goto definition
|
||||||
//! request takes longer to compute. This modules implemented prepopulation of
|
//! request takes longer to compute. This module implements prepopulation of
|
||||||
//! various caches, it's not really advanced at the moment.
|
//! various caches, it's not really advanced at the moment.
|
||||||
mod topologic_sort;
|
mod topologic_sort;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use toolchain::Tool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cfg::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
|
cfg::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
|
||||||
InvocationStrategy, Package, Sysroot, TargetKind,
|
InvocationStrategy, ManifestPath, Package, Sysroot, TargetKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Output of the build script and proc-macro building steps for a workspace.
|
/// Output of the build script and proc-macro building steps for a workspace.
|
||||||
|
@ -63,7 +63,7 @@ impl WorkspaceBuildScripts {
|
||||||
fn build_command(
|
fn build_command(
|
||||||
config: &CargoConfig,
|
config: &CargoConfig,
|
||||||
allowed_features: &FxHashSet<String>,
|
allowed_features: &FxHashSet<String>,
|
||||||
workspace_root: &AbsPathBuf,
|
manifest_path: &ManifestPath,
|
||||||
sysroot: Option<&Sysroot>,
|
sysroot: Option<&Sysroot>,
|
||||||
) -> io::Result<Command> {
|
) -> io::Result<Command> {
|
||||||
let mut cmd = match config.run_build_script_command.as_deref() {
|
let mut cmd = match config.run_build_script_command.as_deref() {
|
||||||
|
@ -79,7 +79,7 @@ impl WorkspaceBuildScripts {
|
||||||
cmd.args(&config.extra_args);
|
cmd.args(&config.extra_args);
|
||||||
|
|
||||||
cmd.arg("--manifest-path");
|
cmd.arg("--manifest-path");
|
||||||
cmd.arg(workspace_root.join("Cargo.toml"));
|
cmd.arg(manifest_path.as_ref());
|
||||||
|
|
||||||
if let Some(target_dir) = &config.target_dir {
|
if let Some(target_dir) = &config.target_dir {
|
||||||
cmd.arg("--target-dir").arg(target_dir);
|
cmd.arg("--target-dir").arg(target_dir);
|
||||||
|
@ -116,6 +116,10 @@ impl WorkspaceBuildScripts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if manifest_path.extension().map_or(false, |ext| ext == "rs") {
|
||||||
|
cmd.arg("-Zscript");
|
||||||
|
}
|
||||||
|
|
||||||
cmd
|
cmd
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -152,37 +156,12 @@ impl WorkspaceBuildScripts {
|
||||||
.as_ref();
|
.as_ref();
|
||||||
|
|
||||||
let allowed_features = workspace.workspace_features();
|
let allowed_features = workspace.workspace_features();
|
||||||
|
let mut cmd =
|
||||||
match Self::run_per_ws(
|
Self::build_command(config, &allowed_features, workspace.manifest_path(), sysroot)?;
|
||||||
Self::build_command(
|
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_75) {
|
||||||
config,
|
|
||||||
&allowed_features,
|
|
||||||
&workspace.workspace_root().to_path_buf(),
|
|
||||||
sysroot,
|
|
||||||
)?,
|
|
||||||
workspace,
|
|
||||||
current_dir,
|
|
||||||
progress,
|
|
||||||
) {
|
|
||||||
Ok(WorkspaceBuildScripts { error: Some(error), .. })
|
|
||||||
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_75) =>
|
|
||||||
{
|
|
||||||
// building build scripts failed, attempt to build with --keep-going so
|
|
||||||
// that we potentially get more build data
|
|
||||||
let mut cmd = Self::build_command(
|
|
||||||
config,
|
|
||||||
&allowed_features,
|
|
||||||
&workspace.workspace_root().to_path_buf(),
|
|
||||||
sysroot,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
cmd.args(["--keep-going"]);
|
cmd.args(["--keep-going"]);
|
||||||
let mut res = Self::run_per_ws(cmd, workspace, current_dir, progress)?;
|
|
||||||
res.error = Some(error);
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
res => res,
|
|
||||||
}
|
}
|
||||||
|
Self::run_per_ws(cmd, workspace, current_dir, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the build scripts by invoking the configured command *once*.
|
/// Runs the build scripts by invoking the configured command *once*.
|
||||||
|
@ -204,7 +183,13 @@ impl WorkspaceBuildScripts {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let cmd = Self::build_command(config, &Default::default(), workspace_root, None)?;
|
let cmd = Self::build_command(
|
||||||
|
config,
|
||||||
|
&Default::default(),
|
||||||
|
// This is not gonna be used anyways, so just construct a dummy here
|
||||||
|
&ManifestPath::try_from(workspace_root.clone()).unwrap(),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
// NB: Cargo.toml could have been modified between `cargo metadata` and
|
// NB: Cargo.toml could have been modified between `cargo metadata` and
|
||||||
// `cargo check`. We shouldn't assume that package ids we see here are
|
// `cargo check`. We shouldn't assume that package ids we see here are
|
||||||
// exactly those from `config`.
|
// exactly those from `config`.
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub struct CargoWorkspace {
|
||||||
targets: Arena<TargetData>,
|
targets: Arena<TargetData>,
|
||||||
workspace_root: AbsPathBuf,
|
workspace_root: AbsPathBuf,
|
||||||
target_directory: AbsPathBuf,
|
target_directory: AbsPathBuf,
|
||||||
|
manifest_path: ManifestPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Index<Package> for CargoWorkspace {
|
impl ops::Index<Package> for CargoWorkspace {
|
||||||
|
@ -334,7 +335,7 @@ impl CargoWorkspace {
|
||||||
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))
|
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
|
pub fn new(mut meta: cargo_metadata::Metadata, manifest_path: ManifestPath) -> CargoWorkspace {
|
||||||
let mut pkg_by_id = FxHashMap::default();
|
let mut pkg_by_id = FxHashMap::default();
|
||||||
let mut packages = Arena::default();
|
let mut packages = Arena::default();
|
||||||
let mut targets = Arena::default();
|
let mut targets = Arena::default();
|
||||||
|
@ -448,7 +449,7 @@ impl CargoWorkspace {
|
||||||
|
|
||||||
let target_directory = AbsPathBuf::assert(meta.target_directory);
|
let target_directory = AbsPathBuf::assert(meta.target_directory);
|
||||||
|
|
||||||
CargoWorkspace { packages, targets, workspace_root, target_directory }
|
CargoWorkspace { packages, targets, workspace_root, target_directory, manifest_path }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn packages(&self) -> impl ExactSizeIterator<Item = Package> + '_ {
|
pub fn packages(&self) -> impl ExactSizeIterator<Item = Package> + '_ {
|
||||||
|
@ -466,6 +467,10 @@ impl CargoWorkspace {
|
||||||
&self.workspace_root
|
&self.workspace_root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn manifest_path(&self) -> &ManifestPath {
|
||||||
|
&self.manifest_path
|
||||||
|
}
|
||||||
|
|
||||||
pub fn target_directory(&self) -> &AbsPath {
|
pub fn target_directory(&self) -> &AbsPath {
|
||||||
&self.target_directory
|
&self.target_directory
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,11 +54,13 @@ pub use crate::{
|
||||||
sysroot::Sysroot,
|
sysroot::Sysroot,
|
||||||
workspace::{FileLoader, PackageRoot, ProjectWorkspace},
|
workspace::{FileLoader, PackageRoot, ProjectWorkspace},
|
||||||
};
|
};
|
||||||
|
pub use cargo_metadata::Metadata;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||||
pub enum ProjectManifest {
|
pub enum ProjectManifest {
|
||||||
ProjectJson(ManifestPath),
|
ProjectJson(ManifestPath),
|
||||||
CargoToml(ManifestPath),
|
CargoToml(ManifestPath),
|
||||||
|
CargoScript(ManifestPath),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectManifest {
|
impl ProjectManifest {
|
||||||
|
@ -71,7 +73,10 @@ impl ProjectManifest {
|
||||||
if path.file_name().unwrap_or_default() == "Cargo.toml" {
|
if path.file_name().unwrap_or_default() == "Cargo.toml" {
|
||||||
return Ok(ProjectManifest::CargoToml(path));
|
return Ok(ProjectManifest::CargoToml(path));
|
||||||
}
|
}
|
||||||
bail!("project root must point to Cargo.toml or rust-project.json: {path}");
|
if path.extension().unwrap_or_default() == "rs" {
|
||||||
|
return Ok(ProjectManifest::CargoScript(path));
|
||||||
|
}
|
||||||
|
bail!("project root must point to a Cargo.toml, rust-project.json or <script>.rs file: {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discover_single(path: &AbsPath) -> anyhow::Result<ProjectManifest> {
|
pub fn discover_single(path: &AbsPath) -> anyhow::Result<ProjectManifest> {
|
||||||
|
@ -146,15 +151,19 @@ impl ProjectManifest {
|
||||||
res.sort();
|
res.sort();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn manifest_path(&self) -> &ManifestPath {
|
||||||
|
match self {
|
||||||
|
ProjectManifest::ProjectJson(it)
|
||||||
|
| ProjectManifest::CargoToml(it)
|
||||||
|
| ProjectManifest::CargoScript(it) => it,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ProjectManifest {
|
impl fmt::Display for ProjectManifest {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
fmt::Display::fmt(self.manifest_path(), f)
|
||||||
ProjectManifest::ProjectJson(it) | ProjectManifest::CargoToml(it) => {
|
|
||||||
fmt::Display::fmt(&it, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! See [`ManifestPath`].
|
//! See [`ManifestPath`].
|
||||||
use std::{fmt, ops, path::Path};
|
use std::{borrow::Borrow, fmt, ops};
|
||||||
|
|
||||||
use paths::{AbsPath, AbsPathBuf};
|
use paths::{AbsPath, AbsPathBuf};
|
||||||
|
|
||||||
|
@ -54,8 +54,14 @@ impl ops::Deref for ManifestPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<Path> for ManifestPath {
|
impl AsRef<AbsPath> for ManifestPath {
|
||||||
fn as_ref(&self) -> &Path {
|
fn as_ref(&self) -> &AbsPath {
|
||||||
self.file.as_ref()
|
self.file.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Borrow<AbsPath> for ManifestPath {
|
||||||
|
fn borrow(&self) -> &AbsPath {
|
||||||
|
self.file.borrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -349,7 +349,7 @@ impl Sysroot {
|
||||||
.filter(|&package| RELEVANT_SYSROOT_CRATES.contains(&&*package.name))
|
.filter(|&package| RELEVANT_SYSROOT_CRATES.contains(&&*package.name))
|
||||||
.map(|package| package.id.clone())
|
.map(|package| package.id.clone())
|
||||||
.collect();
|
.collect();
|
||||||
let cargo_workspace = CargoWorkspace::new(res);
|
let cargo_workspace = CargoWorkspace::new(res, sysroot_cargo_toml);
|
||||||
Some(Sysroot {
|
Some(Sysroot {
|
||||||
root: sysroot_dir.clone(),
|
root: sysroot_dir.clone(),
|
||||||
src_root: Some(Ok(sysroot_src_dir.clone())),
|
src_root: Some(Ok(sysroot_src_dir.clone())),
|
||||||
|
@ -368,7 +368,7 @@ impl Sysroot {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|it| sysroot_src_dir.join(it))
|
.map(|it| sysroot_src_dir.join(it))
|
||||||
.filter_map(|it| ManifestPath::try_from(it).ok())
|
.filter_map(|it| ManifestPath::try_from(it).ok())
|
||||||
.find(|it| fs::metadata(it).is_ok());
|
.find(|it| fs::metadata(it.as_ref()).is_ok());
|
||||||
|
|
||||||
if let Some(root) = root {
|
if let Some(root) = root {
|
||||||
stitched.crates.alloc(SysrootCrateData {
|
stitched.crates.alloc(SysrootCrateData {
|
||||||
|
@ -468,7 +468,7 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option<ManifestPath> {
|
||||||
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
|
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
|
||||||
let rustc_src = ManifestPath::try_from(rustc_src).ok()?;
|
let rustc_src = ManifestPath::try_from(rustc_src).ok()?;
|
||||||
tracing::debug!("checking for rustc source code: {rustc_src}");
|
tracing::debug!("checking for rustc source code: {rustc_src}");
|
||||||
if fs::metadata(&rustc_src).is_ok() {
|
if fs::metadata(rustc_src.as_ref()).is_ok() {
|
||||||
Some(rustc_src)
|
Some(rustc_src)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use base_db::{CrateGraph, FileId, ProcMacroPaths};
|
use base_db::{CrateGraph, FileId, ProcMacroPaths};
|
||||||
|
use cargo_metadata::Metadata;
|
||||||
use cfg::{CfgAtom, CfgDiff};
|
use cfg::{CfgAtom, CfgDiff};
|
||||||
use expect_test::{expect_file, ExpectFile};
|
use expect_test::{expect_file, ExpectFile};
|
||||||
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
|
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
|
||||||
|
@ -9,8 +10,8 @@ use serde::de::DeserializeOwned;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
|
CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace,
|
||||||
WorkspaceBuildScripts,
|
Sysroot, WorkspaceBuildScripts,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
|
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
|
||||||
|
@ -21,8 +22,10 @@ fn load_cargo_with_overrides(
|
||||||
file: &str,
|
file: &str,
|
||||||
cfg_overrides: CfgOverrides,
|
cfg_overrides: CfgOverrides,
|
||||||
) -> (CrateGraph, ProcMacroPaths) {
|
) -> (CrateGraph, ProcMacroPaths) {
|
||||||
let meta = get_test_json_file(file);
|
let meta: Metadata = get_test_json_file(file);
|
||||||
let cargo_workspace = CargoWorkspace::new(meta);
|
let manifest_path =
|
||||||
|
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
|
||||||
|
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
|
||||||
let project_workspace = ProjectWorkspace::Cargo {
|
let project_workspace = ProjectWorkspace::Cargo {
|
||||||
cargo: cargo_workspace,
|
cargo: cargo_workspace,
|
||||||
build_scripts: WorkspaceBuildScripts::default(),
|
build_scripts: WorkspaceBuildScripts::default(),
|
||||||
|
@ -41,8 +44,10 @@ fn load_cargo_with_fake_sysroot(
|
||||||
file_map: &mut FxHashMap<AbsPathBuf, FileId>,
|
file_map: &mut FxHashMap<AbsPathBuf, FileId>,
|
||||||
file: &str,
|
file: &str,
|
||||||
) -> (CrateGraph, ProcMacroPaths) {
|
) -> (CrateGraph, ProcMacroPaths) {
|
||||||
let meta = get_test_json_file(file);
|
let meta: Metadata = get_test_json_file(file);
|
||||||
let cargo_workspace = CargoWorkspace::new(meta);
|
let manifest_path =
|
||||||
|
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
|
||||||
|
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
|
||||||
let project_workspace = ProjectWorkspace::Cargo {
|
let project_workspace = ProjectWorkspace::Cargo {
|
||||||
cargo: cargo_workspace,
|
cargo: cargo_workspace,
|
||||||
build_scripts: WorkspaceBuildScripts::default(),
|
build_scripts: WorkspaceBuildScripts::default(),
|
||||||
|
@ -268,9 +273,10 @@ fn smoke_test_real_sysroot_cargo() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
|
let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
|
||||||
let meta = get_test_json_file("hello-world-metadata.json");
|
let meta: Metadata = get_test_json_file("hello-world-metadata.json");
|
||||||
|
let manifest_path =
|
||||||
let cargo_workspace = CargoWorkspace::new(meta);
|
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
|
||||||
|
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
|
||||||
let sysroot = Ok(Sysroot::discover(
|
let sysroot = Ok(Sysroot::discover(
|
||||||
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
|
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::{collections::VecDeque, fmt, fs, iter, sync};
|
use std::{collections::VecDeque, fmt, fs, iter, sync};
|
||||||
|
|
||||||
use anyhow::{format_err, Context};
|
use anyhow::Context;
|
||||||
use base_db::{
|
use base_db::{
|
||||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileId,
|
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileId,
|
||||||
LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
|
LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
|
||||||
|
@ -14,7 +14,6 @@ use paths::{AbsPath, AbsPathBuf};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
use stdx::always;
|
|
||||||
use toolchain::Tool;
|
use toolchain::Tool;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ pub enum ProjectWorkspace {
|
||||||
/// Backed by basic sysroot crates for basic completion and highlighting.
|
/// Backed by basic sysroot crates for basic completion and highlighting.
|
||||||
DetachedFile {
|
DetachedFile {
|
||||||
/// The file in question.
|
/// The file in question.
|
||||||
file: AbsPathBuf,
|
file: ManifestPath,
|
||||||
/// The sysroot loaded for this workspace.
|
/// The sysroot loaded for this workspace.
|
||||||
sysroot: Result<Sysroot, Option<String>>,
|
sysroot: Result<Sysroot, Option<String>>,
|
||||||
/// Holds cfg flags for the current target. We get those by running
|
/// Holds cfg flags for the current target. We get those by running
|
||||||
|
@ -116,7 +115,7 @@ pub enum ProjectWorkspace {
|
||||||
/// A set of cfg overrides for the files.
|
/// A set of cfg overrides for the files.
|
||||||
cfg_overrides: CfgOverrides,
|
cfg_overrides: CfgOverrides,
|
||||||
/// Is this file a cargo script file?
|
/// Is this file a cargo script file?
|
||||||
cargo_script: Option<CargoWorkspace>,
|
cargo_script: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +229,7 @@ impl ProjectWorkspace {
|
||||||
) -> anyhow::Result<ProjectWorkspace> {
|
) -> anyhow::Result<ProjectWorkspace> {
|
||||||
let res = match manifest {
|
let res = match manifest {
|
||||||
ProjectManifest::ProjectJson(project_json) => {
|
ProjectManifest::ProjectJson(project_json) => {
|
||||||
let file = fs::read_to_string(project_json)
|
let file = fs::read_to_string(project_json.as_ref())
|
||||||
.with_context(|| format!("Failed to read json file {project_json}"))?;
|
.with_context(|| format!("Failed to read json file {project_json}"))?;
|
||||||
let data = serde_json::from_str(&file)
|
let data = serde_json::from_str(&file)
|
||||||
.with_context(|| format!("Failed to deserialize json file {project_json}"))?;
|
.with_context(|| format!("Failed to deserialize json file {project_json}"))?;
|
||||||
|
@ -243,6 +242,9 @@ impl ProjectWorkspace {
|
||||||
&config.cfg_overrides,
|
&config.cfg_overrides,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
ProjectManifest::CargoScript(rust_file) => {
|
||||||
|
ProjectWorkspace::load_detached_file(rust_file, config)?
|
||||||
|
}
|
||||||
ProjectManifest::CargoToml(cargo_toml) => {
|
ProjectManifest::CargoToml(cargo_toml) => {
|
||||||
let sysroot = match (&config.sysroot, &config.sysroot_src) {
|
let sysroot = match (&config.sysroot, &config.sysroot_src) {
|
||||||
(Some(RustLibSource::Path(path)), None) => {
|
(Some(RustLibSource::Path(path)), None) => {
|
||||||
|
@ -299,7 +301,7 @@ impl ProjectWorkspace {
|
||||||
progress,
|
progress,
|
||||||
) {
|
) {
|
||||||
Ok(meta) => {
|
Ok(meta) => {
|
||||||
let workspace = CargoWorkspace::new(meta);
|
let workspace = CargoWorkspace::new(meta, cargo_toml.clone());
|
||||||
let buildscripts = WorkspaceBuildScripts::rustc_crates(
|
let buildscripts = WorkspaceBuildScripts::rustc_crates(
|
||||||
&workspace,
|
&workspace,
|
||||||
cargo_toml.parent(),
|
cargo_toml.parent(),
|
||||||
|
@ -355,7 +357,7 @@ impl ProjectWorkspace {
|
||||||
"Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
|
"Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let cargo = CargoWorkspace::new(meta);
|
let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
|
||||||
|
|
||||||
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);
|
||||||
|
@ -433,40 +435,31 @@ impl ProjectWorkspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_detached_files(
|
pub fn load_detached_file(
|
||||||
detached_files: Vec<AbsPathBuf>,
|
detached_file: &ManifestPath,
|
||||||
config: &CargoConfig,
|
config: &CargoConfig,
|
||||||
) -> Vec<anyhow::Result<ProjectWorkspace>> {
|
) -> anyhow::Result<ProjectWorkspace> {
|
||||||
detached_files
|
let dir = detached_file.parent();
|
||||||
.into_iter()
|
|
||||||
.map(|detached_file| {
|
|
||||||
let dir = detached_file
|
|
||||||
.parent()
|
|
||||||
.ok_or_else(|| format_err!("detached file has no parent"))?;
|
|
||||||
let sysroot = match &config.sysroot {
|
let sysroot = match &config.sysroot {
|
||||||
Some(RustLibSource::Path(path)) => {
|
Some(RustLibSource::Path(path)) => {
|
||||||
Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata)
|
Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata)
|
||||||
.map_err(|e| Some(format!("Failed to find sysroot at {path}:{e}")))
|
.map_err(|e| Some(format!("Failed to find sysroot at {path}:{e}")))
|
||||||
}
|
}
|
||||||
Some(RustLibSource::Discover) => {
|
Some(RustLibSource::Discover) => Sysroot::discover(
|
||||||
Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
|
dir,
|
||||||
|
&config.extra_env,
|
||||||
|
config.sysroot_query_metadata,
|
||||||
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Some(format!(
|
Some(format!("Failed to find sysroot for {dir}. Is rust-src installed? {e}"))
|
||||||
"Failed to find sysroot for {dir}. Is rust-src installed? {e}"
|
}),
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => Err(None),
|
None => Err(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let sysroot_ref = sysroot.as_ref().ok();
|
let sysroot_ref = sysroot.as_ref().ok();
|
||||||
let toolchain = match get_toolchain_version(
|
let toolchain =
|
||||||
dir,
|
match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ")
|
||||||
sysroot_ref,
|
{
|
||||||
Tool::Rustc,
|
|
||||||
&config.extra_env,
|
|
||||||
"rustc ",
|
|
||||||
) {
|
|
||||||
Ok(it) => it,
|
Ok(it) => it,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("{e}");
|
tracing::error!("{e}");
|
||||||
|
@ -474,41 +467,39 @@ impl ProjectWorkspace {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let rustc_cfg =
|
let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
|
||||||
rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
|
|
||||||
let data_layout = target_data_layout::get(
|
let data_layout = target_data_layout::get(
|
||||||
RustcDataLayoutConfig::Rustc(sysroot_ref),
|
RustcDataLayoutConfig::Rustc(sysroot_ref),
|
||||||
None,
|
None,
|
||||||
&config.extra_env,
|
&config.extra_env,
|
||||||
);
|
);
|
||||||
|
|
||||||
let cargo_script = ManifestPath::try_from(detached_file.clone())
|
let cargo_script =
|
||||||
|
CargoWorkspace::fetch_metadata(detached_file, dir, config, sysroot_ref, &|_| ())
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|file| {
|
.map(|ws| {
|
||||||
CargoWorkspace::fetch_metadata(
|
(
|
||||||
&file,
|
CargoWorkspace::new(ws, detached_file.clone()),
|
||||||
file.parent(),
|
WorkspaceBuildScripts::default(),
|
||||||
config,
|
|
||||||
sysroot_ref,
|
|
||||||
&|_| (),
|
|
||||||
)
|
)
|
||||||
.ok()
|
});
|
||||||
})
|
|
||||||
.map(CargoWorkspace::new);
|
|
||||||
|
|
||||||
Ok(ProjectWorkspace::DetachedFile {
|
Ok(ProjectWorkspace::DetachedFile {
|
||||||
file: detached_file,
|
file: detached_file.to_owned(),
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: data_layout
|
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
||||||
.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,
|
cargo_script,
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
.collect()
|
|
||||||
|
pub fn load_detached_files(
|
||||||
|
detached_files: Vec<ManifestPath>,
|
||||||
|
config: &CargoConfig,
|
||||||
|
) -> Vec<anyhow::Result<ProjectWorkspace>> {
|
||||||
|
detached_files.into_iter().map(|file| Self::load_detached_file(&file, config)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the build scripts for this [`ProjectWorkspace`].
|
/// Runs the build scripts for this [`ProjectWorkspace`].
|
||||||
|
@ -519,7 +510,7 @@ impl ProjectWorkspace {
|
||||||
) -> anyhow::Result<WorkspaceBuildScripts> {
|
) -> anyhow::Result<WorkspaceBuildScripts> {
|
||||||
match self {
|
match self {
|
||||||
ProjectWorkspace::DetachedFile {
|
ProjectWorkspace::DetachedFile {
|
||||||
cargo_script: Some(cargo),
|
cargo_script: Some((cargo, _)),
|
||||||
toolchain,
|
toolchain,
|
||||||
sysroot,
|
sysroot,
|
||||||
..
|
..
|
||||||
|
@ -586,10 +577,11 @@ impl ProjectWorkspace {
|
||||||
|
|
||||||
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
|
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
|
||||||
match self {
|
match self {
|
||||||
ProjectWorkspace::Cargo { build_scripts, .. } => *build_scripts = bs,
|
ProjectWorkspace::Cargo { build_scripts, .. }
|
||||||
_ => {
|
| ProjectWorkspace::DetachedFile { cargo_script: Some((_, build_scripts)), .. } => {
|
||||||
always!(bs == WorkspaceBuildScripts::default());
|
*build_scripts = bs
|
||||||
}
|
}
|
||||||
|
_ => assert_eq!(bs, WorkspaceBuildScripts::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,15 +734,18 @@ impl ProjectWorkspace {
|
||||||
ProjectWorkspace::DetachedFile { file, cargo_script, sysroot, .. } => {
|
ProjectWorkspace::DetachedFile { file, cargo_script, sysroot, .. } => {
|
||||||
iter::once(PackageRoot {
|
iter::once(PackageRoot {
|
||||||
is_local: true,
|
is_local: true,
|
||||||
include: vec![file.clone()],
|
include: vec![file.as_ref().to_owned()],
|
||||||
exclude: Vec::new(),
|
exclude: Vec::new(),
|
||||||
})
|
})
|
||||||
.chain(cargo_script.iter().flat_map(|cargo| {
|
.chain(cargo_script.iter().flat_map(|(cargo, build_scripts)| {
|
||||||
cargo.packages().map(|pkg| {
|
cargo.packages().map(|pkg| {
|
||||||
let is_local = cargo[pkg].is_local;
|
let is_local = cargo[pkg].is_local;
|
||||||
let pkg_root = cargo[pkg].manifest.parent().to_path_buf();
|
let pkg_root = cargo[pkg].manifest.parent().to_path_buf();
|
||||||
|
|
||||||
let mut include = vec![pkg_root.clone()];
|
let mut include = vec![pkg_root.clone()];
|
||||||
|
let out_dir =
|
||||||
|
build_scripts.get_output(pkg).and_then(|it| it.out_dir.clone());
|
||||||
|
include.extend(out_dir);
|
||||||
|
|
||||||
// In case target's path is manually set in Cargo.toml to be
|
// In case target's path is manually set in Cargo.toml to be
|
||||||
// outside the package root, add its parent as an extra include.
|
// outside the package root, add its parent as an extra include.
|
||||||
|
@ -801,7 +796,7 @@ impl ProjectWorkspace {
|
||||||
ProjectWorkspace::DetachedFile { sysroot, cargo_script, .. } => {
|
ProjectWorkspace::DetachedFile { sysroot, cargo_script, .. } => {
|
||||||
let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages());
|
let sysroot_package_len = 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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -863,7 +858,7 @@ impl ProjectWorkspace {
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
cargo_script,
|
cargo_script,
|
||||||
} => (
|
} => (
|
||||||
if let Some(cargo) = 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),
|
||||||
None,
|
None,
|
||||||
|
@ -871,7 +866,7 @@ impl ProjectWorkspace {
|
||||||
sysroot.as_ref().ok(),
|
sysroot.as_ref().ok(),
|
||||||
rustc_cfg.clone(),
|
rustc_cfg.clone(),
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
&WorkspaceBuildScripts::default(),
|
build_scripts,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
detached_file_to_crate_graph(
|
detached_file_to_crate_graph(
|
||||||
|
@ -959,7 +954,7 @@ impl ProjectWorkspace {
|
||||||
file,
|
file,
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
cargo_script,
|
cargo_script: Some((cargo_script, _)),
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout,
|
target_layout,
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
|
@ -968,7 +963,7 @@ impl ProjectWorkspace {
|
||||||
file: o_file,
|
file: o_file,
|
||||||
sysroot: o_sysroot,
|
sysroot: o_sysroot,
|
||||||
rustc_cfg: o_rustc_cfg,
|
rustc_cfg: o_rustc_cfg,
|
||||||
cargo_script: o_cargo_script,
|
cargo_script: Some((o_cargo_script, _)),
|
||||||
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,
|
||||||
|
@ -1294,11 +1289,11 @@ fn cargo_to_crate_graph(
|
||||||
fn detached_file_to_crate_graph(
|
fn detached_file_to_crate_graph(
|
||||||
rustc_cfg: Vec<CfgFlag>,
|
rustc_cfg: Vec<CfgFlag>,
|
||||||
load: FileLoader<'_>,
|
load: FileLoader<'_>,
|
||||||
detached_file: &AbsPathBuf,
|
detached_file: &ManifestPath,
|
||||||
sysroot: Option<&Sysroot>,
|
sysroot: Option<&Sysroot>,
|
||||||
override_cfg: &CfgOverrides,
|
override_cfg: &CfgOverrides,
|
||||||
) -> (CrateGraph, ProcMacroPaths) {
|
) -> (CrateGraph, ProcMacroPaths) {
|
||||||
let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered();
|
let _p = tracing::span!(tracing::Level::INFO, "detached_file_to_crate_graph").entered();
|
||||||
let mut crate_graph = CrateGraph::default();
|
let mut crate_graph = CrateGraph::default();
|
||||||
let (public_deps, _libproc_macro) = match sysroot {
|
let (public_deps, _libproc_macro) = match sysroot {
|
||||||
Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
|
Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl<'a> ProgressReport<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_value(&mut self, value: f32) {
|
fn set_value(&mut self, value: f32) {
|
||||||
self.curr = f32::max(0.0, f32::min(1.0, value));
|
self.curr = value.clamp(0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
|
|
|
@ -10,7 +10,9 @@ use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
|
||||||
use itertools::Either;
|
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::{target_data_layout, CargoConfig, ProjectWorkspace, RustLibSource, Sysroot};
|
use project_model::{
|
||||||
|
target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, RustLibSource, Sysroot,
|
||||||
|
};
|
||||||
|
|
||||||
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
|
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -76,7 +78,7 @@ impl Tester {
|
||||||
);
|
);
|
||||||
|
|
||||||
let workspace = ProjectWorkspace::DetachedFile {
|
let workspace = ProjectWorkspace::DetachedFile {
|
||||||
file: tmp_file,
|
file: ManifestPath::try_from(tmp_file).unwrap(),
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg: vec![],
|
rustc_cfg: vec![],
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
|
@ -356,7 +356,8 @@ config_data! {
|
||||||
/// of projects.
|
/// of projects.
|
||||||
///
|
///
|
||||||
/// Elements must be paths pointing to `Cargo.toml`,
|
/// Elements must be paths pointing to `Cargo.toml`,
|
||||||
/// `rust-project.json`, or JSON objects in `rust-project.json` format.
|
/// `rust-project.json`, `.rs` files (which will be treated as standalone files) or JSON
|
||||||
|
/// objects in `rust-project.json` format.
|
||||||
linkedProjects: Vec<ManifestOrProjectJson> = vec![],
|
linkedProjects: Vec<ManifestOrProjectJson> = vec![],
|
||||||
|
|
||||||
/// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
|
/// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
|
||||||
|
@ -1301,12 +1302,9 @@ impl Config {
|
||||||
self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect();
|
self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect();
|
||||||
self.discovered_projects
|
self.discovered_projects
|
||||||
.iter()
|
.iter()
|
||||||
.filter(
|
.filter(|project| {
|
||||||
|(ProjectManifest::ProjectJson(path)
|
!exclude_dirs.iter().any(|p| project.manifest_path().starts_with(p))
|
||||||
| ProjectManifest::CargoToml(path))| {
|
})
|
||||||
!exclude_dirs.iter().any(|p| path.starts_with(p))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(LinkedProject::from)
|
.map(LinkedProject::from)
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -18,7 +18,9 @@ use parking_lot::{
|
||||||
RwLockWriteGuard,
|
RwLockWriteGuard,
|
||||||
};
|
};
|
||||||
use proc_macro_api::ProcMacroServer;
|
use proc_macro_api::ProcMacroServer;
|
||||||
use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
|
use project_model::{
|
||||||
|
CargoWorkspace, ManifestPath, ProjectWorkspace, Target, WorkspaceBuildScripts,
|
||||||
|
};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
use vfs::{AnchoredPathBuf, ChangedFile, Vfs};
|
use vfs::{AnchoredPathBuf, ChangedFile, Vfs};
|
||||||
|
@ -125,7 +127,7 @@ pub(crate) struct GlobalState {
|
||||||
/// to invalidate any salsa caches.
|
/// to invalidate any salsa caches.
|
||||||
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
|
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||||
pub(crate) crate_graph_file_dependencies: FxHashSet<vfs::VfsPath>,
|
pub(crate) crate_graph_file_dependencies: FxHashSet<vfs::VfsPath>,
|
||||||
pub(crate) detached_files: FxHashSet<vfs::AbsPathBuf>,
|
pub(crate) detached_files: FxHashSet<ManifestPath>,
|
||||||
|
|
||||||
// op queues
|
// op queues
|
||||||
pub(crate) fetch_workspaces_queue:
|
pub(crate) fetch_workspaces_queue:
|
||||||
|
|
|
@ -1759,11 +1759,12 @@ pub(crate) fn handle_open_docs(
|
||||||
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 {
|
||||||
ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())),
|
ProjectWorkspace::Cargo { cargo, sysroot, .. }
|
||||||
ProjectWorkspace::Json { .. } => None,
|
| ProjectWorkspace::DetachedFile { cargo_script: Some((cargo, _)), sysroot, .. } => {
|
||||||
ProjectWorkspace::DetachedFile { cargo_script, sysroot, .. } => {
|
Some((cargo, sysroot.as_ref().ok()))
|
||||||
cargo_script.as_ref().zip(Some(sysroot.as_ref().ok()))
|
|
||||||
}
|
}
|
||||||
|
ProjectWorkspace::Json { .. } => None,
|
||||||
|
ProjectWorkspace::DetachedFile { .. } => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let (cargo, sysroot) = match ws_and_sysroot {
|
let (cargo, sysroot) = match ws_and_sysroot {
|
||||||
|
|
|
@ -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::{ProjectWorkspace, WorkspaceBuildScripts};
|
use project_model::{ManifestPath, ProjectWorkspace, 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};
|
||||||
|
@ -204,7 +204,14 @@ impl GlobalState {
|
||||||
|
|
||||||
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, {
|
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, {
|
||||||
let linked_projects = self.config.linked_or_discovered_projects();
|
let linked_projects = self.config.linked_or_discovered_projects();
|
||||||
let detached_files = self.config.detached_files().to_vec();
|
let detached_files: Vec<_> = self
|
||||||
|
.config
|
||||||
|
.detached_files()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(ManifestPath::try_from)
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.collect();
|
||||||
let cargo_config = self.config.cargo();
|
let cargo_config = self.config.cargo();
|
||||||
|
|
||||||
move |sender| {
|
move |sender| {
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use project_model::{CargoWorkspace, ProjectWorkspace, Sysroot, WorkspaceBuildScripts};
|
use project_model::{
|
||||||
|
CargoWorkspace, ManifestPath, Metadata, ProjectWorkspace, Sysroot, WorkspaceBuildScripts,
|
||||||
|
};
|
||||||
use rust_analyzer::ws_to_crate_graph;
|
use rust_analyzer::ws_to_crate_graph;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use vfs::{AbsPathBuf, FileId};
|
use vfs::{AbsPathBuf, FileId};
|
||||||
|
|
||||||
fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
|
fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
|
||||||
let meta = get_test_json_file(file);
|
let meta: Metadata = get_test_json_file(file);
|
||||||
let cargo_workspace = CargoWorkspace::new(meta);
|
let manifest_path =
|
||||||
|
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
|
||||||
|
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
|
||||||
ProjectWorkspace::Cargo {
|
ProjectWorkspace::Cargo {
|
||||||
cargo: cargo_workspace,
|
cargo: cargo_workspace,
|
||||||
build_scripts: WorkspaceBuildScripts::default(),
|
build_scripts: WorkspaceBuildScripts::default(),
|
||||||
|
|
|
@ -150,6 +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"],
|
||||||
}))
|
}))
|
||||||
.server()
|
.server()
|
||||||
.wait_until_workspace_is_loaded();
|
.wait_until_workspace_is_loaded();
|
||||||
|
|
|
@ -185,11 +185,7 @@ impl Project<'_> {
|
||||||
roots,
|
roots,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
// TODO: don't hardcode src/lib.rs as detached file
|
config.update(self.config).expect("invalid config");
|
||||||
let mut c = self.config;
|
|
||||||
let p = tmp_dir_path.join("src/lib.rs").to_string();
|
|
||||||
c["detachedFiles"] = serde_json::json!([p]);
|
|
||||||
config.update(c).expect("invalid config");
|
|
||||||
config.rediscover_workspaces();
|
config.rediscover_workspaces();
|
||||||
|
|
||||||
Server::new(tmp_dir.keep(), config)
|
Server::new(tmp_dir.keep(), config)
|
||||||
|
|
|
@ -778,7 +778,8 @@ Disable project auto-discovery in favor of explicitly specified set
|
||||||
of projects.
|
of projects.
|
||||||
|
|
||||||
Elements must be paths pointing to `Cargo.toml`,
|
Elements must be paths pointing to `Cargo.toml`,
|
||||||
`rust-project.json`, or JSON objects in `rust-project.json` format.
|
`rust-project.json`, `.rs` files (which will be treated as standalone files) or JSON
|
||||||
|
objects in `rust-project.json` format.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.lru.capacity]]rust-analyzer.lru.capacity (default: `null`)::
|
[[rust-analyzer.lru.capacity]]rust-analyzer.lru.capacity (default: `null`)::
|
||||||
+
|
+
|
||||||
|
|
|
@ -1495,7 +1495,7 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"rust-analyzer.linkedProjects": {
|
"rust-analyzer.linkedProjects": {
|
||||||
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set\nof projects.\n\nElements must be paths pointing to `Cargo.toml`,\n`rust-project.json`, or JSON objects in `rust-project.json` format.",
|
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set\nof projects.\n\nElements must be paths pointing to `Cargo.toml`,\n`rust-project.json`, `.rs` files (which will be treated as standalone files) or JSON\nobjects in `rust-project.json` format.",
|
||||||
"default": [],
|
"default": [],
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|
Loading…
Reference in a new issue