on master help sign in
discard stale completion requests
8cb7cdfPascal Kuthe
helix-term/src/commands.rs+29−2
@@ -5,6 +5,7 @@ pub(crate) mod typed;
5pub use dap::*;
5pub use dap::*;
6use helix_vcs::Hunk;
6use helix_vcs::Hunk;
7pub use lsp::*;
7pub use lsp::*;
8+use tokio::sync::oneshot;
8use tui::widgets::Row;
9use tui::widgets::Row;
9pub use typed::*;
10pub use typed::*;
10
11
@@ -4171,6 +4172,24 @@ pub fn completion(cx: &mut Context) {
4171 None => return,
4172 None => return,
4172 };
4173 };
4173
4174
4175+ // setup a chanel that allows the request to be canceled
4176+ let (tx, rx) = oneshot::channel();
4177+ // set completion_request so that this request can be canceled
4178+ // by setting completion_request, the old channel stored there is dropped
4179+ // and the associated request is automatically dropped
4180+ cx.editor.completion_request_handle = Some(tx);
4181+ let future = async move {
4182+ tokio::select! {
4183+ biased;
4184+ _ = rx => {
4185+ Ok(serde_json::Value::Null)
4186+ }
4187+ res = future => {
4188+ res
4189+ }
4190+ }
4191+ };
4192+
4174 let trigger_offset = cursor;
4193 let trigger_offset = cursor;
4175
4194
4176 // TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
4195 // TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
@@ -4183,11 +4202,19 @@ pub fn completion(cx: &mut Context) {
4183 let start_offset = cursor.saturating_sub(offset);
4202 let start_offset = cursor.saturating_sub(offset);
4184 let savepoint = doc.savepoint(view);
4203 let savepoint = doc.savepoint(view);
4185
4204
4205+ let trigger_doc = doc.id();
4206+ let trigger_view = view.id;
4207+
4186 cx.callback(
4208 cx.callback(
4187 future,
4209 future,
4188 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
4210 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
4211+ let (view, doc) = current_ref!(editor);
4212+ // check if the completion request is stale.
4213+ //
4214+ // Completions are completed asynchrounsly and therefore the user could
4215+ //switch document/view or leave insert mode. In all of thoise cases the
4216+ // completion should be discarded
4189− if editor.mode != Mode::Insert {
4217+ if editor.mode != Mode::Insert || view.id != trigger_view || doc.id() != trigger_doc {
4190− // we're not in insert mode anymore
4191 return;
4218 return;
4192 }
4219 }
4193
4220
helix-term/src/ui/editor.rs+1
@@ -820,6 +820,7 @@ impl EditorView {
820 (Mode::Insert, Mode::Normal) => {
820 (Mode::Insert, Mode::Normal) => {
821 // if exiting insert mode, remove completion
821 // if exiting insert mode, remove completion
822 self.completion = None;
822 self.completion = None;
823+ cxt.editor.completion_request_handle = None;
823
824
824 // TODO: Use an on_mode_change hook to remove signature help
825 // TODO: Use an on_mode_change hook to remove signature help
825 cxt.jobs.callback(async {
826 cxt.jobs.callback(async {
helix-view/src/editor.rs+10−1
@@ -31,7 +31,7 @@ use std::{
31use tokio::{
31use tokio::{
32 sync::{
32 sync::{
33 mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
33 mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
34− Notify, RwLock,
34+ oneshot, Notify, RwLock,
35 },
35 },
36 time::{sleep, Duration, Instant, Sleep},
36 time::{sleep, Duration, Instant, Sleep},
37};
37};
@@ -852,6 +852,14 @@ pub struct Editor {
852 /// avoid calculating the cursor position multiple
852 /// avoid calculating the cursor position multiple
853 /// times during rendering and should not be set by other functions.
853 /// times during rendering and should not be set by other functions.
854 pub cursor_cache: Cell<Option<Option<Position>>>,
854 pub cursor_cache: Cell<Option<Option<Position>>>,
855+ /// When a new completion request is sent to the server old
856+ /// unifinished request must be dropped. Each completion
857+ /// request is associated with a channel that cancels
858+ /// when the channel is dropped. That channel is stored
859+ /// here. When a new completion request is sent this
860+ /// field is set and any old requests are automatically
861+ /// canceled as a result
862+ pub completion_request_handle: Option<oneshot::Sender<()>>,
855}
863}
856
864
857pub type RedrawHandle = (Arc<Notify>, Arc<RwLock<()>>);
865pub type RedrawHandle = (Arc<Notify>, Arc<RwLock<()>>);
@@ -950,6 +958,7 @@ impl Editor {
950 redraw_handle: Default::default(),
958 redraw_handle: Default::default(),
951 needs_redraw: false,
959 needs_redraw: false,
952 cursor_cache: Cell::new(None),
960 cursor_cache: Cell::new(None),
961+ completion_request_handle: None,
953 }
962 }
954 }
963 }
955
964