Properly determine default prettier plugins to install

This commit is contained in:
Kirill Bulatov 2023-11-28 22:16:16 +02:00
parent 64259e4a0b
commit acd1aec862

View File

@ -87,6 +87,7 @@ pub enum PrettierInstallation {
NotInstalled { NotInstalled {
attempts: usize, attempts: usize,
installation_task: Option<Shared<Task<Result<(), Arc<anyhow::Error>>>>>, installation_task: Option<Shared<Task<Result<(), Arc<anyhow::Error>>>>>,
not_installed_plugins: HashSet<&'static str>,
}, },
Installed(PrettierInstance), Installed(PrettierInstance),
} }
@ -105,6 +106,7 @@ impl Default for DefaultPrettier {
prettier: PrettierInstallation::NotInstalled { prettier: PrettierInstallation::NotInstalled {
attempts: 0, attempts: 0,
installation_task: None, installation_task: None,
not_installed_plugins: HashSet::default(),
}, },
installed_plugins: HashSet::default(), installed_plugins: HashSet::default(),
} }
@ -212,6 +214,7 @@ fn start_default_prettier(
if let PrettierInstallation::NotInstalled { if let PrettierInstallation::NotInstalled {
installation_task, installation_task,
attempts, attempts,
..
} = &mut project.default_prettier.prettier } = &mut project.default_prettier.prettier
{ {
*installation_task = None; *installation_task = None;
@ -571,24 +574,23 @@ impl Project {
} }
} }
// TODO kb uncomment #[cfg(any(test, feature = "test-support"))]
// #[cfg(any(test, feature = "test-support"))] pub fn install_default_prettier(
// pub fn install_default_prettier( &mut self,
// &mut self, _worktree: Option<WorktreeId>,
// _worktree: Option<WorktreeId>, _new_language: &Language,
// _new_language: &Language, language_settings: &LanguageSettings,
// language_settings: &LanguageSettings, _cx: &mut ModelContext<Self>,
// _cx: &mut ModelContext<Self>, ) {
// ) { // suppress unused code warnings
// // suppress unused code warnings match &language_settings.formatter {
// match &language_settings.formatter { Formatter::Prettier { .. } | Formatter::Auto => {}
// Formatter::Prettier { .. } | Formatter::Auto => {} Formatter::LanguageServer | Formatter::External { .. } => return,
// Formatter::LanguageServer | Formatter::External { .. } => return, };
// }; let _ = &self.default_prettier.installed_plugins;
// let _ = &self.default_prettier.installed_plugins; }
// }
// #[cfg(not(any(test, feature = "test-support")))] #[cfg(not(any(test, feature = "test-support")))]
pub fn install_default_prettier( pub fn install_default_prettier(
&mut self, &mut self,
worktree: Option<WorktreeId>, worktree: Option<WorktreeId>,
@ -637,25 +639,28 @@ impl Project {
} }
None => Task::ready(Ok(ControlFlow::Break(()))), None => Task::ready(Ok(ControlFlow::Break(()))),
}; };
let mut plugins_to_install = prettier_plugins; let mut new_plugins = prettier_plugins;
plugins_to_install new_plugins
.retain(|plugin| !self.default_prettier.installed_plugins.contains(plugin)); .retain(|plugin| !self.default_prettier.installed_plugins.contains(plugin));
let mut installation_attempts = 0; let mut installation_attempt = 0;
let previous_installation_task = match &self.default_prettier.prettier { let previous_installation_task = match &self.default_prettier.prettier {
PrettierInstallation::NotInstalled { PrettierInstallation::NotInstalled {
installation_task, installation_task,
attempts, attempts,
not_installed_plugins
} => { } => {
installation_attempts = *attempts; installation_attempt = *attempts;
new_plugins.extend(not_installed_plugins.iter());
installation_task.clone() installation_task.clone()
} }
PrettierInstallation::Installed { .. } => { PrettierInstallation::Installed { .. } => {
if plugins_to_install.is_empty() { if new_plugins.is_empty() {
return; return;
} }
None None
} }
}; };
let plugins_to_install = new_plugins.clone();
let fs = Arc::clone(&self.fs); let fs = Arc::clone(&self.fs);
let new_installation_task = cx let new_installation_task = cx
.spawn(|project, mut cx| async move { .spawn(|project, mut cx| async move {
@ -665,51 +670,48 @@ impl Project {
.map_err(Arc::new)? .map_err(Arc::new)?
{ {
ControlFlow::Break(()) => return Ok(()), ControlFlow::Break(()) => return Ok(()),
ControlFlow::Continue(_) => { ControlFlow::Continue(prettier_path) => {
let mut needs_install = match previous_installation_task { if prettier_path.is_some() {
Some(previous_installation_task) => { new_plugins.clear();
match previous_installation_task.await { }
Ok(()) => false, let mut needs_install = false;
Err(e) => { if let Some(previous_installation_task) = previous_installation_task {
project.update(&mut cx, |project, _| { if let Err(e) = previous_installation_task.await {
if let PrettierInstallation::NotInstalled { log::error!("Failed to install default prettier (attempt {installation_attempt}): {e:#}");
attempts, project.update(&mut cx, |project, _| {
.. if let PrettierInstallation::NotInstalled { attempts, not_installed_plugins, .. } = &mut project.default_prettier.prettier {
} = &mut project.default_prettier.prettier *attempts += 1;
{ new_plugins.extend(not_installed_plugins.iter());
*attempts += 1; installation_attempt = *attempts;
installation_attempts = *attempts; needs_install = true;
} else {
installation_attempts += 1;
}
});
log::error!("Failed to install default prettier: {e:#}");
true
} }
} })
} }
None => true,
}; };
if installation_attempt > prettier::LAUNCH_THRESHOLD {
if installation_attempts > prettier::LAUNCH_THRESHOLD {
log::warn!( log::warn!(
"Default prettier installation has failed {installation_attempts} times, not attempting again", "Default prettier installation has failed {installation_attempt} times, not attempting again",
); );
return Ok(()); return Ok(());
} }
project.update(&mut cx, |project, _| { project.update(&mut cx, |project, _| {
plugins_to_install.retain(|plugin| { new_plugins.retain(|plugin| {
!project.default_prettier.installed_plugins.contains(plugin) !project.default_prettier.installed_plugins.contains(plugin)
}); });
needs_install |= !plugins_to_install.is_empty(); if let PrettierInstallation::NotInstalled { not_installed_plugins, .. } = &mut project.default_prettier.prettier {
not_installed_plugins.retain(|plugin| {
!project.default_prettier.installed_plugins.contains(plugin)
});
not_installed_plugins.extend(new_plugins.iter());
}
needs_install |= !new_plugins.is_empty();
}); });
if needs_install { if needs_install {
let installed_plugins = plugins_to_install.clone(); let installed_plugins = new_plugins.clone();
cx.background() cx.background()
.spawn(async move { .spawn(async move {
save_prettier_server_file(fs.as_ref()).await?; save_prettier_server_file(fs.as_ref()).await?;
install_prettier_packages(plugins_to_install, node).await install_prettier_packages(new_plugins, node).await
}) })
.await .await
.context("prettier & plugins install") .context("prettier & plugins install")
@ -731,8 +733,9 @@ impl Project {
}) })
.shared(); .shared();
self.default_prettier.prettier = PrettierInstallation::NotInstalled { self.default_prettier.prettier = PrettierInstallation::NotInstalled {
attempts: installation_attempts, attempts: installation_attempt,
installation_task: Some(new_installation_task), installation_task: Some(new_installation_task),
not_installed_plugins: plugins_to_install,
}; };
} }
} }