about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-04-21 17:34:21 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-04-21 17:40:17 +0200
commit0a29e6fc85cf6cf18b02c7eaaaf4a9b79e00d52c (patch)
tree98c9f26c55c17b88312d5db540d126522bbbd53e
parent92ace4b1394581e6f1df60de735355494eff7871 (diff)
downloadrust-0a29e6fc85cf6cf18b02c7eaaaf4a9b79e00d52c.tar.gz
rust-0a29e6fc85cf6cf18b02c7eaaaf4a9b79e00d52c.zip
Support flychecking for cargo scripts
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs30
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs48
7 files changed, 61 insertions, 44 deletions
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index 5dfaaf77420..6d5ca8321e5 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -125,8 +125,10 @@ impl FlycheckHandle {
         config: FlycheckConfig,
         sysroot_root: Option<AbsPathBuf>,
         workspace_root: AbsPathBuf,
+        manifest_path: Option<AbsPathBuf>,
     ) -> FlycheckHandle {
-        let actor = FlycheckActor::new(id, sender, config, sysroot_root, workspace_root);
+        let actor =
+            FlycheckActor::new(id, sender, config, sysroot_root, workspace_root, manifest_path);
         let (sender, receiver) = unbounded::<StateChange>();
         let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
             .name("Flycheck".to_owned())
@@ -205,6 +207,7 @@ struct FlycheckActor {
     id: usize,
     sender: Box<dyn Fn(Message) + Send>,
     config: FlycheckConfig,
+    manifest_path: Option<AbsPathBuf>,
     /// Either the workspace root of the workspace we are flychecking,
     /// or the project root of the project.
     root: AbsPathBuf,
@@ -233,6 +236,7 @@ impl FlycheckActor {
         config: FlycheckConfig,
         sysroot_root: Option<AbsPathBuf>,
         workspace_root: AbsPathBuf,
+        manifest_path: Option<AbsPathBuf>,
     ) -> FlycheckActor {
         tracing::info!(%id, ?workspace_root, "Spawning flycheck");
         FlycheckActor {
@@ -241,6 +245,7 @@ impl FlycheckActor {
             config,
             sysroot_root,
             root: workspace_root,
+            manifest_path,
             command_handle: None,
             command_receiver: None,
         }
@@ -388,8 +393,13 @@ impl FlycheckActor {
                     "--message-format=json"
                 });
 
-                cmd.arg("--manifest-path");
-                cmd.arg(self.root.join("Cargo.toml"));
+                if let Some(manifest_path) = &self.manifest_path {
+                    cmd.arg("--manifest-path");
+                    cmd.arg(manifest_path);
+                    if manifest_path.extension().map_or(false, |ext| ext == "rs") {
+                        cmd.arg("-Zscript");
+                    }
+                }
 
                 options.apply_on_command(&mut cmd);
                 (cmd, options.extra_args.clone())
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index f8485d336ec..7f845f85aeb 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -91,7 +91,7 @@ pub enum ProjectWorkspaceKind {
         /// The file in question.
         file: ManifestPath,
         /// Is this file a cargo script file?
-        cargo_script: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
+        cargo: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
         /// Environment variables set in the `.cargo/config` file.
         cargo_config_extra_env: FxHashMap<String, String>,
     },
@@ -135,7 +135,11 @@ impl fmt::Debug for ProjectWorkspace {
                     .field("n_cfg_overrides", &cfg_overrides.len());
                 debug_struct.finish()
             }
-            ProjectWorkspaceKind::DetachedFile { file, cargo_script, cargo_config_extra_env } => f
+            ProjectWorkspaceKind::DetachedFile {
+                file,
+                cargo: cargo_script,
+                cargo_config_extra_env,
+            } => f
                 .debug_struct("DetachedFiles")
                 .field("file", &file)
                 .field("cargo_script", &cargo_script.is_some())
@@ -451,7 +455,7 @@ impl ProjectWorkspace {
         Ok(ProjectWorkspace {
             kind: ProjectWorkspaceKind::DetachedFile {
                 file: detached_file.to_owned(),
-                cargo_script,
+                cargo: cargo_script,
                 cargo_config_extra_env,
             },
             sysroot,
@@ -476,7 +480,7 @@ impl ProjectWorkspace {
         progress: &dyn Fn(String),
     ) -> anyhow::Result<WorkspaceBuildScripts> {
         match &self.kind {
-            ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. }
+            ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. }
             | ProjectWorkspaceKind::Cargo { cargo, .. } => {
                 WorkspaceBuildScripts::run_for_workspace(
                     config,
@@ -489,7 +493,7 @@ impl ProjectWorkspace {
                     format!("Failed to run build scripts for {}", cargo.workspace_root())
                 })
             }
-            ProjectWorkspaceKind::DetachedFile { cargo_script: None, .. }
+            ProjectWorkspaceKind::DetachedFile { cargo: None, .. }
             | ProjectWorkspaceKind::Json { .. } => Ok(WorkspaceBuildScripts::default()),
         }
     }
@@ -540,9 +544,9 @@ impl ProjectWorkspace {
     pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
         match &mut self.kind {
             ProjectWorkspaceKind::Cargo { build_scripts, .. }
-            | ProjectWorkspaceKind::DetachedFile {
-                cargo_script: Some((_, build_scripts)), ..
-            } => *build_scripts = bs,
+            | ProjectWorkspaceKind::DetachedFile { cargo: Some((_, build_scripts)), .. } => {
+                *build_scripts = bs
+            }
             _ => assert_eq!(bs, WorkspaceBuildScripts::default()),
         }
     }
@@ -674,7 +678,7 @@ impl ProjectWorkspace {
                     }))
                     .collect()
             }
-            ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => {
+            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => {
                 iter::once(PackageRoot {
                     is_local: true,
                     include: vec![file.as_ref().to_owned()],
@@ -736,7 +740,7 @@ impl ProjectWorkspace {
                 let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
                 cargo.packages().len() + sysroot_package_len + rustc_package_len
             }
-            ProjectWorkspaceKind::DetachedFile { cargo_script, .. } => {
+            ProjectWorkspaceKind::DetachedFile { cargo: cargo_script, .. } => {
                 let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
                 sysroot_package_len
                     + cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len())
@@ -781,7 +785,7 @@ impl ProjectWorkspace {
                 ),
                 sysroot,
             ),
-            ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => (
+            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => (
                 if let Some((cargo, build_scripts)) = cargo_script {
                     cargo_to_crate_graph(
                         &mut |path| load(path),
@@ -851,12 +855,12 @@ impl ProjectWorkspace {
             (
                 ProjectWorkspaceKind::DetachedFile {
                     file,
-                    cargo_script: Some((cargo_script, _)),
+                    cargo: Some((cargo_script, _)),
                     cargo_config_extra_env,
                 },
                 ProjectWorkspaceKind::DetachedFile {
                     file: o_file,
-                    cargo_script: Some((o_cargo_script, _)),
+                    cargo: Some((o_cargo_script, _)),
                     cargo_config_extra_env: o_cargo_config_extra_env,
                 },
             ) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index d38fcf92ced..85f964b1dd9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -81,7 +81,7 @@ impl Tester {
         let workspace = ProjectWorkspace {
             kind: ProjectWorkspaceKind::DetachedFile {
                 file: ManifestPath::try_from(tmp_file).unwrap(),
-                cargo_script: None,
+                cargo: None,
                 cargo_config_extra_env: Default::default(),
             },
             sysroot,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index d2c9f466e5a..1fcb5d44962 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -521,7 +521,7 @@ impl GlobalStateSnapshot {
         let path = path.as_path()?;
         self.workspaces.iter().find_map(|ws| match &ws.kind {
             ProjectWorkspaceKind::Cargo { cargo, .. }
-            | ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => {
+            | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
                 cargo.target_by_root(path).map(|it| (cargo, it))
             }
             ProjectWorkspaceKind::Json { .. } => None,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index 253d5498aa4..fee8e972739 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -292,7 +292,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                 let package = match &ws.kind {
                     project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
                     | project_model::ProjectWorkspaceKind::DetachedFile {
-                        cargo_script: Some((cargo, _)),
+                        cargo: Some((cargo, _)),
                         ..
                     } => cargo.packages().find_map(|pkg| {
                         let has_target_with_root = cargo[pkg]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index dfefb862072..6afcc2c51f8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -767,7 +767,8 @@ pub(crate) fn handle_parent_module(
                 .workspaces
                 .iter()
                 .filter_map(|ws| match &ws.kind {
-                    ProjectWorkspaceKind::Cargo { cargo, .. } => {
+                    ProjectWorkspaceKind::Cargo { cargo, .. }
+                    | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
                         cargo.parent_manifests(&manifest_path)
                     }
                     _ => None,
@@ -1759,7 +1760,7 @@ pub(crate) fn handle_open_docs(
 
     let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
         ProjectWorkspaceKind::Cargo { cargo, .. }
-        | ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => {
+        | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
             Some((cargo, ws.sysroot.as_ref().ok()))
         }
         ProjectWorkspaceKind::Json { .. } => None,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index 4a2fbaa6784..f2b6e3ed032 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -502,7 +502,7 @@ impl GlobalState {
                 let env = match &ws.kind {
                     ProjectWorkspaceKind::Cargo { cargo_config_extra_env, .. }
                     | ProjectWorkspaceKind::DetachedFile {
-                        cargo_script: Some(_),
+                        cargo: Some(_),
                         cargo_config_extra_env,
                         ..
                     } => cargo_config_extra_env
@@ -669,36 +669,37 @@ impl GlobalState {
                 config,
                 None,
                 self.config.root_path().clone(),
+                None,
             )],
             flycheck::InvocationStrategy::PerWorkspace => {
                 self.workspaces
                     .iter()
                     .enumerate()
-                    .filter_map(|(id, ws)| match &ws.kind {
-                        ProjectWorkspaceKind::Cargo { cargo, .. } => Some((
+                    .filter_map(|(id, ws)| {
+                        Some((
                             id,
-                            cargo.workspace_root(),
+                            match &ws.kind {
+                                ProjectWorkspaceKind::Cargo { cargo, .. }
+                                | ProjectWorkspaceKind::DetachedFile {
+                                    cargo: Some((cargo, _)),
+                                    ..
+                                } => (cargo.workspace_root(), Some(cargo.manifest_path())),
+                                ProjectWorkspaceKind::Json(project) => {
+                                    // Enable flychecks for json projects if a custom flycheck command was supplied
+                                    // in the workspace configuration.
+                                    match config {
+                                        FlycheckConfig::CustomCommand { .. } => {
+                                            (project.path(), None)
+                                        }
+                                        _ => return None,
+                                    }
+                                }
+                                ProjectWorkspaceKind::DetachedFile { .. } => return None,
+                            },
                             ws.sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
-                        )),
-                        ProjectWorkspaceKind::Json(project) => {
-                            // Enable flychecks for json projects if a custom flycheck command was supplied
-                            // in the workspace configuration.
-                            match config {
-                                FlycheckConfig::CustomCommand { .. } => Some((
-                                    id,
-                                    project.path(),
-                                    ws.sysroot
-                                        .as_ref()
-                                        .ok()
-                                        .map(|sysroot| sysroot.root().to_owned()),
-                                )),
-                                _ => None,
-                            }
-                        }
-                        // FIXME
-                        ProjectWorkspaceKind::DetachedFile { .. } => None,
+                        ))
                     })
-                    .map(|(id, root, sysroot_root)| {
+                    .map(|(id, (root, manifest_path), sysroot_root)| {
                         let sender = sender.clone();
                         FlycheckHandle::spawn(
                             id,
@@ -706,6 +707,7 @@ impl GlobalState {
                             config.clone(),
                             sysroot_root,
                             root.to_path_buf(),
+                            manifest_path.map(|it| it.to_path_buf()),
                         )
                     })
                     .collect()