Skip to content

Commit a2ed683

Browse files
committed
Allow rust files to be used linkedProjects
1 parent 55d9a53 commit a2ed683

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)