Skip to content

Commit f512a5e

Browse files
committed
Auto merge of #17118 - Veykril:linked-rust-files, r=Veykril
feat: Allow rust files to be used linkedProjects With this, script files become more usable as the user can at least add them manually to the linked projects, allowing them to be used "on the (manual) fly" without having to open a separate vscode window that only has files open and no folder. Also makes build scripts work for them (though no proc-macros, for some reason the dylib field is not populated in the output)
2 parents 55d9a53 + a2ed683 commit f512a5e

File tree

21 files changed

+201
-178
lines changed

21 files changed

+201
-178
lines changed

crates/base-db/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub trait FileLoader {
5151
/// Text of the file.
5252
fn file_text(&self, file_id: FileId) -> Arc<str>;
5353
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
54+
/// Crates whose root's source root is the same as the source root of `file_id`
5455
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
5556
}
5657

@@ -104,6 +105,7 @@ pub trait SourceDatabaseExt: SourceDatabase {
104105
#[salsa::input]
105106
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
106107

108+
/// Crates whose root fool is in `id`.
107109
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
108110
}
109111

crates/hir/src/semantics/source_to_def.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,17 @@ impl SourceToDefCtx<'_, '_> {
121121
let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def").entered();
122122
let mut mods = SmallVec::new();
123123
for &crate_id in self.db.relevant_crates(file).iter() {
124-
// FIXME: inner items
124+
// Note: `mod` declarations in block modules cannot be supported here
125125
let crate_def_map = self.db.crate_def_map(crate_id);
126126
mods.extend(
127127
crate_def_map
128128
.modules_for_file(file)
129129
.map(|local_id| crate_def_map.module_id(local_id)),
130130
)
131131
}
132+
if mods.is_empty() {
133+
// FIXME: detached file
134+
}
132135
mods
133136
}
134137

crates/ide-db/src/prime_caches.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! rust-analyzer is lazy and doesn't compute anything unless asked. This
22
//! sometimes is counter productive when, for example, the first goto definition
3-
//! request takes longer to compute. This modules implemented prepopulation of
3+
//! request takes longer to compute. This module implements prepopulation of
44
//! various caches, it's not really advanced at the moment.
55
mod topologic_sort;
66

crates/project-model/src/build_scripts.rs

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use toolchain::Tool;
2424

2525
use crate::{
2626
cfg::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
27-
InvocationStrategy, Package, Sysroot, TargetKind,
27+
InvocationStrategy, ManifestPath, Package, Sysroot, TargetKind,
2828
};
2929

3030
/// Output of the build script and proc-macro building steps for a workspace.
@@ -63,7 +63,7 @@ impl WorkspaceBuildScripts {
6363
fn build_command(
6464
config: &CargoConfig,
6565
allowed_features: &FxHashSet<String>,
66-
workspace_root: &AbsPathBuf,
66+
manifest_path: &ManifestPath,
6767
sysroot: Option<&Sysroot>,
6868
) -> io::Result<Command> {
6969
let mut cmd = match config.run_build_script_command.as_deref() {
@@ -79,7 +79,7 @@ impl WorkspaceBuildScripts {
7979
cmd.args(&config.extra_args);
8080

8181
cmd.arg("--manifest-path");
82-
cmd.arg(workspace_root.join("Cargo.toml"));
82+
cmd.arg(manifest_path.as_ref());
8383

8484
if let Some(target_dir) = &config.target_dir {
8585
cmd.arg("--target-dir").arg(target_dir);
@@ -116,6 +116,10 @@ impl WorkspaceBuildScripts {
116116
}
117117
}
118118

119+
if manifest_path.extension().map_or(false, |ext| ext == "rs") {
120+
cmd.arg("-Zscript");
121+
}
122+
119123
cmd
120124
}
121125
};
@@ -152,37 +156,12 @@ impl WorkspaceBuildScripts {
152156
.as_ref();
153157

154158
let allowed_features = workspace.workspace_features();
155-
156-
match Self::run_per_ws(
157-
Self::build_command(
158-
config,
159-
&allowed_features,
160-
&workspace.workspace_root().to_path_buf(),
161-
sysroot,
162-
)?,
163-
workspace,
164-
current_dir,
165-
progress,
166-
) {
167-
Ok(WorkspaceBuildScripts { error: Some(error), .. })
168-
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_75) =>
169-
{
170-
// building build scripts failed, attempt to build with --keep-going so
171-
// that we potentially get more build data
172-
let mut cmd = Self::build_command(
173-
config,
174-
&allowed_features,
175-
&workspace.workspace_root().to_path_buf(),
176-
sysroot,
177-
)?;
178-
179-
cmd.args(["--keep-going"]);
180-
let mut res = Self::run_per_ws(cmd, workspace, current_dir, progress)?;
181-
res.error = Some(error);
182-
Ok(res)
183-
}
184-
res => res,
159+
let mut cmd =
160+
Self::build_command(config, &allowed_features, workspace.manifest_path(), sysroot)?;
161+
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_75) {
162+
cmd.args(["--keep-going"]);
185163
}
164+
Self::run_per_ws(cmd, workspace, current_dir, progress)
186165
}
187166

188167
/// Runs the build scripts by invoking the configured command *once*.
@@ -204,7 +183,13 @@ impl WorkspaceBuildScripts {
204183
))
205184
}
206185
};
207-
let cmd = Self::build_command(config, &Default::default(), workspace_root, None)?;
186+
let cmd = Self::build_command(
187+
config,
188+
&Default::default(),
189+
// This is not gonna be used anyways, so just construct a dummy here
190+
&ManifestPath::try_from(workspace_root.clone()).unwrap(),
191+
None,
192+
)?;
208193
// NB: Cargo.toml could have been modified between `cargo metadata` and
209194
// `cargo check`. We shouldn't assume that package ids we see here are
210195
// exactly those from `config`.

