Skip to content

Commit b2abbf8

Browse files
committed
feat: Make rust-analyzer work partially when missing an internet connection
1 parent 0765978 commit b2abbf8

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

crates/project-model/src/cargo_workspace.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ impl CargoWorkspace {
259259
sysroot: &Sysroot,
260260
locked: bool,
261261
progress: &dyn Fn(String),
262+
) -> anyhow::Result<cargo_metadata::Metadata> {
263+
Self::fetch_metadata_(cargo_toml, current_dir, config, sysroot, locked, false, progress)
264+
}
265+
266+
fn fetch_metadata_(
267+
cargo_toml: &ManifestPath,
268+
current_dir: &AbsPath,
269+
config: &CargoConfig,
270+
sysroot: &Sysroot,
271+
locked: bool,
272+
no_deps: bool,
273+
progress: &dyn Fn(String),
262274
) -> anyhow::Result<cargo_metadata::Metadata> {
263275
let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
264276

@@ -314,6 +326,9 @@ impl CargoWorkspace {
314326
if locked {
315327
other_options.push("--locked".to_owned());
316328
}
329+
if no_deps {
330+
other_options.push("--no-deps".to_owned());
331+
}
317332
meta.other_options(other_options);
318333

319334
// FIXME: Fetching metadata is a slow process, as it might require
@@ -324,6 +339,22 @@ impl CargoWorkspace {
324339
(|| -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
325340
let output = meta.cargo_command().output()?;
326341
if !output.status.success() {
342+
if !no_deps {
343+
// If we failed to fetch metadata with deps, try again without them.
344+
// This makes r-a still work partially when offline.
345+
if let Ok(metadata) = Self::fetch_metadata_(
346+
cargo_toml,
347+
current_dir,
348+
config,
349+
sysroot,
350+
locked,
351+
true,
352+
progress,
353+
) {
354+
return Ok(metadata);
355+
}
356+
}
357+
327358
return Err(cargo_metadata::Error::CargoMetadata {
328359
stderr: String::from_utf8(output.stderr)?,
329360
});
@@ -431,8 +462,8 @@ impl CargoWorkspace {
431462
pkg_data.targets.push(tgt);
432463
}
433464
}
434-
let resolve = meta.resolve.expect("metadata executed with deps");
435-
for mut node in resolve.nodes {
465+
let nodes = meta.resolve.map_or_else(Vec::new, |it| it.nodes);
466+
for mut node in nodes {
436467
let &source = pkg_by_id.get(&node.id).unwrap();
437468
node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg));
438469
let dependencies = node

crates/project-model/src/sysroot.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -372,18 +372,19 @@ impl Sysroot {
372372
.flatten()
373373
};
374374

375-
let resolve = res.resolve.as_mut().expect("metadata executed with deps");
376-
resolve.nodes.retain_mut(|node| {
377-
// Replace `rustc-std-workspace` crate with the actual one in the dependency list
378-
node.deps.iter_mut().for_each(|dep| {
379-
let real_pkg = patches.clone().find(|((_, fake_id), _)| *fake_id == dep.pkg);
380-
if let Some((_, real)) = real_pkg {
381-
dep.pkg = real;
382-
}
375+
if let Some(resolve) = res.resolve.as_mut() {
376+
resolve.nodes.retain_mut(|node| {
377+
// Replace `rustc-std-workspace` crate with the actual one in the dependency list
378+
node.deps.iter_mut().for_each(|dep| {
379+
let real_pkg = patches.clone().find(|((_, fake_id), _)| *fake_id == dep.pkg);
380+
if let Some((_, real)) = real_pkg {
381+
dep.pkg = real;
382+
}
383+
});
384+
// Remove this node if it's a fake one
385+
!patches.clone().any(|((_, fake), _)| fake == node.id)
383386
});
384-
// Remove this node if it's a fake one
385-
!patches.clone().any(|((_, fake), _)| fake == node.id)
386-
});
387+
}
387388
// Remove the fake ones from the package list
388389
patches.map(|((idx, _), _)| idx).sorted().rev().for_each(|idx| {
389390
res.packages.remove(idx);

0 commit comments

Comments
 (0)