flush writes on force quit (#4397)

When force quitting, we need to block on the pending writes to ensure
that write commands succeed before exiting, and also to avoid a crash
when all the views are gone before the auto format call returns from
the LS.
pull/4299/head
Skyler Hawthorne 2 years ago committed by GitHub
parent 74a6a2282e
commit f486f34ebe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -51,6 +51,7 @@ fn force_quit(
ensure!(args.is_empty(), ":quit! takes no arguments"); ensure!(args.is_empty(), ":quit! takes no arguments");
cx.block_try_flush_writes()?;
cx.editor.close(view!(cx.editor).id); cx.editor.close(view!(cx.editor).id);
Ok(()) Ok(())

@ -11,7 +11,7 @@ mod test {
use self::helpers::*; use self::helpers::*;
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn hello_world() -> anyhow::Result<()> { async fn hello_world() -> anyhow::Result<()> {
test(("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#")).await?; test(("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#")).await?;
Ok(()) Ok(())

@ -1,6 +1,6 @@
use super::*; use super::*;
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn auto_indent_c() -> anyhow::Result<()> { async fn auto_indent_c() -> anyhow::Result<()> {
test_with_config( test_with_config(
Args { Args {

@ -12,7 +12,7 @@ fn matching_pairs() -> impl Iterator<Item = &'static (char, char)> {
DEFAULT_PAIRS.iter().filter(|(open, close)| open == close) DEFAULT_PAIRS.iter().filter(|(open, close)| open == close)
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_basic() -> anyhow::Result<()> { async fn insert_basic() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -26,7 +26,7 @@ async fn insert_basic() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_configured_multi_byte_chars() -> anyhow::Result<()> { async fn insert_configured_multi_byte_chars() -> anyhow::Result<()> {
// NOTE: these are multi-byte Unicode characters // NOTE: these are multi-byte Unicode characters
let pairs = hashmap!('„' => '“', '' => '', '「' => '」'); let pairs = hashmap!('„' => '“', '' => '', '「' => '」');
@ -68,7 +68,7 @@ async fn insert_configured_multi_byte_chars() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_after_word() -> anyhow::Result<()> { async fn insert_after_word() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -91,7 +91,7 @@ async fn insert_after_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_before_word() -> anyhow::Result<()> { async fn insert_before_word() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -105,7 +105,7 @@ async fn insert_before_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_before_word_selection() -> anyhow::Result<()> { async fn insert_before_word_selection() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -119,7 +119,7 @@ async fn insert_before_word_selection() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_before_word_selection_trailing_word() -> anyhow::Result<()> { async fn insert_before_word_selection_trailing_word() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -133,7 +133,7 @@ async fn insert_before_word_selection_trailing_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_closer_selection_trailing_word() -> anyhow::Result<()> { async fn insert_closer_selection_trailing_word() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -147,7 +147,7 @@ async fn insert_closer_selection_trailing_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_before_eol() -> anyhow::Result<()> { async fn insert_before_eol() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -166,7 +166,7 @@ async fn insert_before_eol() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_auto_pairs_disabled() -> anyhow::Result<()> { async fn insert_auto_pairs_disabled() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test_with_config( test_with_config(
@ -191,7 +191,7 @@ async fn insert_auto_pairs_disabled() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_multi_range() -> anyhow::Result<()> { async fn insert_multi_range() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -210,7 +210,7 @@ async fn insert_multi_range() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_before_multi_code_point_graphemes() -> anyhow::Result<()> { async fn insert_before_multi_code_point_graphemes() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -223,7 +223,7 @@ async fn insert_before_multi_code_point_graphemes() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_at_end_of_document() -> anyhow::Result<()> { async fn insert_at_end_of_document() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(TestCase { test(TestCase {
@ -248,7 +248,7 @@ async fn insert_at_end_of_document() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_close_inside_pair() -> anyhow::Result<()> { async fn insert_close_inside_pair() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -272,7 +272,7 @@ async fn insert_close_inside_pair() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_close_inside_pair_multi() -> anyhow::Result<()> { async fn insert_close_inside_pair_multi() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -296,7 +296,7 @@ async fn insert_close_inside_pair_multi() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_nested_open_inside_pair() -> anyhow::Result<()> { async fn insert_nested_open_inside_pair() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -320,7 +320,7 @@ async fn insert_nested_open_inside_pair() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_nested_open_inside_pair_multi() -> anyhow::Result<()> { async fn insert_nested_open_inside_pair_multi() -> anyhow::Result<()> {
for outer_pair in DEFAULT_PAIRS { for outer_pair in DEFAULT_PAIRS {
for inner_pair in DEFAULT_PAIRS { for inner_pair in DEFAULT_PAIRS {
@ -352,7 +352,7 @@ async fn insert_nested_open_inside_pair_multi() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_basic() -> anyhow::Result<()> { async fn append_basic() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -371,7 +371,7 @@ async fn append_basic() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_multi_range() -> anyhow::Result<()> { async fn append_multi_range() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -390,7 +390,7 @@ async fn append_multi_range() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_close_inside_pair() -> anyhow::Result<()> { async fn append_close_inside_pair() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -414,7 +414,7 @@ async fn append_close_inside_pair() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_close_inside_pair_multi() -> anyhow::Result<()> { async fn append_close_inside_pair_multi() -> anyhow::Result<()> {
for pair in DEFAULT_PAIRS { for pair in DEFAULT_PAIRS {
test(( test((
@ -438,7 +438,7 @@ async fn append_close_inside_pair_multi() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_end_of_word() -> anyhow::Result<()> { async fn append_end_of_word() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -457,7 +457,7 @@ async fn append_end_of_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_middle_of_word() -> anyhow::Result<()> { async fn append_middle_of_word() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -471,7 +471,7 @@ async fn append_middle_of_word() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_end_of_word_multi() -> anyhow::Result<()> { async fn append_end_of_word_multi() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -490,7 +490,7 @@ async fn append_end_of_word_multi() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_inside_nested_pair() -> anyhow::Result<()> { async fn append_inside_nested_pair() -> anyhow::Result<()> {
for pair in differing_pairs() { for pair in differing_pairs() {
test(( test((
@ -514,7 +514,7 @@ async fn append_inside_nested_pair() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn append_inside_nested_pair_multi() -> anyhow::Result<()> { async fn append_inside_nested_pair_multi() -> anyhow::Result<()> {
for outer_pair in DEFAULT_PAIRS { for outer_pair in DEFAULT_PAIRS {
for inner_pair in DEFAULT_PAIRS { for inner_pair in DEFAULT_PAIRS {

@ -94,7 +94,7 @@ async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_selection_duplication() -> anyhow::Result<()> { async fn test_selection_duplication() -> anyhow::Result<()> {
// Forward // Forward
test(( test((

@ -1,6 +1,6 @@
use super::*; use super::*;
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_mode_cursor_position() -> anyhow::Result<()> { async fn insert_mode_cursor_position() -> anyhow::Result<()> {
test(TestCase { test(TestCase {
in_text: String::new(), in_text: String::new(),
@ -19,7 +19,7 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> {
} }
/// Range direction is preserved when escaping insert mode to normal /// Range direction is preserved when escaping insert mode to normal
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
test(("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n")).await?; test(("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n")).await?;
test(( test((
@ -66,7 +66,7 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
/// Ensure the very initial cursor in an opened file is the width of /// Ensure the very initial cursor in an opened file is the width of
/// the first grapheme /// the first grapheme
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn cursor_position_newly_opened_file() -> anyhow::Result<()> { async fn cursor_position_newly_opened_file() -> anyhow::Result<()> {
let test = |content: &str, expected_sel: Selection| -> anyhow::Result<()> { let test = |content: &str, expected_sel: Selection| -> anyhow::Result<()> {
let file = helpers::temp_file_with_contents(content)?; let file = helpers::temp_file_with_contents(content)?;
@ -88,7 +88,7 @@ async fn cursor_position_newly_opened_file() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn cursor_position_append_eof() -> anyhow::Result<()> { async fn cursor_position_append_eof() -> anyhow::Result<()> {
// Selection is fowards // Selection is fowards
test(( test((
@ -109,7 +109,7 @@ async fn cursor_position_append_eof() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn select_mode_tree_sitter_next_function_is_union_of_objects() -> anyhow::Result<()> { async fn select_mode_tree_sitter_next_function_is_union_of_objects() -> anyhow::Result<()> {
test_with_config( test_with_config(
Args { Args {
@ -141,7 +141,7 @@ async fn select_mode_tree_sitter_next_function_is_union_of_objects() -> anyhow::
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn select_mode_tree_sitter_prev_function_unselects_object() -> anyhow::Result<()> { async fn select_mode_tree_sitter_prev_function_unselects_object() -> anyhow::Result<()> {
test_with_config( test_with_config(
Args { Args {
@ -173,7 +173,7 @@ async fn select_mode_tree_sitter_prev_function_unselects_object() -> anyhow::Res
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn select_mode_tree_sitter_prev_function_goes_backwards_to_object() -> anyhow::Result<()> { async fn select_mode_tree_sitter_prev_function_goes_backwards_to_object() -> anyhow::Result<()> {
// Note: the anchor stays put and the head moves back. // Note: the anchor stays put and the head moves back.
test_with_config( test_with_config(

@ -1,6 +1,6 @@
use super::*; use super::*;
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_history_completion() -> anyhow::Result<()> { async fn test_history_completion() -> anyhow::Result<()> {
test_key_sequence( test_key_sequence(
&mut AppBuilder::new().build()?, &mut AppBuilder::new().build()?,

@ -8,7 +8,7 @@ use helix_view::doc;
use super::*; use super::*;
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write() -> anyhow::Result<()> { async fn test_write() -> anyhow::Result<()> {
let mut file = tempfile::NamedTempFile::new()?; let mut file = tempfile::NamedTempFile::new()?;
let mut app = helpers::AppBuilder::new() let mut app = helpers::AppBuilder::new()
@ -92,7 +92,7 @@ async fn test_write_concurrent() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_fail_mod_flag() -> anyhow::Result<()> { async fn test_write_fail_mod_flag() -> anyhow::Result<()> {
let file = helpers::new_readonly_tempfile()?; let file = helpers::new_readonly_tempfile()?;
let mut app = helpers::AppBuilder::new() let mut app = helpers::AppBuilder::new()
@ -133,7 +133,7 @@ async fn test_write_fail_mod_flag() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_scratch_to_new_path() -> anyhow::Result<()> { async fn test_write_scratch_to_new_path() -> anyhow::Result<()> {
let mut file = tempfile::NamedTempFile::new()?; let mut file = tempfile::NamedTempFile::new()?;
@ -158,7 +158,7 @@ async fn test_write_scratch_to_new_path() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_scratch_no_path_fails() -> anyhow::Result<()> { async fn test_write_scratch_no_path_fails() -> anyhow::Result<()> {
helpers::test_key_sequence_with_input_text( helpers::test_key_sequence_with_input_text(
None, None,
@ -179,7 +179,7 @@ async fn test_write_scratch_no_path_fails() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_auto_format_fails_still_writes() -> anyhow::Result<()> { async fn test_write_auto_format_fails_still_writes() -> anyhow::Result<()> {
let mut file = tempfile::Builder::new().suffix(".rs").tempfile()?; let mut file = tempfile::Builder::new().suffix(".rs").tempfile()?;
@ -203,7 +203,7 @@ async fn test_write_auto_format_fails_still_writes() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_new_path() -> anyhow::Result<()> { async fn test_write_new_path() -> anyhow::Result<()> {
let mut file1 = tempfile::NamedTempFile::new().unwrap(); let mut file1 = tempfile::NamedTempFile::new().unwrap();
let mut file2 = tempfile::NamedTempFile::new().unwrap(); let mut file2 = tempfile::NamedTempFile::new().unwrap();
@ -249,7 +249,7 @@ async fn test_write_new_path() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test] #[tokio::test(flavor = "multi_thread")]
async fn test_write_fail_new_path() -> anyhow::Result<()> { async fn test_write_fail_new_path() -> anyhow::Result<()> {
let file = helpers::new_readonly_tempfile()?; let file = helpers::new_readonly_tempfile()?;

Loading…
Cancel
Save