crates/project-model/src/cargo_workspace.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub struct CargoWorkspace {
3232
targets: Arena<TargetData>,
3333
workspace_root: AbsPathBuf,
3434
target_directory: AbsPathBuf,
35+
manifest_path: ManifestPath,
3536
}
3637

3738
impl ops::Index<Package> for CargoWorkspace {
@@ -334,7 +335,7 @@ impl CargoWorkspace {
334335
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))
335336
}
336337

337-
pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
338+
pub fn new(mut meta: cargo_metadata::Metadata, manifest_path: ManifestPath) -> CargoWorkspace {
338339
let mut pkg_by_id = FxHashMap::default();
339340
let mut packages = Arena::default();
340341
let mut targets = Arena::default();
@@ -448,7 +449,7 @@ impl CargoWorkspace {
448449

449450
let target_directory = AbsPathBuf::assert(meta.target_directory);
450451

451-
CargoWorkspace { packages, targets, workspace_root, target_directory }
452+
CargoWorkspace { packages, targets, workspace_root, target_directory, manifest_path }
452453
}
453454

454455
pub fn packages(&self) -> impl ExactSizeIterator<Item = Package> + '_ {
@@ -466,6 +467,10 @@ impl CargoWorkspace {
466467
&self.workspace_root
467468
}
468469

470+
pub fn manifest_path(&self) -> &ManifestPath {
471+
&self.manifest_path
472+
}
473+
469474
pub fn target_directory(&self) -> &AbsPath {
470475
&self.target_directory
471476
}

crates/project-model/src/lib.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ pub use crate::{
5454
sysroot::Sysroot,
5555
workspace::{FileLoader, PackageRoot, ProjectWorkspace},
5656
};
57+
pub use cargo_metadata::Metadata;
5758

5859
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
5960
pub enum ProjectManifest {
6061
ProjectJson(ManifestPath),
6162
CargoToml(ManifestPath),
63+
CargoScript(ManifestPath),
6264
}
6365

6466
impl ProjectManifest {
@@ -71,7 +73,10 @@ impl ProjectManifest {
7173
if path.file_name().unwrap_or_default() == "Cargo.toml" {
7274
return Ok(ProjectManifest::CargoToml(path));
7375
}
74-
bail!("project root must point to Cargo.toml or rust-project.json: {path}");
76+
if path.extension().unwrap_or_default() == "rs" {
77+
return Ok(ProjectManifest::CargoScript(path));
78+
}
79+
bail!("project root must point to a Cargo.toml, rust-project.json or <script>.rs file: {path}");
7580
}
7681

7782
pub fn discover_single(path: &AbsPath) -> anyhow::Result<ProjectManifest> {
@@ -146,15 +151,19 @@ impl ProjectManifest {
146151
res.sort();
147152
res
148153
}
154+
155+
pub fn manifest_path(&self) -> &ManifestPath {
156+
match self {
157+
ProjectManifest::ProjectJson(it)
158+
| ProjectManifest::CargoToml(it)
159+
| ProjectManifest::CargoScript(it) => it,
160+
}
161+
}
149162
}
150163

151164
impl fmt::Display for ProjectManifest {
152165
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153-
match self {
154-
ProjectManifest::ProjectJson(it) | ProjectManifest::CargoToml(it) => {
155-
fmt::Display::fmt(&it, f)
156-
}
157-
}
166+
fmt::Display::fmt(self.manifest_path(), f)
158167
}
159168
}
160169

crates/project-model/src/manifest_path.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! See [`ManifestPath`].
2-
use std::{fmt, ops, path::Path};
2+
use std::{borrow::Borrow, fmt, ops};
33

44
use paths::{AbsPath, AbsPathBuf};
55

@@ -54,8 +54,14 @@ impl ops::Deref for ManifestPath {
5454
}
5555
}
5656

