diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 7709f99b2e..98c5a02dcd 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -518,7 +518,13 @@ impl ProjectWorkspace { progress: &dyn Fn(String), ) -> anyhow::Result { match self { - ProjectWorkspace::Cargo { cargo, toolchain, sysroot, .. } => { + ProjectWorkspace::DetachedFile { + cargo_script: Some(cargo), + toolchain, + sysroot, + .. + } + | ProjectWorkspace::Cargo { cargo, toolchain, sysroot, .. } => { WorkspaceBuildScripts::run_for_workspace( config, cargo, @@ -530,9 +536,8 @@ impl ProjectWorkspace { format!("Failed to run build scripts for {}", cargo.workspace_root()) }) } - ProjectWorkspace::Json { .. } | ProjectWorkspace::DetachedFile { .. } => { - Ok(WorkspaceBuildScripts::default()) - } + ProjectWorkspace::DetachedFile { cargo_script: None, .. } + | ProjectWorkspace::Json { .. } => Ok(WorkspaceBuildScripts::default()), } } @@ -734,13 +739,50 @@ impl ProjectWorkspace { })) .collect() } - ProjectWorkspace::DetachedFile { file, sysroot, .. } => iter::once(PackageRoot { - is_local: true, - include: vec![file.clone()], - exclude: Vec::new(), - }) - .chain(mk_sysroot(sysroot.as_ref())) - .collect(), + ProjectWorkspace::DetachedFile { file, cargo_script, sysroot, .. } => { + iter::once(PackageRoot { + is_local: true, + include: vec![file.clone()], + exclude: Vec::new(), + }) + .chain(cargo_script.iter().flat_map(|cargo| { + cargo.packages().map(|pkg| { + let is_local = cargo[pkg].is_local; + let pkg_root = cargo[pkg].manifest.parent().to_path_buf(); + + let mut include = vec![pkg_root.clone()]; + + // In case target's path is manually set in Cargo.toml to be + // outside the package root, add its parent as an extra include. + // An example of this situation would look like this: + // + // ```toml + // [lib] + // path = "../../src/lib.rs" + // ``` + let extra_targets = cargo[pkg] + .targets + .iter() + .filter(|&&tgt| matches!(cargo[tgt].kind, TargetKind::Lib { .. })) + .filter_map(|&tgt| cargo[tgt].root.parent()) + .map(|tgt| tgt.normalize().to_path_buf()) + .filter(|path| !path.starts_with(&pkg_root)); + include.extend(extra_targets); + + let mut exclude = vec![pkg_root.join(".git")]; + if is_local { + exclude.push(pkg_root.join("target")); + } else { + exclude.push(pkg_root.join("tests")); + exclude.push(pkg_root.join("examples")); + exclude.push(pkg_root.join("benches")); + } + PackageRoot { is_local, include, exclude } + }) + })) + .chain(mk_sysroot(sysroot.as_ref())) + .collect() + } } } @@ -756,9 +798,10 @@ impl ProjectWorkspace { let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); cargo.packages().len() + sysroot_package_len + rustc_package_len } - ProjectWorkspace::DetachedFile { sysroot, .. } => { + ProjectWorkspace::DetachedFile { sysroot, cargo_script, .. } => { let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); - sysroot_package_len + 1 + sysroot_package_len + + cargo_script.as_ref().map_or(1, |cargo| cargo.packages().len()) } } } diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index 84065c6848..4b8c3d06ce 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -307,6 +307,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { } None } + // FIXME project_model::ProjectWorkspace::DetachedFile { .. } => return None, }; Some((idx, package)) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index aa5567bb66..cf97d7d9d2 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1761,7 +1761,9 @@ pub(crate) fn handle_open_docs( let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws { ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())), ProjectWorkspace::Json { .. } => None, - ProjectWorkspace::DetachedFile { .. } => None, + ProjectWorkspace::DetachedFile { cargo_script, sysroot, .. } => { + cargo_script.as_ref().zip(Some(sysroot.as_ref().ok())) + } }); let (cargo, sysroot) = match ws_and_sysroot { diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 557faaf84c..5d8a66cabc 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -682,6 +682,7 @@ impl GlobalState { _ => None, } } + // FIXME ProjectWorkspace::DetachedFile { .. } => None, }) .map(|(id, root, sysroot_root)| { diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index 22d8b6bdf1..b87f02947b 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -119,7 +119,8 @@ fn f() { #[test] fn completes_items_from_standard_library_in_cargo_script() { - if skip_slow_tests() { + // this test requires nightly so CI can't run it + if skip_slow_tests() || std::env::var("CI").is_ok() { return; } @@ -139,7 +140,7 @@ version = "0.1.0" pub struct SpecialHashMap2; //- /src/lib.rs #!/usr/bin/env -S cargo +nightly -Zscript ----cargo +--- [dependencies] dependency = { path = "../dependency" } --- @@ -178,7 +179,7 @@ use dependency2::Spam; server.write_file_and_save( "src/lib.rs", r#"#!/usr/bin/env -S cargo +nightly -Zscript ----cargo +--- [dependencies] dependency2 = { path = "../dependency2" } ---