Switch from Arc/RwLock to Rc/RefCell for CodeContextMenu (#22035)
`CodeContextMenu` is always accessed on one thread, so only `Rc`s and `Rc<RefCell<_>>` are needed. There should be tiny performance benefits from this. The main benefit of this is that when seeing code accessing a `RwLock` it would be reasonable to wonder whether it will block. The only potential downside is the potential for panics due to overlapping borrows of the RefCells. I think this is an acceptable risk because most errors of this nature will be local or will be caught by clippy via the check for holding a RefCell reference over an `await`. Release Notes: - N/A
This commit is contained in:
parent
7b721efe2c
commit
a94afbc062
12 changed files with 108 additions and 93 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2768,7 +2768,6 @@ dependencies = [
|
||||||
"language",
|
"language",
|
||||||
"menu",
|
"menu",
|
||||||
"notifications",
|
"notifications",
|
||||||
"parking_lot",
|
|
||||||
"picker",
|
"picker",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"project",
|
"project",
|
||||||
|
|
|
@ -47,6 +47,7 @@ use std::{
|
||||||
iter, mem,
|
iter, mem,
|
||||||
ops::{Range, RangeInclusive},
|
ops::{Range, RangeInclusive},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
task::{self, Poll},
|
task::{self, Poll},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -174,7 +175,7 @@ impl InlineAssistant {
|
||||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
if let Some(editor) = item.act_as::<Editor>(cx) {
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
editor.push_code_action_provider(
|
editor.push_code_action_provider(
|
||||||
Arc::new(AssistantCodeActionProvider {
|
Rc::new(AssistantCodeActionProvider {
|
||||||
editor: cx.view().downgrade(),
|
editor: cx.view().downgrade(),
|
||||||
workspace: workspace.downgrade(),
|
workspace: workspace.downgrade(),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -7,11 +7,13 @@ use editor::{CompletionProvider, Editor};
|
||||||
use fuzzy::{match_strings, StringMatchCandidate};
|
use fuzzy::{match_strings, StringMatchCandidate};
|
||||||
use gpui::{AppContext, Model, Task, ViewContext, WeakView, WindowContext};
|
use gpui::{AppContext, Model, Task, ViewContext, WeakView, WindowContext};
|
||||||
use language::{Anchor, Buffer, CodeLabel, Documentation, HighlightId, LanguageServerId, ToPoint};
|
use language::{Anchor, Buffer, CodeLabel, Documentation, HighlightId, LanguageServerId, ToPoint};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::Mutex;
|
||||||
use project::CompletionIntent;
|
use project::CompletionIntent;
|
||||||
use rope::Point;
|
use rope::Point;
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
|
rc::Rc,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering::SeqCst},
|
atomic::{AtomicBool, Ordering::SeqCst},
|
||||||
Arc,
|
Arc,
|
||||||
|
@ -322,7 +324,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
|
||||||
&self,
|
&self,
|
||||||
_: Model<Buffer>,
|
_: Model<Buffer>,
|
||||||
_: Vec<usize>,
|
_: Vec<usize>,
|
||||||
_: Arc<RwLock<Box<[project::Completion]>>>,
|
_: Rc<RefCell<Box<[project::Completion]>>>,
|
||||||
_: &mut ViewContext<Editor>,
|
_: &mut ViewContext<Editor>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
Task::ready(Ok(true))
|
Task::ready(Ok(true))
|
||||||
|
|
|
@ -45,6 +45,7 @@ use std::{
|
||||||
iter, mem,
|
iter, mem,
|
||||||
ops::{Range, RangeInclusive},
|
ops::{Range, RangeInclusive},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
task::{self, Poll},
|
task::{self, Poll},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
|
@ -178,7 +179,7 @@ impl InlineAssistant {
|
||||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
if let Some(editor) = item.act_as::<Editor>(cx) {
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
editor.push_code_action_provider(
|
editor.push_code_action_provider(
|
||||||
Arc::new(AssistantCodeActionProvider {
|
Rc::new(AssistantCodeActionProvider {
|
||||||
editor: cx.view().downgrade(),
|
editor: cx.view().downgrade(),
|
||||||
workspace: workspace.downgrade(),
|
workspace: workspace.downgrade(),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -44,7 +44,6 @@ gpui.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
menu.workspace = true
|
menu.workspace = true
|
||||||
notifications.workspace = true
|
notifications.workspace = true
|
||||||
parking_lot.workspace = true
|
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
release_channel.workspace = true
|
release_channel.workspace = true
|
||||||
|
|
|
@ -12,10 +12,15 @@ use language::{
|
||||||
language_settings::SoftWrap, Anchor, Buffer, BufferSnapshot, CodeLabel, LanguageRegistry,
|
language_settings::SoftWrap, Anchor, Buffer, BufferSnapshot, CodeLabel, LanguageRegistry,
|
||||||
LanguageServerId, ToOffset,
|
LanguageServerId, ToOffset,
|
||||||
};
|
};
|
||||||
use parking_lot::RwLock;
|
|
||||||
use project::{search::SearchQuery, Completion};
|
use project::{search::SearchQuery, Completion};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::{ops::Range, sync::Arc, sync::LazyLock, time::Duration};
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
ops::Range,
|
||||||
|
rc::Rc,
|
||||||
|
sync::{Arc, LazyLock},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
use ui::{prelude::*, TextSize};
|
use ui::{prelude::*, TextSize};
|
||||||
|
|
||||||
|
@ -68,7 +73,7 @@ impl CompletionProvider for MessageEditorCompletionProvider {
|
||||||
&self,
|
&self,
|
||||||
_buffer: Model<Buffer>,
|
_buffer: Model<Buffer>,
|
||||||
_completion_indices: Vec<usize>,
|
_completion_indices: Vec<usize>,
|
||||||
_completions: Arc<RwLock<Box<[Completion]>>>,
|
_completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
_cx: &mut ViewContext<Editor>,
|
_cx: &mut ViewContext<Editor>,
|
||||||
) -> Task<anyhow::Result<bool>> {
|
) -> Task<anyhow::Result<bool>> {
|
||||||
Task::ready(Ok(false))
|
Task::ready(Ok(false))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{cell::Cell, cmp::Reverse, ops::Range, sync::Arc};
|
use std::cell::RefCell;
|
||||||
|
use std::{cell::Cell, cmp::Reverse, ops::Range, rc::Rc};
|
||||||
|
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
|
@ -11,7 +12,6 @@ use language::{CodeLabel, Documentation};
|
||||||
use lsp::LanguageServerId;
|
use lsp::LanguageServerId;
|
||||||
use multi_buffer::{Anchor, ExcerptId};
|
use multi_buffer::{Anchor, ExcerptId};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use parking_lot::RwLock;
|
|
||||||
use project::{CodeAction, Completion, TaskSourceKind};
|
use project::{CodeAction, Completion, TaskSourceKind};
|
||||||
use task::ResolvedTask;
|
use task::ResolvedTask;
|
||||||
use ui::{
|
use ui::{
|
||||||
|
@ -137,9 +137,9 @@ pub struct CompletionsMenu {
|
||||||
sort_completions: bool,
|
sort_completions: bool,
|
||||||
pub initial_position: Anchor,
|
pub initial_position: Anchor,
|
||||||
pub buffer: Model<Buffer>,
|
pub buffer: Model<Buffer>,
|
||||||
pub completions: Arc<RwLock<Box<[Completion]>>>,
|
pub completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
match_candidates: Arc<[StringMatchCandidate]>,
|
match_candidates: Rc<[StringMatchCandidate]>,
|
||||||
pub matches: Arc<[StringMatch]>,
|
pub matches: Rc<[StringMatch]>,
|
||||||
pub selected_item: usize,
|
pub selected_item: usize,
|
||||||
scroll_handle: UniformListScrollHandle,
|
scroll_handle: UniformListScrollHandle,
|
||||||
resolve_completions: bool,
|
resolve_completions: bool,
|
||||||
|
@ -169,7 +169,7 @@ impl CompletionsMenu {
|
||||||
initial_position,
|
initial_position,
|
||||||
buffer,
|
buffer,
|
||||||
show_completion_documentation,
|
show_completion_documentation,
|
||||||
completions: Arc::new(RwLock::new(completions)),
|
completions: RefCell::new(completions).into(),
|
||||||
match_candidates,
|
match_candidates,
|
||||||
matches: Vec::new().into(),
|
matches: Vec::new().into(),
|
||||||
selected_item: 0,
|
selected_item: 0,
|
||||||
|
@ -223,7 +223,7 @@ impl CompletionsMenu {
|
||||||
sort_completions,
|
sort_completions,
|
||||||
initial_position: selection.start,
|
initial_position: selection.start,
|
||||||
buffer,
|
buffer,
|
||||||
completions: Arc::new(RwLock::new(completions)),
|
completions: RefCell::new(completions).into(),
|
||||||
match_candidates,
|
match_candidates,
|
||||||
matches,
|
matches,
|
||||||
selected_item: 0,
|
selected_item: 0,
|
||||||
|
@ -329,13 +329,13 @@ impl CompletionsMenu {
|
||||||
workspace: Option<WeakView<Workspace>>,
|
workspace: Option<WeakView<Workspace>>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
|
let completions = self.completions.borrow_mut();
|
||||||
let show_completion_documentation = self.show_completion_documentation;
|
let show_completion_documentation = self.show_completion_documentation;
|
||||||
let widest_completion_ix = self
|
let widest_completion_ix = self
|
||||||
.matches
|
.matches
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.max_by_key(|(_, mat)| {
|
.max_by_key(|(_, mat)| {
|
||||||
let completions = self.completions.read();
|
|
||||||
let completion = &completions[mat.candidate_id];
|
let completion = &completions[mat.candidate_id];
|
||||||
let documentation = &completion.documentation;
|
let documentation = &completion.documentation;
|
||||||
|
|
||||||
|
@ -350,14 +350,12 @@ impl CompletionsMenu {
|
||||||
})
|
})
|
||||||
.map(|(ix, _)| ix);
|
.map(|(ix, _)| ix);
|
||||||
|
|
||||||
let completions = self.completions.clone();
|
|
||||||
let matches = self.matches.clone();
|
|
||||||
let selected_item = self.selected_item;
|
let selected_item = self.selected_item;
|
||||||
let style = style.clone();
|
let style = style.clone();
|
||||||
|
|
||||||
let multiline_docs = if show_completion_documentation {
|
let multiline_docs = if show_completion_documentation {
|
||||||
let mat = &self.matches[selected_item];
|
let mat = &self.matches[selected_item];
|
||||||
match &self.completions.read()[mat.candidate_id].documentation {
|
match &completions[mat.candidate_id].documentation {
|
||||||
Some(Documentation::MultiLinePlainText(text)) => {
|
Some(Documentation::MultiLinePlainText(text)) => {
|
||||||
Some(div().child(SharedString::from(text.clone())))
|
Some(div().child(SharedString::from(text.clone())))
|
||||||
}
|
}
|
||||||
|
@ -401,13 +399,16 @@ impl CompletionsMenu {
|
||||||
.occlude()
|
.occlude()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
drop(completions);
|
||||||
|
let completions = self.completions.clone();
|
||||||
|
let matches = self.matches.clone();
|
||||||
let list = uniform_list(
|
let list = uniform_list(
|
||||||
cx.view().clone(),
|
cx.view().clone(),
|
||||||
"completions",
|
"completions",
|
||||||
matches.len(),
|
matches.len(),
|
||||||
move |_editor, range, cx| {
|
move |_editor, range, cx| {
|
||||||
let start_ix = range.start;
|
let start_ix = range.start;
|
||||||
let completions_guard = completions.read();
|
let completions_guard = completions.borrow_mut();
|
||||||
|
|
||||||
matches[range]
|
matches[range]
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -548,7 +549,7 @@ impl CompletionsMenu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let completions = self.completions.read();
|
let completions = self.completions.borrow_mut();
|
||||||
if self.sort_completions {
|
if self.sort_completions {
|
||||||
matches.sort_unstable_by_key(|mat| {
|
matches.sort_unstable_by_key(|mat| {
|
||||||
// We do want to strike a balance here between what the language server tells us
|
// We do want to strike a balance here between what the language server tells us
|
||||||
|
@ -611,13 +612,13 @@ impl CompletionsMenu {
|
||||||
pub struct AvailableCodeAction {
|
pub struct AvailableCodeAction {
|
||||||
pub excerpt_id: ExcerptId,
|
pub excerpt_id: ExcerptId,
|
||||||
pub action: CodeAction,
|
pub action: CodeAction,
|
||||||
pub provider: Arc<dyn CodeActionProvider>,
|
pub provider: Rc<dyn CodeActionProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CodeActionContents {
|
pub struct CodeActionContents {
|
||||||
pub tasks: Option<Arc<ResolvedTasks>>,
|
pub tasks: Option<Rc<ResolvedTasks>>,
|
||||||
pub actions: Option<Arc<[AvailableCodeAction]>>,
|
pub actions: Option<Rc<[AvailableCodeAction]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeActionContents {
|
impl CodeActionContents {
|
||||||
|
@ -702,7 +703,7 @@ pub enum CodeActionsItem {
|
||||||
CodeAction {
|
CodeAction {
|
||||||
excerpt_id: ExcerptId,
|
excerpt_id: ExcerptId,
|
||||||
action: CodeAction,
|
action: CodeAction,
|
||||||
provider: Arc<dyn CodeActionProvider>,
|
provider: Rc<dyn CodeActionProvider>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,6 @@ pub use multi_buffer::{
|
||||||
use multi_buffer::{
|
use multi_buffer::{
|
||||||
ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow, ToOffsetUtf16,
|
ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow, ToOffsetUtf16,
|
||||||
};
|
};
|
||||||
use parking_lot::RwLock;
|
|
||||||
use project::{
|
use project::{
|
||||||
lsp_store::{FormatTarget, FormatTrigger, OpenLspBufferHandle},
|
lsp_store::{FormatTarget, FormatTrigger, OpenLspBufferHandle},
|
||||||
project_settings::{GitGutterSetting, ProjectSettings},
|
project_settings::{GitGutterSetting, ProjectSettings},
|
||||||
|
@ -606,7 +605,7 @@ pub struct Editor {
|
||||||
scrollbar_marker_state: ScrollbarMarkerState,
|
scrollbar_marker_state: ScrollbarMarkerState,
|
||||||
active_indent_guides_state: ActiveIndentGuidesState,
|
active_indent_guides_state: ActiveIndentGuidesState,
|
||||||
nav_history: Option<ItemNavHistory>,
|
nav_history: Option<ItemNavHistory>,
|
||||||
context_menu: RwLock<Option<CodeContextMenu>>,
|
context_menu: RefCell<Option<CodeContextMenu>>,
|
||||||
mouse_context_menu: Option<MouseContextMenu>,
|
mouse_context_menu: Option<MouseContextMenu>,
|
||||||
hunk_controls_menu_handle: PopoverMenuHandle<ui::ContextMenu>,
|
hunk_controls_menu_handle: PopoverMenuHandle<ui::ContextMenu>,
|
||||||
completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
|
completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
|
||||||
|
@ -614,7 +613,7 @@ pub struct Editor {
|
||||||
auto_signature_help: Option<bool>,
|
auto_signature_help: Option<bool>,
|
||||||
find_all_references_task_sources: Vec<Anchor>,
|
find_all_references_task_sources: Vec<Anchor>,
|
||||||
next_completion_id: CompletionId,
|
next_completion_id: CompletionId,
|
||||||
available_code_actions: Option<(Location, Arc<[AvailableCodeAction]>)>,
|
available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
|
||||||
code_actions_task: Option<Task<Result<()>>>,
|
code_actions_task: Option<Task<Result<()>>>,
|
||||||
document_highlights_task: Option<Task<()>>,
|
document_highlights_task: Option<Task<()>>,
|
||||||
linked_editing_range_task: Option<Task<Option<()>>>,
|
linked_editing_range_task: Option<Task<Option<()>>>,
|
||||||
|
@ -635,7 +634,7 @@ pub struct Editor {
|
||||||
gutter_hovered: bool,
|
gutter_hovered: bool,
|
||||||
hovered_link_state: Option<HoveredLinkState>,
|
hovered_link_state: Option<HoveredLinkState>,
|
||||||
inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
|
inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
|
||||||
code_action_providers: Vec<Arc<dyn CodeActionProvider>>,
|
code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
|
||||||
active_inline_completion: Option<InlineCompletionState>,
|
active_inline_completion: Option<InlineCompletionState>,
|
||||||
// enable_inline_completions is a switch that Vim can use to disable
|
// enable_inline_completions is a switch that Vim can use to disable
|
||||||
// inline completions based on its mode.
|
// inline completions based on its mode.
|
||||||
|
@ -1192,7 +1191,7 @@ impl Editor {
|
||||||
let mut code_action_providers = Vec::new();
|
let mut code_action_providers = Vec::new();
|
||||||
if let Some(project) = project.clone() {
|
if let Some(project) = project.clone() {
|
||||||
get_unstaged_changes_for_buffers(&project, buffer.read(cx).all_buffers(), cx);
|
get_unstaged_changes_for_buffers(&project, buffer.read(cx).all_buffers(), cx);
|
||||||
code_action_providers.push(Arc::new(project) as Arc<_>);
|
code_action_providers.push(Rc::new(project) as Rc<_>);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
|
@ -1238,7 +1237,7 @@ impl Editor {
|
||||||
scrollbar_marker_state: ScrollbarMarkerState::default(),
|
scrollbar_marker_state: ScrollbarMarkerState::default(),
|
||||||
active_indent_guides_state: ActiveIndentGuidesState::default(),
|
active_indent_guides_state: ActiveIndentGuidesState::default(),
|
||||||
nav_history: None,
|
nav_history: None,
|
||||||
context_menu: RwLock::new(None),
|
context_menu: RefCell::new(None),
|
||||||
mouse_context_menu: None,
|
mouse_context_menu: None,
|
||||||
hunk_controls_menu_handle: PopoverMenuHandle::default(),
|
hunk_controls_menu_handle: PopoverMenuHandle::default(),
|
||||||
completion_tasks: Default::default(),
|
completion_tasks: Default::default(),
|
||||||
|
@ -1384,7 +1383,7 @@ impl Editor {
|
||||||
key_context.add("renaming");
|
key_context.add("renaming");
|
||||||
}
|
}
|
||||||
if self.context_menu_visible() {
|
if self.context_menu_visible() {
|
||||||
match self.context_menu.read().as_ref() {
|
match self.context_menu.borrow().as_ref() {
|
||||||
Some(CodeContextMenu::Completions(_)) => {
|
Some(CodeContextMenu::Completions(_)) => {
|
||||||
key_context.add("menu");
|
key_context.add("menu");
|
||||||
key_context.add("showing_completions")
|
key_context.add("showing_completions")
|
||||||
|
@ -1886,10 +1885,9 @@ impl Editor {
|
||||||
|
|
||||||
if local {
|
if local {
|
||||||
let new_cursor_position = self.selections.newest_anchor().head();
|
let new_cursor_position = self.selections.newest_anchor().head();
|
||||||
let mut context_menu = self.context_menu.write();
|
let mut context_menu = self.context_menu.borrow_mut();
|
||||||
let completion_menu = match context_menu.as_ref() {
|
let completion_menu = match context_menu.as_ref() {
|
||||||
Some(CodeContextMenu::Completions(menu)) => Some(menu),
|
Some(CodeContextMenu::Completions(menu)) => Some(menu),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
*context_menu = None;
|
*context_menu = None;
|
||||||
None
|
None
|
||||||
|
@ -1913,7 +1911,7 @@ impl Editor {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
let mut context_menu = this.context_menu.write();
|
let mut context_menu = this.context_menu.borrow_mut();
|
||||||
let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
|
let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
|
@ -3651,7 +3649,7 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.snippet_stack.is_empty() && self.context_menu.read().as_ref().is_some() {
|
if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3670,7 +3668,7 @@ impl Editor {
|
||||||
|
|
||||||
let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
|
let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
|
||||||
|
|
||||||
let aside_was_displayed = match self.context_menu.read().deref() {
|
let aside_was_displayed = match self.context_menu.borrow().deref() {
|
||||||
Some(CodeContextMenu::Completions(menu)) => menu.aside_was_displayed.get(),
|
Some(CodeContextMenu::Completions(menu)) => menu.aside_was_displayed.get(),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -3723,16 +3721,14 @@ impl Editor {
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.update(&mut cx, |editor, cx| {
|
editor.update(&mut cx, |editor, cx| {
|
||||||
let mut context_menu = editor.context_menu.write();
|
let mut context_menu = editor.context_menu.borrow_mut();
|
||||||
match context_menu.as_ref() {
|
match context_menu.as_ref() {
|
||||||
None => {}
|
None => {}
|
||||||
|
|
||||||
Some(CodeContextMenu::Completions(prev_menu)) => {
|
Some(CodeContextMenu::Completions(prev_menu)) => {
|
||||||
if prev_menu.id > id {
|
if prev_menu.id > id {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return,
|
_ => return,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3795,7 +3791,7 @@ impl Editor {
|
||||||
.matches
|
.matches
|
||||||
.get(item_ix.unwrap_or(completions_menu.selected_item))?;
|
.get(item_ix.unwrap_or(completions_menu.selected_item))?;
|
||||||
let buffer_handle = completions_menu.buffer;
|
let buffer_handle = completions_menu.buffer;
|
||||||
let completions = completions_menu.completions.read();
|
let completions = completions_menu.completions.borrow_mut();
|
||||||
let completion = completions.get(mat.candidate_id)?;
|
let completion = completions.get(mat.candidate_id)?;
|
||||||
cx.stop_propagation();
|
cx.stop_propagation();
|
||||||
|
|
||||||
|
@ -3961,7 +3957,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
|
pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
|
||||||
let mut context_menu = self.context_menu.write();
|
let mut context_menu = self.context_menu.borrow_mut();
|
||||||
if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
|
if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
|
||||||
if code_actions.deployed_from_indicator == action.deployed_from_indicator {
|
if code_actions.deployed_from_indicator == action.deployed_from_indicator {
|
||||||
// Toggle if we're selecting the same one
|
// Toggle if we're selecting the same one
|
||||||
|
@ -4041,7 +4037,7 @@ impl Editor {
|
||||||
};
|
};
|
||||||
let resolved_tasks =
|
let resolved_tasks =
|
||||||
tasks.zip(task_context).map(|(tasks, task_context)| {
|
tasks.zip(task_context).map(|(tasks, task_context)| {
|
||||||
Arc::new(ResolvedTasks {
|
Rc::new(ResolvedTasks {
|
||||||
templates: tasks.resolve(&task_context).collect(),
|
templates: tasks.resolve(&task_context).collect(),
|
||||||
position: snapshot.buffer_snapshot.anchor_before(Point::new(
|
position: snapshot.buffer_snapshot.anchor_before(Point::new(
|
||||||
multibuffer_point.row,
|
multibuffer_point.row,
|
||||||
|
@ -4056,7 +4052,7 @@ impl Editor {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(true, |actions| actions.is_empty());
|
.map_or(true, |actions| actions.is_empty());
|
||||||
if let Ok(task) = editor.update(&mut cx, |editor, cx| {
|
if let Ok(task) = editor.update(&mut cx, |editor, cx| {
|
||||||
*editor.context_menu.write() =
|
*editor.context_menu.borrow_mut() =
|
||||||
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
|
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
|
||||||
buffer,
|
buffer,
|
||||||
actions: CodeActionContents {
|
actions: CodeActionContents {
|
||||||
|
@ -4241,7 +4237,7 @@ impl Editor {
|
||||||
|
|
||||||
pub fn push_code_action_provider(
|
pub fn push_code_action_provider(
|
||||||
&mut self,
|
&mut self,
|
||||||
provider: Arc<dyn CodeActionProvider>,
|
provider: Rc<dyn CodeActionProvider>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.code_action_providers.push(provider);
|
self.code_action_providers.push(provider);
|
||||||
|
@ -5004,7 +5000,7 @@ impl Editor {
|
||||||
|
|
||||||
pub fn context_menu_visible(&self) -> bool {
|
pub fn context_menu_visible(&self) -> bool {
|
||||||
self.context_menu
|
self.context_menu
|
||||||
.read()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |menu| menu.visible())
|
.map_or(false, |menu| menu.visible())
|
||||||
}
|
}
|
||||||
|
@ -5016,7 +5012,7 @@ impl Editor {
|
||||||
max_height: Pixels,
|
max_height: Pixels,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> Option<(ContextMenuOrigin, AnyElement)> {
|
) -> Option<(ContextMenuOrigin, AnyElement)> {
|
||||||
self.context_menu.read().as_ref().map(|menu| {
|
self.context_menu.borrow().as_ref().map(|menu| {
|
||||||
menu.render(
|
menu.render(
|
||||||
cursor_position,
|
cursor_position,
|
||||||
style,
|
style,
|
||||||
|
@ -5030,7 +5026,7 @@ impl Editor {
|
||||||
fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<CodeContextMenu> {
|
fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<CodeContextMenu> {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
self.completion_tasks.clear();
|
self.completion_tasks.clear();
|
||||||
self.context_menu.write().take()
|
self.context_menu.borrow_mut().take()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_snippet_choices(
|
fn show_snippet_choices(
|
||||||
|
@ -5047,7 +5043,7 @@ impl Editor {
|
||||||
let id = post_inc(&mut self.next_completion_id);
|
let id = post_inc(&mut self.next_completion_id);
|
||||||
|
|
||||||
if let Some(buffer) = buffer {
|
if let Some(buffer) = buffer {
|
||||||
*self.context_menu.write() = Some(CodeContextMenu::Completions(
|
*self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
|
||||||
CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
|
CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -7101,7 +7097,7 @@ impl Editor {
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.context_menu
|
.context_menu
|
||||||
.write()
|
.borrow_mut()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
|
.map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
@ -7210,7 +7206,7 @@ impl Editor {
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.context_menu
|
.context_menu
|
||||||
.write()
|
.borrow_mut()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
|
.map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
@ -7263,25 +7259,25 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
|
pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(context_menu) = self.context_menu.write().as_mut() {
|
if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
|
||||||
context_menu.select_first(self.completion_provider.as_deref(), cx);
|
context_menu.select_first(self.completion_provider.as_deref(), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
|
pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(context_menu) = self.context_menu.write().as_mut() {
|
if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
|
||||||
context_menu.select_prev(self.completion_provider.as_deref(), cx);
|
context_menu.select_prev(self.completion_provider.as_deref(), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
|
pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(context_menu) = self.context_menu.write().as_mut() {
|
if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
|
||||||
context_menu.select_next(self.completion_provider.as_deref(), cx);
|
context_menu.select_next(self.completion_provider.as_deref(), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
|
pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(context_menu) = self.context_menu.write().as_mut() {
|
if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
|
||||||
context_menu.select_last(self.completion_provider.as_deref(), cx);
|
context_menu.select_last(self.completion_provider.as_deref(), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12818,7 +12814,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_active_completions_menu(&self) -> bool {
|
pub fn has_active_completions_menu(&self) -> bool {
|
||||||
self.context_menu.read().as_ref().map_or(false, |menu| {
|
self.context_menu.borrow().as_ref().map_or(false, |menu| {
|
||||||
menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
|
menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -13314,7 +13310,7 @@ pub trait CompletionProvider {
|
||||||
&self,
|
&self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
completion_indices: Vec<usize>,
|
completion_indices: Vec<usize>,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> Task<Result<bool>>;
|
) -> Task<Result<bool>>;
|
||||||
|
|
||||||
|
@ -13544,7 +13540,7 @@ impl CompletionProvider for Model<Project> {
|
||||||
&self,
|
&self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
completion_indices: Vec<usize>,
|
completion_indices: Vec<usize>,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
self.update(cx, |project, cx| {
|
self.update(cx, |project, cx| {
|
||||||
|
|
|
@ -8342,9 +8342,9 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
|
||||||
additional edit
|
additional edit
|
||||||
"});
|
"});
|
||||||
cx.simulate_keystroke(" ");
|
cx.simulate_keystroke(" ");
|
||||||
assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
|
assert!(cx.editor(|e, _| e.context_menu.borrow_mut().is_none()));
|
||||||
cx.simulate_keystroke("s");
|
cx.simulate_keystroke("s");
|
||||||
assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
|
assert!(cx.editor(|e, _| e.context_menu.borrow_mut().is_none()));
|
||||||
|
|
||||||
cx.assert_editor_state(indoc! {"
|
cx.assert_editor_state(indoc! {"
|
||||||
one.second_completion
|
one.second_completion
|
||||||
|
@ -8406,12 +8406,12 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
|
||||||
});
|
});
|
||||||
cx.set_state("editorˇ");
|
cx.set_state("editorˇ");
|
||||||
cx.simulate_keystroke(".");
|
cx.simulate_keystroke(".");
|
||||||
assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
|
assert!(cx.editor(|e, _| e.context_menu.borrow_mut().is_none()));
|
||||||
cx.simulate_keystroke("c");
|
cx.simulate_keystroke("c");
|
||||||
cx.simulate_keystroke("l");
|
cx.simulate_keystroke("l");
|
||||||
cx.simulate_keystroke("o");
|
cx.simulate_keystroke("o");
|
||||||
cx.assert_editor_state("editor.cloˇ");
|
cx.assert_editor_state("editor.cloˇ");
|
||||||
assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
|
assert!(cx.editor(|e, _| e.context_menu.borrow_mut().is_none()));
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
editor.show_completions(&ShowCompletions { trigger: None }, cx);
|
editor.show_completions(&ShowCompletions { trigger: None }, cx);
|
||||||
});
|
});
|
||||||
|
@ -8468,7 +8468,8 @@ async fn test_completion_page_up_down_keys(cx: &mut gpui::TestAppContext) {
|
||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
||||||
&["first", "last"]
|
&["first", "last"]
|
||||||
|
@ -8480,7 +8481,8 @@ async fn test_completion_page_up_down_keys(cx: &mut gpui::TestAppContext) {
|
||||||
|
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
editor.move_page_down(&MovePageDown::default(), cx);
|
editor.move_page_down(&MovePageDown::default(), cx);
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert!(
|
assert!(
|
||||||
menu.selected_item == 1,
|
menu.selected_item == 1,
|
||||||
"expected PageDown to select the last item from the context menu"
|
"expected PageDown to select the last item from the context menu"
|
||||||
|
@ -8492,7 +8494,8 @@ async fn test_completion_page_up_down_keys(cx: &mut gpui::TestAppContext) {
|
||||||
|
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
editor.move_page_up(&MovePageUp::default(), cx);
|
editor.move_page_up(&MovePageUp::default(), cx);
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert!(
|
assert!(
|
||||||
menu.selected_item == 0,
|
menu.selected_item == 0,
|
||||||
"expected PageUp to select the first item from the context menu"
|
"expected PageUp to select the first item from the context menu"
|
||||||
|
@ -8560,7 +8563,8 @@ async fn test_completion_sort(cx: &mut gpui::TestAppContext) {
|
||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
||||||
&["r", "ret", "Range", "return"]
|
&["r", "ret", "Range", "return"]
|
||||||
|
@ -10704,13 +10708,13 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(
|
||||||
cx.condition(|editor, _| editor.context_menu_visible())
|
cx.condition(|editor, _| editor.context_menu_visible())
|
||||||
.await;
|
.await;
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
let context_menu = editor.context_menu.read();
|
let context_menu = editor.context_menu.borrow_mut();
|
||||||
let context_menu = context_menu
|
let context_menu = context_menu
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Should have the context menu deployed");
|
.expect("Should have the context menu deployed");
|
||||||
match context_menu {
|
match context_menu {
|
||||||
CodeContextMenu::Completions(completions_menu) => {
|
CodeContextMenu::Completions(completions_menu) => {
|
||||||
let completions = completions_menu.completions.read();
|
let completions = completions_menu.completions.borrow_mut();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
completions
|
completions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -10761,13 +10765,13 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
|
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
let context_menu = editor.context_menu.read();
|
let context_menu = editor.context_menu.borrow_mut();
|
||||||
let context_menu = context_menu
|
let context_menu = context_menu
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Should have the context menu deployed");
|
.expect("Should have the context menu deployed");
|
||||||
match context_menu {
|
match context_menu {
|
||||||
CodeContextMenu::Completions(completions_menu) => {
|
CodeContextMenu::Completions(completions_menu) => {
|
||||||
let completions = completions_menu.completions.read();
|
let completions = completions_menu.completions.borrow_mut();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
completions
|
completions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -10954,7 +10958,7 @@ async fn test_completions_default_resolve_data_handling(cx: &mut gpui::TestAppCo
|
||||||
.await;
|
.await;
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
let menu = editor.context_menu.read();
|
let menu = editor.context_menu.borrow_mut();
|
||||||
match menu.as_ref().expect("should have the completions menu") {
|
match menu.as_ref().expect("should have the completions menu") {
|
||||||
CodeContextMenu::Completions(completions_menu) => {
|
CodeContextMenu::Completions(completions_menu) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -11059,7 +11063,8 @@ async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui:
|
||||||
cx.simulate_keystroke("-");
|
cx.simulate_keystroke("-");
|
||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
||||||
&["bg-red", "bg-blue", "bg-yellow"]
|
&["bg-red", "bg-blue", "bg-yellow"]
|
||||||
|
@ -11072,7 +11077,8 @@ async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui:
|
||||||
cx.simulate_keystroke("l");
|
cx.simulate_keystroke("l");
|
||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
||||||
&["bg-blue", "bg-yellow"]
|
&["bg-blue", "bg-yellow"]
|
||||||
|
@ -11088,7 +11094,8 @@ async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui:
|
||||||
cx.simulate_keystroke("l");
|
cx.simulate_keystroke("l");
|
||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
cx.update_editor(|editor, _| {
|
cx.update_editor(|editor, _| {
|
||||||
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
|
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
|
||||||
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
|
||||||
&["bg-yellow"]
|
&["bg-yellow"]
|
||||||
|
|
|
@ -1686,7 +1686,7 @@ impl EditorElement {
|
||||||
deployed_from_indicator,
|
deployed_from_indicator,
|
||||||
actions,
|
actions,
|
||||||
..
|
..
|
||||||
})) = editor.context_menu.read().as_ref()
|
})) = editor.context_menu.borrow().as_ref()
|
||||||
{
|
{
|
||||||
actions
|
actions
|
||||||
.tasks
|
.tasks
|
||||||
|
@ -1777,7 +1777,7 @@ impl EditorElement {
|
||||||
if let Some(crate::CodeContextMenu::CodeActions(CodeActionsMenu {
|
if let Some(crate::CodeContextMenu::CodeActions(CodeActionsMenu {
|
||||||
deployed_from_indicator,
|
deployed_from_indicator,
|
||||||
..
|
..
|
||||||
})) = editor.context_menu.read().as_ref()
|
})) = editor.context_menu.borrow().as_ref()
|
||||||
{
|
{
|
||||||
active = deployed_from_indicator.map_or(true, |indicator_row| indicator_row == row);
|
active = deployed_from_indicator.map_or(true, |indicator_row| indicator_row == row);
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ use lsp::{
|
||||||
WillRenameFiles, WorkDoneProgressCancelParams, WorkspaceFolder,
|
WillRenameFiles, WorkDoneProgressCancelParams, WorkspaceFolder,
|
||||||
};
|
};
|
||||||
use node_runtime::read_package_installed_version;
|
use node_runtime::read_package_installed_version;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::Mutex;
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
|
@ -65,12 +65,14 @@ use smol::channel::Sender;
|
||||||
use snippet::Snippet;
|
use snippet::Snippet;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
|
cell::RefCell,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
iter, mem,
|
iter, mem,
|
||||||
ops::{ControlFlow, Range},
|
ops::{ControlFlow, Range},
|
||||||
path::{self, Path, PathBuf},
|
path::{self, Path, PathBuf},
|
||||||
|
rc::Rc,
|
||||||
str,
|
str,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -4137,7 +4139,7 @@ impl LspStore {
|
||||||
&self,
|
&self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
completion_indices: Vec<usize>,
|
completion_indices: Vec<usize>,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
let client = self.upstream_client();
|
let client = self.upstream_client();
|
||||||
|
@ -4151,8 +4153,8 @@ impl LspStore {
|
||||||
if let Some((client, project_id)) = client {
|
if let Some((client, project_id)) = client {
|
||||||
for completion_index in completion_indices {
|
for completion_index in completion_indices {
|
||||||
let (server_id, completion) = {
|
let (server_id, completion) = {
|
||||||
let completions_guard = completions.read();
|
let completions = completions.borrow_mut();
|
||||||
let completion = &completions_guard[completion_index];
|
let completion = &completions[completion_index];
|
||||||
did_resolve = true;
|
did_resolve = true;
|
||||||
let server_id = completion.server_id;
|
let server_id = completion.server_id;
|
||||||
let completion = completion.lsp_completion.clone();
|
let completion = completion.lsp_completion.clone();
|
||||||
|
@ -4175,8 +4177,8 @@ impl LspStore {
|
||||||
} else {
|
} else {
|
||||||
for completion_index in completion_indices {
|
for completion_index in completion_indices {
|
||||||
let (server_id, completion) = {
|
let (server_id, completion) = {
|
||||||
let completions_guard = completions.read();
|
let completions = completions.borrow_mut();
|
||||||
let completion = &completions_guard[completion_index];
|
let completion = &completions[completion_index];
|
||||||
let server_id = completion.server_id;
|
let server_id = completion.server_id;
|
||||||
let completion = completion.lsp_completion.clone();
|
let completion = completion.lsp_completion.clone();
|
||||||
|
|
||||||
|
@ -4218,7 +4220,7 @@ impl LspStore {
|
||||||
server: Arc<lsp::LanguageServer>,
|
server: Arc<lsp::LanguageServer>,
|
||||||
adapter: Arc<CachedLspAdapter>,
|
adapter: Arc<CachedLspAdapter>,
|
||||||
snapshot: &BufferSnapshot,
|
snapshot: &BufferSnapshot,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
completion_index: usize,
|
completion_index: usize,
|
||||||
completion: lsp::CompletionItem,
|
completion: lsp::CompletionItem,
|
||||||
language_registry: Arc<LanguageRegistry>,
|
language_registry: Arc<LanguageRegistry>,
|
||||||
|
@ -4246,11 +4248,11 @@ impl LspStore {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(documentation);
|
completion.documentation = Some(documentation);
|
||||||
} else {
|
} else {
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(Documentation::Undocumented);
|
completion.documentation = Some(Documentation::Undocumented);
|
||||||
}
|
}
|
||||||
|
@ -4265,7 +4267,7 @@ impl LspStore {
|
||||||
if let Some((old_range, mut new_text)) = edit {
|
if let Some((old_range, mut new_text)) = edit {
|
||||||
LineEnding::normalize(&mut new_text);
|
LineEnding::normalize(&mut new_text);
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
|
|
||||||
completion.new_text = new_text;
|
completion.new_text = new_text;
|
||||||
|
@ -4274,7 +4276,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
if completion_item.insert_text_format == Some(InsertTextFormat::SNIPPET) {
|
if completion_item.insert_text_format == Some(InsertTextFormat::SNIPPET) {
|
||||||
// vtsls might change the type of completion after resolution.
|
// vtsls might change the type of completion after resolution.
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
if completion_item.insert_text_format != completion.lsp_completion.insert_text_format {
|
if completion_item.insert_text_format != completion.lsp_completion.insert_text_format {
|
||||||
completion.lsp_completion.insert_text_format = completion_item.insert_text_format;
|
completion.lsp_completion.insert_text_format = completion_item.insert_text_format;
|
||||||
|
@ -4300,7 +4302,7 @@ impl LspStore {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.lsp_completion = completion_item;
|
completion.lsp_completion = completion_item;
|
||||||
if completion.label.filter_text() == new_label.filter_text() {
|
if completion.label.filter_text() == new_label.filter_text() {
|
||||||
|
@ -4322,7 +4324,7 @@ impl LspStore {
|
||||||
project_id: u64,
|
project_id: u64,
|
||||||
server_id: LanguageServerId,
|
server_id: LanguageServerId,
|
||||||
buffer_id: BufferId,
|
buffer_id: BufferId,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
completion_index: usize,
|
completion_index: usize,
|
||||||
completion: lsp::CompletionItem,
|
completion: lsp::CompletionItem,
|
||||||
client: AnyProtoClient,
|
client: AnyProtoClient,
|
||||||
|
@ -4360,7 +4362,7 @@ impl LspStore {
|
||||||
Documentation::MultiLinePlainText(response.documentation)
|
Documentation::MultiLinePlainText(response.documentation)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.borrow_mut();
|
||||||
let completion = &mut completions[completion_index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(documentation);
|
completion.documentation = Some(documentation);
|
||||||
completion.lsp_completion = lsp_completion;
|
completion.lsp_completion = lsp_completion;
|
||||||
|
|
|
@ -57,7 +57,7 @@ use lsp::{
|
||||||
};
|
};
|
||||||
use lsp_command::*;
|
use lsp_command::*;
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::Mutex;
|
||||||
pub use prettier_store::PrettierStore;
|
pub use prettier_store::PrettierStore;
|
||||||
use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};
|
use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};
|
||||||
use remote::{SshConnectionOptions, SshRemoteClient};
|
use remote::{SshConnectionOptions, SshRemoteClient};
|
||||||
|
@ -73,8 +73,10 @@ use snippet::Snippet;
|
||||||
use snippet_provider::SnippetProvider;
|
use snippet_provider::SnippetProvider;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
|
cell::RefCell,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::{Component, Path, PathBuf},
|
path::{Component, Path, PathBuf},
|
||||||
|
rc::Rc,
|
||||||
str,
|
str,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -2872,7 +2874,7 @@ impl Project {
|
||||||
&self,
|
&self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
completion_indices: Vec<usize>,
|
completion_indices: Vec<usize>,
|
||||||
completions: Arc<RwLock<Box<[Completion]>>>,
|
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
self.lsp_store.update(cx, |lsp_store, cx| {
|
self.lsp_store.update(cx, |lsp_store, cx| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue