Fix bug where prior LSP completions can be displayed after trigger char (#32927)

Bug in #31872

Closes #32774

Release Notes:

- Fixed a bug in LSP completions caching where prior completions may be
used when they should not, after typing a trigger char like `.`
This commit is contained in:
Michael Sloan 2025-06-18 03:01:47 -06:00 committed by GitHub
parent 70aab39e4f
commit d8eb341f9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5266,6 +5266,37 @@ impl Editor {
.as_ref()
.map_or(true, |provider| provider.filter_completions());
let trigger_kind = match trigger {
Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
CompletionTriggerKind::TRIGGER_CHARACTER
}
_ => CompletionTriggerKind::INVOKED,
};
let completion_context = CompletionContext {
trigger_character: trigger.and_then(|trigger| {
if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
Some(String::from(trigger))
} else {
None
}
}),
trigger_kind,
};
// Hide the current completions menu when a trigger char is typed. Without this, cached
// completions from before the trigger char may be reused (#32774). Snippet choices could
// involve trigger chars, so this is skipped in that case.
if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER && self.snippet_stack.is_empty()
{
let menu_is_open = matches!(
self.context_menu.borrow().as_ref(),
Some(CodeContextMenu::Completions(_))
);
if menu_is_open {
self.hide_context_menu(window, cx);
}
}
if let Some(CodeContextMenu::Completions(menu)) = self.context_menu.borrow_mut().as_mut() {
if filter_completions {
menu.filter(query.clone(), provider.clone(), window, cx);
@ -5296,23 +5327,6 @@ impl Editor {
}
};
let trigger_kind = match trigger {
Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
CompletionTriggerKind::TRIGGER_CHARACTER
}
_ => CompletionTriggerKind::INVOKED,
};
let completion_context = CompletionContext {
trigger_character: trigger.and_then(|trigger| {
if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
Some(String::from(trigger))
} else {
None
}
}),
trigger_kind,
};
let (word_replace_range, word_to_exclude) = if let (word_range, Some(CharKind::Word)) =
buffer_snapshot.surrounding_word(buffer_position)
{