57-
impl AsRef<Path> for ManifestPath {
58-
fn as_ref(&self) -> &Path {
57+
impl AsRef<AbsPath> for ManifestPath {
58+
fn as_ref(&self) -> &AbsPath {
5959
self.file.as_ref()
6060
}
6161
}
62+
63+
impl Borrow<AbsPath> for ManifestPath {
64+
fn borrow(&self) -> &AbsPath {
65+
self.file.borrow()
66+
}
67+
}

crates/project-model/src/sysroot.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl Sysroot {
349349
.filter(|&package| RELEVANT_SYSROOT_CRATES.contains(&&*package.name))
350350
.map(|package| package.id.clone())
351351
.collect();
352-
let cargo_workspace = CargoWorkspace::new(res);
352+
let cargo_workspace = CargoWorkspace::new(res, sysroot_cargo_toml);
353353
Some(Sysroot {
354354
root: sysroot_dir.clone(),
355355
src_root: Some(Ok(sysroot_src_dir.clone())),
@@ -368,7 +368,7 @@ impl Sysroot {
368368
.into_iter()
369369
.map(|it| sysroot_src_dir.join(it))
370370
.filter_map(|it| ManifestPath::try_from(it).ok())
371-
.find(|it| fs::metadata(it).is_ok());
371+
.find(|it| fs::metadata(it.as_ref()).is_ok());
372372

373373
if let Some(root) = root {
374374
stitched.crates.alloc(SysrootCrateData {
@@ -468,7 +468,7 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option<ManifestPath> {
468468
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
469469
let rustc_src = ManifestPath::try_from(rustc_src).ok()?;
470470
tracing::debug!("checking for rustc source code: {rustc_src}");
471-
if fs::metadata(&rustc_src).is_ok() {
471+
if fs::metadata(rustc_src.as_ref()).is_ok() {
472472
Some(rustc_src)
473473
} else {
474474
None

crates/project-model/src/tests.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::ops::Deref;
22

33
use base_db::{CrateGraph, FileId, ProcMacroPaths};
4+
use cargo_metadata::Metadata;
45
use cfg::{CfgAtom, CfgDiff};
56
use expect_test::{expect_file, ExpectFile};
67
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
@@ -9,8 +10,8 @@ use serde::de::DeserializeOwned;
910
use triomphe::Arc;
1011

1112
use crate::{
12-
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
13-
WorkspaceBuildScripts,
13+
CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace,
14+
Sysroot, WorkspaceBuildScripts,
1415
};
1516

1617
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
@@ -21,8 +22,10 @@ fn load_cargo_with_overrides(
2122
file: &str,
2223
cfg_overrides: CfgOverrides,
2324
) -> (CrateGraph, ProcMacroPaths) {
24-
let meta = get_test_json_file(file);
25-
let cargo_workspace = CargoWorkspace::new(meta);
25+
let meta: Metadata = get_test_json_file(file);
26+
let manifest_path =
27+
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
28+
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
2629
let project_workspace = ProjectWorkspace::Cargo {
2730
cargo: cargo_workspace,
2831
build_scripts: WorkspaceBuildScripts::default(),
@@ -41,8 +44,10 @@ fn load_cargo_with_fake_sysroot(
4144
file_map: &mut FxHashMap<AbsPathBuf, FileId>,
4245
file: &str,
4346
) -> (CrateGraph, ProcMacroPaths) {
44-
let meta = get_test_json_file(file);
45-
let cargo_workspace = CargoWorkspace::new(meta);
47+
let meta: Metadata = get_test_json_file(file);
48+
let manifest_path =
49+
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
50+
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
4651
let project_workspace = ProjectWorkspace::Cargo {
4752
cargo: cargo_workspace,
4853
build_scripts: WorkspaceBuildScripts::default(),
@@ -268,9 +273,10 @@ fn smoke_test_real_sysroot_cargo() {
268273
return;
269274
}
270275
let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
271-
let meta = get_test_json_file("hello-world-metadata.json");
272-
273-
let cargo_workspace = CargoWorkspace::new(meta);
276+
let meta: Metadata = get_test_json_file("hello-world-metadata.json");
277+
let manifest_path =
278+
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
279+
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
274280
let sysroot = Ok(Sysroot::discover(
275281
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
276282
&Default::default(),

0 commit comments

Comments
 (0)