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:
parent
778de45547
commit
53a371c505
4 changed files with 62 additions and 20 deletions
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -942,6 +942,7 @@ impl GlobalState {
|
|||
}
|
||||
}
|
||||
.into();
|
||||
self.flycheck_formatted_commands = vec![];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue