flycheck: notifications show full command when configured in a rust-project.json runnable

For JSON / override users, pretty-print the custom flycheck command with fewer quote characters

Better debug logging in flycheck
This commit is contained in:
Cormac Relf 2024-09-04 13:52:59 +10:00
parent 778de45547
commit 53a371c505
4 changed files with 62 additions and 20 deletions

View file

@ -309,13 +309,18 @@ impl fmt::Debug for FlycheckMessage {
#[derive(Debug)]
pub(crate) enum Progress {
DidStart,
DidStart {
/// The user sees this in VSCode, etc. May be a shortened version of the command we actually
/// executed, otherwise it is way too long.
user_facing_command: String,
},
DidCheckCrate(String),
DidFinish(io::Result<()>),
DidCancel,
DidFailToRestart(String),
}
#[derive(Debug, Clone)]
enum FlycheckScope {
Workspace,
Package {
@ -346,6 +351,16 @@ impl PackageSpecifier {
}
}
#[derive(Debug)]
enum FlycheckCommandOrigin {
/// Regular cargo invocation
Cargo,
/// Configured via check_overrideCommand
CheckOverrideCommand,
/// From a runnable with [project_json::RunnableKind::Flycheck]
ProjectJsonRunnable,
}
enum StateChange {
Restart {
generation: DiagnosticsGeneration,
@ -529,16 +544,28 @@ impl FlycheckActor {
}
let command = self.check_command(&scope, saved_file.as_deref(), target);
self.scope = scope;
self.scope = scope.clone();
self.generation = generation;
let Some(command) = command else {
let Some((command, origin)) = command else {
tracing::debug!(?scope, "failed to build flycheck command");
continue;
};
let formatted_command = format!("{command:?}");
let debug_command = format!("{command:?}");
let user_facing_command = match origin {
// Don't show all the --format=json-with-blah-blah args, just the simple
// version
FlycheckCommandOrigin::Cargo => self.config.to_string(),
// show them the full command but pretty printed. advanced user
FlycheckCommandOrigin::ProjectJsonRunnable
| FlycheckCommandOrigin::CheckOverrideCommand => display_command(
&command,
Some(std::path::Path::new(self.root.as_path())),
),
};
tracing::debug!(?command, "will restart flycheck");
tracing::debug!(?origin, ?command, "will restart flycheck");
let (sender, receiver) = unbounded();
match CommandHandle::spawn(
command,
@ -575,14 +602,14 @@ impl FlycheckActor {
},
) {
Ok(command_handle) => {
tracing::debug!(command = formatted_command, "did restart flycheck");
tracing::debug!(?origin, command = %debug_command, "did restart flycheck");
self.command_handle = Some(command_handle);
self.command_receiver = Some(receiver);
self.report_progress(Progress::DidStart);
self.report_progress(Progress::DidStart { user_facing_command });
}
Err(error) => {
self.report_progress(Progress::DidFailToRestart(format!(
"Failed to run the following command: {formatted_command} error={error}"
"Failed to run the following command: {debug_command} origin={origin:?} error={error}"
)));
}
}
@ -789,7 +816,7 @@ impl FlycheckActor {
scope: &FlycheckScope,
saved_file: Option<&AbsPath>,
target: Option<Target>,
) -> Option<Command> {
) -> Option<(Command, FlycheckCommandOrigin)> {
match &self.config {
FlycheckConfig::CargoCommand { command, options, ansi_color_output } => {
// Only use the rust-project.json's flycheck config when no check_overrideCommand
@ -803,7 +830,8 @@ impl FlycheckActor {
// Completely handle according to rust-project.json.
// We don't consider this to be "using cargo" so we will not apply any of the
// CargoOptions to the command.
return self.explicit_check_command(scope, saved_file);
let cmd = self.explicit_check_command(scope, saved_file)?;
return Some((cmd, FlycheckCommandOrigin::ProjectJsonRunnable));
}
let mut cmd =
@ -864,7 +892,7 @@ impl FlycheckActor {
self.ws_target_dir.as_ref().map(Utf8PathBuf::as_path),
);
cmd.args(&options.extra_args);
Some(cmd)
Some((cmd, FlycheckCommandOrigin::Cargo))
}
FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy } => {
let root = match invocation_strategy {
@ -892,7 +920,7 @@ impl FlycheckActor {
let subs = Substitutions { label, saved_file: saved_file.map(|x| x.as_str()) };
let cmd = subs.substitute(&runnable, extra_env)?;
Some(cmd)
Some((cmd, FlycheckCommandOrigin::CheckOverrideCommand))
}
}
}

View file

@ -112,6 +112,7 @@ pub(crate) struct GlobalState {
pub(crate) flycheck_sender: Sender<FlycheckMessage>,
pub(crate) flycheck_receiver: Receiver<FlycheckMessage>,
pub(crate) last_flycheck_error: Option<String>,
pub(crate) flycheck_formatted_commands: Vec<String>,
// Test explorer
pub(crate) test_run_session: Option<Vec<CargoTestHandle>>,
@ -288,6 +289,7 @@ impl GlobalState {
flycheck_sender,
flycheck_receiver,
last_flycheck_error: None,
flycheck_formatted_commands: vec![],
test_run_session: None,
test_run_sender,

View file

@ -1179,8 +1179,24 @@ impl GlobalState {
kind: ClearDiagnosticsKind::OlderThan(generation, ClearScope::Package(package_id)),
} => self.diagnostics.clear_check_older_than_for_package(id, package_id, generation),
FlycheckMessage::Progress { id, progress } => {
let format_with_id = |user_facing_command: String| {
if self.flycheck.len() == 1 {
user_facing_command
} else {
format!("{user_facing_command} (#{})", id + 1)
}
};
self.flycheck_formatted_commands
.resize_with(self.flycheck.len().max(id + 1), || {
format_with_id(self.config.flycheck(None).to_string())
});
let (state, message) = match progress {
flycheck::Progress::DidStart => (Progress::Begin, None),
flycheck::Progress::DidStart { user_facing_command } => {
self.flycheck_formatted_commands[id] = format_with_id(user_facing_command);
(Progress::Begin, None)
}
flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
flycheck::Progress::DidCancel => {
self.last_flycheck_error = None;
@ -1200,13 +1216,8 @@ impl GlobalState {
}
};
// When we're running multiple flychecks, we have to include a disambiguator in
// the title, or the editor complains. Note that this is a user-facing string.
let title = if self.flycheck.len() == 1 {
format!("{}", self.config.flycheck(None))
} else {
format!("{} (#{})", self.config.flycheck(None), id + 1)
};
// Clone because we &mut self for report_progress
let title = self.flycheck_formatted_commands[id].clone();
self.report_progress(
&title,
state,

View file

@ -942,6 +942,7 @@ impl GlobalState {
}
}
.into();
self.flycheck_formatted_commands = vec![];
}
}