Support flychecking for cargo scripts

This commit is contained in:
Lukas Wirth 2024-04-21 17:34:21 +02:00
parent ff56cb6e49
commit fa754becc4
7 changed files with 61 additions and 44 deletions

View file

@ -125,8 +125,10 @@ impl FlycheckHandle {
config: FlycheckConfig, config: FlycheckConfig,
sysroot_root: Option<AbsPathBuf>, sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf, workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
) -> FlycheckHandle { ) -> 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 (sender, receiver) = unbounded::<StateChange>();
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
.name("Flycheck".to_owned()) .name("Flycheck".to_owned())
@ -205,6 +207,7 @@ struct FlycheckActor {
id: usize, id: usize,
sender: Box<dyn Fn(Message) + Send>, sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig, config: FlycheckConfig,
manifest_path: Option<AbsPathBuf>,
/// Either the workspace root of the workspace we are flychecking, /// Either the workspace root of the workspace we are flychecking,
/// or the project root of the project. /// or the project root of the project.
root: AbsPathBuf, root: AbsPathBuf,
@ -233,6 +236,7 @@ impl FlycheckActor {
config: FlycheckConfig, config: FlycheckConfig,
sysroot_root: Option<AbsPathBuf>, sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf, workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
) -> FlycheckActor { ) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck"); tracing::info!(%id, ?workspace_root, "Spawning flycheck");
FlycheckActor { FlycheckActor {
@ -241,6 +245,7 @@ impl FlycheckActor {
config, config,
sysroot_root, sysroot_root,
root: workspace_root, root: workspace_root,
manifest_path,
command_handle: None, command_handle: None,
command_receiver: None, command_receiver: None,
} }
@ -388,8 +393,13 @@ impl FlycheckActor {
"--message-format=json" "--message-format=json"
}); });
cmd.arg("--manifest-path"); if let Some(manifest_path) = &self.manifest_path {
cmd.arg(self.root.join("Cargo.toml")); 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); options.apply_on_command(&mut cmd);
(cmd, options.extra_args.clone()) (cmd, options.extra_args.clone())

View file

@ -91,7 +91,7 @@ pub enum ProjectWorkspaceKind {
/// The file in question. /// The file in question.
file: ManifestPath, file: ManifestPath,
/// Is this file a cargo script file? /// Is this file a cargo script file?
cargo_script: Option<(CargoWorkspace, WorkspaceBuildScripts)>, cargo: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
/// Environment variables set in the `.cargo/config` file. /// Environment variables set in the `.cargo/config` file.
cargo_config_extra_env: FxHashMap<String, String>, cargo_config_extra_env: FxHashMap<String, String>,
}, },
@ -135,7 +135,11 @@ impl fmt::Debug for ProjectWorkspace {
.field("n_cfg_overrides", &cfg_overrides.len()); .field("n_cfg_overrides", &cfg_overrides.len());
debug_struct.finish() 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") .debug_struct("DetachedFiles")
.field("file", &file) .field("file", &file)
.field("cargo_script", &cargo_script.is_some()) .field("cargo_script", &cargo_script.is_some())
@ -451,7 +455,7 @@ impl ProjectWorkspace {
Ok(ProjectWorkspace { Ok(ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile { kind: ProjectWorkspaceKind::DetachedFile {
file: detached_file.to_owned(), file: detached_file.to_owned(),
cargo_script, cargo: cargo_script,
cargo_config_extra_env, cargo_config_extra_env,
}, },
sysroot, sysroot,
@ -476,7 +480,7 @@ impl ProjectWorkspace {
progress: &dyn Fn(String), progress: &dyn Fn(String),
) -> anyhow::Result<WorkspaceBuildScripts> { ) -> anyhow::Result<WorkspaceBuildScripts> {
match &self.kind { match &self.kind {
ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. }
| ProjectWorkspaceKind::Cargo { cargo, .. } => { | ProjectWorkspaceKind::Cargo { cargo, .. } => {
WorkspaceBuildScripts::run_for_workspace( WorkspaceBuildScripts::run_for_workspace(
config, config,
@ -489,7 +493,7 @@ impl ProjectWorkspace {
format!("Failed to run build scripts for {}", cargo.workspace_root()) format!("Failed to run build scripts for {}", cargo.workspace_root())
}) })
} }
ProjectWorkspaceKind::DetachedFile { cargo_script: None, .. } ProjectWorkspaceKind::DetachedFile { cargo: None, .. }
| ProjectWorkspaceKind::Json { .. } => Ok(WorkspaceBuildScripts::default()), | ProjectWorkspaceKind::Json { .. } => Ok(WorkspaceBuildScripts::default()),
} }
} }
@ -540,9 +544,9 @@ impl ProjectWorkspace {
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) { pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
match &mut self.kind { match &mut self.kind {
ProjectWorkspaceKind::Cargo { build_scripts, .. } ProjectWorkspaceKind::Cargo { build_scripts, .. }
| ProjectWorkspaceKind::DetachedFile { | ProjectWorkspaceKind::DetachedFile { cargo: Some((_, build_scripts)), .. } => {
cargo_script: Some((_, build_scripts)), .. *build_scripts = bs
} => *build_scripts = bs, }
_ => assert_eq!(bs, WorkspaceBuildScripts::default()), _ => assert_eq!(bs, WorkspaceBuildScripts::default()),
} }
} }
@ -674,7 +678,7 @@ impl ProjectWorkspace {
})) }))
.collect() .collect()
} }
ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => { ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => {
iter::once(PackageRoot { iter::once(PackageRoot {
is_local: true, is_local: true,
include: vec![file.as_ref().to_owned()], 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()); let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
cargo.packages().len() + sysroot_package_len + rustc_package_len 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()); let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
sysroot_package_len sysroot_package_len
+ cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len()) + cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len())
@ -781,7 +785,7 @@ impl ProjectWorkspace {
), ),
sysroot, sysroot,
), ),
ProjectWorkspaceKind::DetachedFile { file, cargo_script, .. } => ( ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => (
if let Some((cargo, build_scripts)) = cargo_script { if let Some((cargo, build_scripts)) = cargo_script {
cargo_to_crate_graph( cargo_to_crate_graph(
&mut |path| load(path), &mut |path| load(path),
@ -851,12 +855,12 @@ impl ProjectWorkspace {
( (
ProjectWorkspaceKind::DetachedFile { ProjectWorkspaceKind::DetachedFile {
file, file,
cargo_script: Some((cargo_script, _)), cargo: Some((cargo_script, _)),
cargo_config_extra_env, cargo_config_extra_env,
}, },
ProjectWorkspaceKind::DetachedFile { ProjectWorkspaceKind::DetachedFile {
file: o_file, file: o_file,
cargo_script: Some((o_cargo_script, _)), cargo: Some((o_cargo_script, _)),
cargo_config_extra_env: o_cargo_config_extra_env, cargo_config_extra_env: o_cargo_config_extra_env,
}, },
) => { ) => {

View file

@ -81,7 +81,7 @@ impl Tester {
let workspace = ProjectWorkspace { let workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile { kind: ProjectWorkspaceKind::DetachedFile {
file: ManifestPath::try_from(tmp_file).unwrap(), file: ManifestPath::try_from(tmp_file).unwrap(),
cargo_script: None, cargo: None,
cargo_config_extra_env: Default::default(), cargo_config_extra_env: Default::default(),
}, },
sysroot, sysroot,

View file

@ -521,7 +521,7 @@ impl GlobalStateSnapshot {
let path = path.as_path()?; let path = path.as_path()?;
self.workspaces.iter().find_map(|ws| match &ws.kind { self.workspaces.iter().find_map(|ws| match &ws.kind {
ProjectWorkspaceKind::Cargo { cargo, .. } ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => { | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
cargo.target_by_root(path).map(|it| (cargo, it)) cargo.target_by_root(path).map(|it| (cargo, it))
} }
ProjectWorkspaceKind::Json { .. } => None, ProjectWorkspaceKind::Json { .. } => None,

View file

@ -292,7 +292,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
let package = match &ws.kind { let package = match &ws.kind {
project_model::ProjectWorkspaceKind::Cargo { cargo, .. } project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
| project_model::ProjectWorkspaceKind::DetachedFile { | project_model::ProjectWorkspaceKind::DetachedFile {
cargo_script: Some((cargo, _)), cargo: Some((cargo, _)),
.. ..
} => cargo.packages().find_map(|pkg| { } => cargo.packages().find_map(|pkg| {
let has_target_with_root = cargo[pkg] let has_target_with_root = cargo[pkg]

View file

@ -767,7 +767,8 @@ pub(crate) fn handle_parent_module(
.workspaces .workspaces
.iter() .iter()
.filter_map(|ws| match &ws.kind { .filter_map(|ws| match &ws.kind {
ProjectWorkspaceKind::Cargo { cargo, .. } => { ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
cargo.parent_manifests(&manifest_path) cargo.parent_manifests(&manifest_path)
} }
_ => None, _ => None,
@ -1759,7 +1760,7 @@ pub(crate) fn handle_open_docs(
let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind { let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
ProjectWorkspaceKind::Cargo { cargo, .. } ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspaceKind::DetachedFile { cargo_script: Some((cargo, _)), .. } => { | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
Some((cargo, ws.sysroot.as_ref().ok())) Some((cargo, ws.sysroot.as_ref().ok()))
} }
ProjectWorkspaceKind::Json { .. } => None, ProjectWorkspaceKind::Json { .. } => None,

View file

@ -502,7 +502,7 @@ impl GlobalState {
let env = match &ws.kind { let env = match &ws.kind {
ProjectWorkspaceKind::Cargo { cargo_config_extra_env, .. } ProjectWorkspaceKind::Cargo { cargo_config_extra_env, .. }
| ProjectWorkspaceKind::DetachedFile { | ProjectWorkspaceKind::DetachedFile {
cargo_script: Some(_), cargo: Some(_),
cargo_config_extra_env, cargo_config_extra_env,
.. ..
} => cargo_config_extra_env } => cargo_config_extra_env
@ -669,36 +669,37 @@ impl GlobalState {
config, config,
None, None,
self.config.root_path().clone(), self.config.root_path().clone(),
None,
)], )],
flycheck::InvocationStrategy::PerWorkspace => { flycheck::InvocationStrategy::PerWorkspace => {
self.workspaces self.workspaces
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(id, ws)| match &ws.kind { .filter_map(|(id, ws)| {
ProjectWorkspaceKind::Cargo { cargo, .. } => Some(( Some((
id, 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()), 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(); let sender = sender.clone();
FlycheckHandle::spawn( FlycheckHandle::spawn(
id, id,
@ -706,6 +707,7 @@ impl GlobalState {
config.clone(), config.clone(),
sysroot_root, sysroot_root,
root.to_path_buf(), root.to_path_buf(),
manifest_path.map(|it| it.to_path_buf()),
) )
}) })
.collect() .collect()