@@ -73,7 +73,7 @@ use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock};
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::prelude::*;
-use rpc::proto::*;
+use rpc::proto::{self, *};
use scroll::{
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
};
@@ -155,7 +155,6 @@ pub fn render_parsed_markdown(
);
let runs = text_runs_for_highlights(&parsed.text, &editor_style.text, highlights);
- // todo!("add the ability to change cursor style for link ranges")
let mut links = Vec::new();
let mut link_ranges = Vec::new();
for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
@@ -972,95 +971,94 @@ impl CompletionsMenu {
fn pre_resolve_completion_documentation(
&self,
- _editor: &Editor,
- _cx: &mut ViewContext<Editor>,
+ editor: &Editor,
+ cx: &mut ViewContext<Editor>,
) -> Option<Task<()>> {
- // todo!("implementation below ");
- None
- }
- // {
- // let settings = EditorSettings::get_global(cx);
- // if !settings.show_completion_documentation {
- // return None;
- // }
+ let settings = EditorSettings::get_global(cx);
+ if !settings.show_completion_documentation {
+ return None;
+ }
- // let Some(project) = editor.project.clone() else {
- // return None;
- // };
+ let Some(project) = editor.project.clone() else {
+ return None;
+ };
- // let client = project.read(cx).client();
- // let language_registry = project.read(cx).languages().clone();
+ let client = project.read(cx).client();
+ let language_registry = project.read(cx).languages().clone();
- // let is_remote = project.read(cx).is_remote();
- // let project_id = project.read(cx).remote_id();
+ let is_remote = project.read(cx).is_remote();
+ let project_id = project.read(cx).remote_id();
- // let completions = self.completions.clone();
- // let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
+ let completions = self.completions.clone();
+ let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
- // Some(cx.spawn(move |this, mut cx| async move {
- // if is_remote {
- // let Some(project_id) = project_id else {
- // log::error!("Remote project without remote_id");
- // return;
- // };
+ Some(cx.spawn(move |this, mut cx| async move {
+ if is_remote {
+ let Some(project_id) = project_id else {
+ log::error!("Remote project without remote_id");
+ return;
+ };
- // for completion_index in completion_indices {
- // let completions_guard = completions.read();
- // let completion = &completions_guard[completion_index];
- // if completion.documentation.is_some() {
- // continue;
- // }
+ for completion_index in completion_indices {
+ let completions_guard = completions.read();
+ let completion = &completions_guard[completion_index];
+ if completion.documentation.is_some() {
+ continue;
+ }
- // let server_id = completion.server_id;
- // let completion = completion.lsp_completion.clone();
- // drop(completions_guard);
-
- // Self::resolve_completion_documentation_remote(
- // project_id,
- // server_id,
- // completions.clone(),
- // completion_index,
- // completion,
- // client.clone(),
- // language_registry.clone(),
- // )
- // .await;
-
- // _ = this.update(&mut cx, |_, cx| cx.notify());
- // }
- // } else {
- // for completion_index in completion_indices {
- // let completions_guard = completions.read();
- // let completion = &completions_guard[completion_index];
- // if completion.documentation.is_some() {
- // continue;
- // }
+ let server_id = completion.server_id;
+ let completion = completion.lsp_completion.clone();
+ drop(completions_guard);
+
+ Self::resolve_completion_documentation_remote(
+ project_id,
+ server_id,
+ completions.clone(),
+ completion_index,
+ completion,
+ client.clone(),
+ language_registry.clone(),
+ )
+ .await;
- // let server_id = completion.server_id;
- // let completion = completion.lsp_completion.clone();
- // drop(completions_guard);
+ _ = this.update(&mut cx, |_, cx| cx.notify());
+ }
+ } else {
+ for completion_index in completion_indices {
+ let completions_guard = completions.read();
+ let completion = &completions_guard[completion_index];
+ if completion.documentation.is_some() {
+ continue;
+ }
- // let server = project.read_with(&mut cx, |project, _| {
- // project.language_server_for_id(server_id)
- // });
- // let Some(server) = server else {
- // return;
- // };
-
- // Self::resolve_completion_documentation_local(
- // server,
- // completions.clone(),
- // completion_index,
- // completion,
- // language_registry.clone(),
- // )
- // .await;
-
- // _ = this.update(&mut cx, |_, cx| cx.notify());
- // }
- // }
- // }))
- // }
+ let server_id = completion.server_id;
+ let completion = completion.lsp_completion.clone();
+ drop(completions_guard);
+
+ let server = project
+ .read_with(&mut cx, |project, _| {
+ project.language_server_for_id(server_id)
+ })
+ .ok()
+ .flatten();
+ let Some(server) = server else {
+ return;
+ };
+
+ Self::resolve_completion_documentation_local(
+ server,
+ completions.clone(),
+ completion_index,
+ completion,
+ language_registry.clone(),
+ )
+ .await;
+
+ _ = this.update(&mut cx, |_, cx| cx.notify());
+ }
+ }
+ }))
+ }
fn attempt_resolve_selected_completion_documentation(
&mut self,
@@ -1081,10 +1079,9 @@ impl CompletionsMenu {
let completions = self.completions.clone();
let completions_guard = completions.read();
let completion = &completions_guard[completion_index];
- // todo!()
- // if completion.documentation.is_some() {
- // return;
- // }
+ if completion.documentation.is_some() {
+ return;
+ }
let server_id = completion.server_id;
let completion = completion.lsp_completion.clone();
@@ -1143,41 +1140,40 @@ impl CompletionsMenu {
client: Arc<Client>,
language_registry: Arc<LanguageRegistry>,
) {
- // todo!()
- // let request = proto::ResolveCompletionDocumentation {
- // project_id,
- // language_server_id: server_id.0 as u64,
- // lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
- // };
-
- // let Some(response) = client
- // .request(request)
- // .await
- // .context("completion documentation resolve proto request")
- // .log_err()
- // else {
- // return;
- // };
-
- // if response.text.is_empty() {
- // let mut completions = completions.write();
- // let completion = &mut completions[completion_index];
- // completion.documentation = Some(Documentation::Undocumented);
- // }
-
- // let documentation = if response.is_markdown {
- // Documentation::MultiLineMarkdown(
- // markdown::parse_markdown(&response.text, &language_registry, None).await,
- // )
- // } else if response.text.lines().count() <= 1 {
- // Documentation::SingleLine(response.text)
- // } else {
- // Documentation::MultiLinePlainText(response.text)
- // };
-
- // let mut completions = completions.write();
- // let completion = &mut completions[completion_index];
- // completion.documentation = Some(documentation);
+ let request = proto::ResolveCompletionDocumentation {
+ project_id,
+ language_server_id: server_id.0 as u64,
+ lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
+ };
+
+ let Some(response) = client
+ .request(request)
+ .await
+ .context("completion documentation resolve proto request")
+ .log_err()
+ else {
+ return;
+ };
+
+ if response.text.is_empty() {
+ let mut completions = completions.write();
+ let completion = &mut completions[completion_index];
+ completion.documentation = Some(Documentation::Undocumented);
+ }
+
+ let documentation = if response.is_markdown {
+ Documentation::MultiLineMarkdown(
+ markdown::parse_markdown(&response.text, &language_registry, None).await,
+ )
+ } else if response.text.lines().count() <= 1 {
+ Documentation::SingleLine(response.text)
+ } else {
+ Documentation::MultiLinePlainText(response.text)
+ };
+
+ let mut completions = completions.write();
+ let completion = &mut completions[completion_index];
+ completion.documentation = Some(documentation);
}
async fn resolve_completion_documentation_local(
@@ -1187,38 +1183,37 @@ impl CompletionsMenu {
completion: lsp::CompletionItem,
language_registry: Arc<LanguageRegistry>,
) {
- // todo!()
- // let can_resolve = server
- // .capabilities()
- // .completion_provider
- // .as_ref()
- // .and_then(|options| options.resolve_provider)
- // .unwrap_or(false);
- // if !can_resolve {
- // return;
- // }
-
- // let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
- // let Some(completion_item) = request.await.log_err() else {
- // return;
- // };
-
- // if let Some(lsp_documentation) = completion_item.documentation {
- // let documentation = language::prepare_completion_documentation(
- // &lsp_documentation,
- // &language_registry,
- // None, // TODO: Try to reasonably work out which language the completion is for
- // )
- // .await;
-
- // let mut completions = completions.write();
- // let completion = &mut completions[completion_index];
- // completion.documentation = Some(documentation);
- // } else {
- // let mut completions = completions.write();
- // let completion = &mut completions[completion_index];
- // completion.documentation = Some(Documentation::Undocumented);
- // }
+ let can_resolve = server
+ .capabilities()
+ .completion_provider
+ .as_ref()
+ .and_then(|options| options.resolve_provider)
+ .unwrap_or(false);
+ if !can_resolve {
+ return;
+ }
+
+ let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
+ let Some(completion_item) = request.await.log_err() else {
+ return;
+ };
+
+ if let Some(lsp_documentation) = completion_item.documentation {
+ let documentation = language::prepare_completion_documentation(
+ &lsp_documentation,
+ &language_registry,
+ None, // TODO: Try to reasonably work out which language the completion is for
+ )
+ .await;
+
+ let mut completions = completions.write();
+ let completion = &mut completions[completion_index];
+ completion.documentation = Some(documentation);
+ } else {
+ let mut completions = completions.write();
+ let completion = &mut completions[completion_index];
+ completion.documentation = Some(Documentation::Undocumented);
+ }
}
fn visible(&self) -> bool {
@@ -5427,178 +5427,177 @@ async fn test_strip_whitespace_and_format_via_lsp(cx: &mut gpui::TestAppContext)
);
}
-//todo!(completion)
-// #[gpui::test]
-// async fn test_completion(cx: &mut gpui::TestAppContext) {
-// init_test(cx, |_| {});
+#[gpui::test]
+async fn test_completion(cx: &mut gpui::TestAppContext) {
+ init_test(cx, |_| {});
-// let mut cx = EditorLspTestContext::new_rust(
-// lsp::ServerCapabilities {
-// completion_provider: Some(lsp::CompletionOptions {
-// trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
-// resolve_provider: Some(true),
-// ..Default::default()
-// }),
-// ..Default::default()
-// },
-// cx,
-// )
-// .await;
+ let mut cx = EditorLspTestContext::new_rust(
+ lsp::ServerCapabilities {
+ completion_provider: Some(lsp::CompletionOptions {
+ trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
+ resolve_provider: Some(true),
+ ..Default::default()
+ }),
+ ..Default::default()
+ },
+ cx,
+ )
+ .await;
-// cx.set_state(indoc! {"
-// oneˇ
-// two
-// three
-// "});
-// cx.simulate_keystroke(".");
-// handle_completion_request(
-// &mut cx,
-// indoc! {"
-// one.|<>
-// two
-// three
-// "},
-// vec!["first_completion", "second_completion"],
-// )
-// .await;
-// cx.condition(|editor, _| editor.context_menu_visible())
-// .await;
-// let apply_additional_edits = cx.update_editor(|editor, cx| {
-// editor.context_menu_next(&Default::default(), cx);
-// editor
-// .confirm_completion(&ConfirmCompletion::default(), cx)
-// .unwrap()
-// });
-// cx.assert_editor_state(indoc! {"
-// one.second_completionˇ
-// two
-// three
-// "});
+ cx.set_state(indoc! {"
+ oneˇ
+ two
+ three
+ "});
+ cx.simulate_keystroke(".");
+ handle_completion_request(
+ &mut cx,
+ indoc! {"
+ one.|<>
+ two
+ three
+ "},
+ vec!["first_completion", "second_completion"],
+ )
+ .await;
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
+ let apply_additional_edits = cx.update_editor(|editor, cx| {
+ editor.context_menu_next(&Default::default(), cx);
+ editor
+ .confirm_completion(&ConfirmCompletion::default(), cx)
+ .unwrap()
+ });
+ cx.assert_editor_state(indoc! {"
+ one.second_completionˇ
+ two
+ three
+ "});
-// handle_resolve_completion_request(
-// &mut cx,
-// Some(vec![
-// (
-// //This overlaps with the primary completion edit which is
-// //misbehavior from the LSP spec, test that we filter it out
-// indoc! {"
-// one.second_ˇcompletion
-// two
-// threeˇ
-// "},
-// "overlapping additional edit",
-// ),
-// (
-// indoc! {"
-// one.second_completion
-// two
-// threeˇ
-// "},
-// "\nadditional edit",
-// ),
-// ]),
-// )
-// .await;
-// apply_additional_edits.await.unwrap();
-// cx.assert_editor_state(indoc! {"
-// one.second_completionˇ
-// two
-// three
-// additional edit
-// "});
+ handle_resolve_completion_request(
+ &mut cx,
+ Some(vec![
+ (
+ //This overlaps with the primary completion edit which is
+ //misbehavior from the LSP spec, test that we filter it out
+ indoc! {"
+ one.second_ˇcompletion
+ two
+ threeˇ
+ "},
+ "overlapping additional edit",
+ ),
+ (
+ indoc! {"
+ one.second_completion
+ two
+ threeˇ
+ "},
+ "\nadditional edit",
+ ),
+ ]),
+ )
+ .await;
+ apply_additional_edits.await.unwrap();
+ cx.assert_editor_state(indoc! {"
+ one.second_completionˇ
+ two
+ three
+ additional edit
+ "});
-// cx.set_state(indoc! {"
-// one.second_completion
-// twoˇ
-// threeˇ
-// additional edit
-// "});
-// cx.simulate_keystroke(" ");
-// assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
-// cx.simulate_keystroke("s");
-// assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
+ cx.set_state(indoc! {"
+ one.second_completion
+ twoˇ
+ threeˇ
+ additional edit
+ "});
+ cx.simulate_keystroke(" ");
+ assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
+ cx.simulate_keystroke("s");
+ assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
-// cx.assert_editor_state(indoc! {"
-// one.second_completion
-// two sˇ
-// three sˇ
-// additional edit
-// "});
-// handle_completion_request(
-// &mut cx,
-// indoc! {"
-// one.second_completion
-// two s
-// three <s|>
-// additional edit
-// "},
-// vec!["fourth_completion", "fifth_completion", "sixth_completion"],
-// )
-// .await;
-// cx.condition(|editor, _| editor.context_menu_visible())
-// .await;
+ cx.assert_editor_state(indoc! {"
+ one.second_completion
+ two sˇ
+ three sˇ
+ additional edit
+ "});
+ handle_completion_request(
+ &mut cx,
+ indoc! {"
+ one.second_completion
+ two s
+ three <s|>
+ additional edit
+ "},
+ vec!["fourth_completion", "fifth_completion", "sixth_completion"],
+ )
+ .await;
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
-// cx.simulate_keystroke("i");
+ cx.simulate_keystroke("i");
-// handle_completion_request(
-// &mut cx,
-// indoc! {"
-// one.second_completion
-// two si
-// three <si|>
-// additional edit
-// "},
-// vec!["fourth_completion", "fifth_completion", "sixth_completion"],
-// )
-// .await;
-// cx.condition(|editor, _| editor.context_menu_visible())
-// .await;
+ handle_completion_request(
+ &mut cx,
+ indoc! {"
+ one.second_completion
+ two si
+ three <si|>
+ additional edit
+ "},
+ vec!["fourth_completion", "fifth_completion", "sixth_completion"],
+ )
+ .await;
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
-// let apply_additional_edits = cx.update_editor(|editor, cx| {
-// editor
-// .confirm_completion(&ConfirmCompletion::default(), cx)
-// .unwrap()
-// });
-// cx.assert_editor_state(indoc! {"
-// one.second_completion
-// two sixth_completionˇ
-// three sixth_completionˇ
-// additional edit
-// "});
+ let apply_additional_edits = cx.update_editor(|editor, cx| {
+ editor
+ .confirm_completion(&ConfirmCompletion::default(), cx)
+ .unwrap()
+ });
+ cx.assert_editor_state(indoc! {"
+ one.second_completion
+ two sixth_completionˇ
+ three sixth_completionˇ
+ additional edit
+ "});
-// handle_resolve_completion_request(&mut cx, None).await;
-// apply_additional_edits.await.unwrap();
+ handle_resolve_completion_request(&mut cx, None).await;
+ apply_additional_edits.await.unwrap();
-// cx.update(|cx| {
-// cx.update_global::<SettingsStore, _, _>(|settings, cx| {
-// settings.update_user_settings::<EditorSettings>(cx, |settings| {
-// settings.show_completions_on_input = Some(false);
-// });
-// })
-// });
-// cx.set_state("editorˇ");
-// cx.simulate_keystroke(".");
-// assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
-// cx.simulate_keystroke("c");
-// cx.simulate_keystroke("l");
-// cx.simulate_keystroke("o");
-// cx.assert_editor_state("editor.cloˇ");
-// assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
-// cx.update_editor(|editor, cx| {
-// editor.show_completions(&ShowCompletions, cx);
-// });
-// handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
-// cx.condition(|editor, _| editor.context_menu_visible())
-// .await;
-// let apply_additional_edits = cx.update_editor(|editor, cx| {
-// editor
-// .confirm_completion(&ConfirmCompletion::default(), cx)
-// .unwrap()
-// });
-// cx.assert_editor_state("editor.closeˇ");
-// handle_resolve_completion_request(&mut cx, None).await;
-// apply_additional_edits.await.unwrap();
-// }
+ cx.update(|cx| {
+ cx.update_global::<SettingsStore, _>(|settings, cx| {
+ settings.update_user_settings::<EditorSettings>(cx, |settings| {
+ settings.show_completions_on_input = Some(false);
+ });
+ })
+ });
+ cx.set_state("editorˇ");
+ cx.simulate_keystroke(".");
+ assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
+ cx.simulate_keystroke("c");
+ cx.simulate_keystroke("l");
+ cx.simulate_keystroke("o");
+ cx.assert_editor_state("editor.cloˇ");
+ assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
+ cx.update_editor(|editor, cx| {
+ editor.show_completions(&ShowCompletions, cx);
+ });
+ handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
+ let apply_additional_edits = cx.update_editor(|editor, cx| {
+ editor
+ .confirm_completion(&ConfirmCompletion::default(), cx)
+ .unwrap()
+ });
+ cx.assert_editor_state("editor.closeˇ");
+ handle_resolve_completion_request(&mut cx, None).await;
+ apply_additional_edits.await.unwrap();
+}
#[gpui::test]
async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
@@ -7803,197 +7802,196 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut gpui::Test
);
}
-//todo!(completions)
-// #[gpui::test]
-// async fn test_completions_with_additional_edits(cx: &mut gpui::TestAppContext) {
-// init_test(cx, |_| {});
+#[gpui::test]
+async fn test_completions_with_additional_edits(cx: &mut gpui::TestAppContext) {
+ init_test(cx, |_| {});
-// let mut cx = EditorLspTestContext::new_rust(
-// lsp::ServerCapabilities {
-// completion_provider: Some(lsp::CompletionOptions {
-// trigger_characters: Some(vec![".".to_string()]),
-// resolve_provider: Some(true),
-// ..Default::default()
-// }),
-// ..Default::default()
-// },
-// cx,
-// )
-// .await;
+ let mut cx = EditorLspTestContext::new_rust(
+ lsp::ServerCapabilities {
+ completion_provider: Some(lsp::CompletionOptions {
+ trigger_characters: Some(vec![".".to_string()]),
+ resolve_provider: Some(true),
+ ..Default::default()
+ }),
+ ..Default::default()
+ },
+ cx,
+ )
+ .await;
-// cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
-// cx.simulate_keystroke(".");
-// let completion_item = lsp::CompletionItem {
-// label: "some".into(),
-// kind: Some(lsp::CompletionItemKind::SNIPPET),
-// detail: Some("Wrap the expression in an `Option::Some`".to_string()),
-// documentation: Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
-// kind: lsp::MarkupKind::Markdown,
-// value: "```rust\nSome(2)\n```".to_string(),
-// })),
-// deprecated: Some(false),
-// sort_text: Some("fffffff2".to_string()),
-// filter_text: Some("some".to_string()),
-// insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
-// text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-// range: lsp::Range {
-// start: lsp::Position {
-// line: 0,
-// character: 22,
-// },
-// end: lsp::Position {
-// line: 0,
-// character: 22,
-// },
-// },
-// new_text: "Some(2)".to_string(),
-// })),
-// additional_text_edits: Some(vec![lsp::TextEdit {
-// range: lsp::Range {
-// start: lsp::Position {
-// line: 0,
-// character: 20,
-// },
-// end: lsp::Position {
-// line: 0,
-// character: 22,
-// },
-// },
-// new_text: "".to_string(),
-// }]),
-// ..Default::default()
-// };
-
-// let closure_completion_item = completion_item.clone();
-// let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
-// let task_completion_item = closure_completion_item.clone();
-// async move {
-// Ok(Some(lsp::CompletionResponse::Array(vec![
-// task_completion_item,
-// ])))
-// }
-// });
+ cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
+ cx.simulate_keystroke(".");
+ let completion_item = lsp::CompletionItem {
+ label: "some".into(),
+ kind: Some(lsp::CompletionItemKind::SNIPPET),
+ detail: Some("Wrap the expression in an `Option::Some`".to_string()),
+ documentation: Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
+ kind: lsp::MarkupKind::Markdown,
+ value: "```rust\nSome(2)\n```".to_string(),
+ })),
+ deprecated: Some(false),
+ sort_text: Some("fffffff2".to_string()),
+ filter_text: Some("some".to_string()),
+ insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range: lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 22,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 22,
+ },
+ },
+ new_text: "Some(2)".to_string(),
+ })),
+ additional_text_edits: Some(vec![lsp::TextEdit {
+ range: lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 20,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 22,
+ },
+ },
+ new_text: "".to_string(),
+ }]),
+ ..Default::default()
+ };
-// request.next().await;
+ let closure_completion_item = completion_item.clone();
+ let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
+ let task_completion_item = closure_completion_item.clone();
+ async move {
+ Ok(Some(lsp::CompletionResponse::Array(vec![
+ task_completion_item,
+ ])))
+ }
+ });
-// cx.condition(|editor, _| editor.context_menu_visible())
-// .await;
-// let apply_additional_edits = cx.update_editor(|editor, cx| {
-// editor
-// .confirm_completion(&ConfirmCompletion::default(), cx)
-// .unwrap()
-// });
-// cx.assert_editor_state(indoc! {"fn main() { let a = 2.Some(2)ˇ; }"});
-
-// cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
-// let task_completion_item = completion_item.clone();
-// async move { Ok(task_completion_item) }
-// })
-// .next()
-// .await
-// .unwrap();
-// apply_additional_edits.await.unwrap();
-// cx.assert_editor_state(indoc! {"fn main() { let a = Some(2)ˇ; }"});
-// }
+ request.next().await;
-// #[gpui::test]
-// async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui::TestAppContext) {
-// init_test(cx, |_| {});
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
+ let apply_additional_edits = cx.update_editor(|editor, cx| {
+ editor
+ .confirm_completion(&ConfirmCompletion::default(), cx)
+ .unwrap()
+ });
+ cx.assert_editor_state(indoc! {"fn main() { let a = 2.Some(2)ˇ; }"});
+
+ cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
+ let task_completion_item = completion_item.clone();
+ async move { Ok(task_completion_item) }
+ })
+ .next()
+ .await
+ .unwrap();
+ apply_additional_edits.await.unwrap();
+ cx.assert_editor_state(indoc! {"fn main() { let a = Some(2)ˇ; }"});
+}
-// let mut cx = EditorLspTestContext::new(
-// Language::new(
-// LanguageConfig {
-// path_suffixes: vec!["jsx".into()],
-// overrides: [(
-// "element".into(),
-// LanguageConfigOverride {
-// word_characters: Override::Set(['-'].into_iter().collect()),
-// ..Default::default()
-// },
-// )]
-// .into_iter()
-// .collect(),
-// ..Default::default()
-// },
-// Some(tree_sitter_typescript::language_tsx()),
-// )
-// .with_override_query("(jsx_self_closing_element) @element")
-// .unwrap(),
-// lsp::ServerCapabilities {
-// completion_provider: Some(lsp::CompletionOptions {
-// trigger_characters: Some(vec![":".to_string()]),
-// ..Default::default()
-// }),
-// ..Default::default()
-// },
-// cx,
-// )
-// .await;
+#[gpui::test]
+async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui::TestAppContext) {
+ init_test(cx, |_| {});
-// cx.lsp
-// .handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
-// Ok(Some(lsp::CompletionResponse::Array(vec![
-// lsp::CompletionItem {
-// label: "bg-blue".into(),
-// ..Default::default()
-// },
-// lsp::CompletionItem {
-// label: "bg-red".into(),
-// ..Default::default()
-// },
-// lsp::CompletionItem {
-// label: "bg-yellow".into(),
-// ..Default::default()
-// },
-// ])))
-// });
+ let mut cx = EditorLspTestContext::new(
+ Language::new(
+ LanguageConfig {
+ path_suffixes: vec!["jsx".into()],
+ overrides: [(
+ "element".into(),
+ LanguageConfigOverride {
+ word_characters: Override::Set(['-'].into_iter().collect()),
+ ..Default::default()
+ },
+ )]
+ .into_iter()
+ .collect(),
+ ..Default::default()
+ },
+ Some(tree_sitter_typescript::language_tsx()),
+ )
+ .with_override_query("(jsx_self_closing_element) @element")
+ .unwrap(),
+ lsp::ServerCapabilities {
+ completion_provider: Some(lsp::CompletionOptions {
+ trigger_characters: Some(vec![":".to_string()]),
+ ..Default::default()
+ }),
+ ..Default::default()
+ },
+ cx,
+ )
+ .await;
-// cx.set_state(r#"<p class="bgˇ" />"#);
+ cx.lsp
+ .handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
+ Ok(Some(lsp::CompletionResponse::Array(vec![
+ lsp::CompletionItem {
+ label: "bg-blue".into(),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "bg-red".into(),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "bg-yellow".into(),
+ ..Default::default()
+ },
+ ])))
+ });
-// // Trigger completion when typing a dash, because the dash is an extra
-// // word character in the 'element' scope, which contains the cursor.
-// cx.simulate_keystroke("-");
-// cx.executor().run_until_parked();
-// cx.update_editor(|editor, _| {
-// if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
-// assert_eq!(
-// menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
-// &["bg-red", "bg-blue", "bg-yellow"]
-// );
-// } else {
-// panic!("expected completion menu to be open");
-// }
-// });
+ cx.set_state(r#"<p class="bgˇ" />"#);
-// cx.simulate_keystroke("l");
-// cx.executor().run_until_parked();
-// cx.update_editor(|editor, _| {
-// if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
-// assert_eq!(
-// menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
-// &["bg-blue", "bg-yellow"]
-// );
-// } else {
-// panic!("expected completion menu to be open");
-// }
-// });
+ // Trigger completion when typing a dash, because the dash is an extra
+ // word character in the 'element' scope, which contains the cursor.
+ cx.simulate_keystroke("-");
+ cx.executor().run_until_parked();
+ cx.update_editor(|editor, _| {
+ if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
+ assert_eq!(
+ menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
+ &["bg-red", "bg-blue", "bg-yellow"]
+ );
+ } else {
+ panic!("expected completion menu to be open");
+ }
+ });
-// // When filtering completions, consider the character after the '-' to
-// // be the start of a subword.
-// cx.set_state(r#"<p class="yelˇ" />"#);
-// cx.simulate_keystroke("l");
-// cx.executor().run_until_parked();
-// cx.update_editor(|editor, _| {
-// if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
-// assert_eq!(
-// menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
-// &["bg-yellow"]
-// );
-// } else {
-// panic!("expected completion menu to be open");
-// }
-// });
-// }
+ cx.simulate_keystroke("l");
+ cx.executor().run_until_parked();
+ cx.update_editor(|editor, _| {
+ if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
+ assert_eq!(
+ menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
+ &["bg-blue", "bg-yellow"]
+ );
+ } else {
+ panic!("expected completion menu to be open");
+ }
+ });
+
+ // When filtering completions, consider the character after the '-' to
+ // be the start of a subword.
+ cx.set_state(r#"<p class="yelˇ" />"#);
+ cx.simulate_keystroke("l");
+ cx.executor().run_until_parked();
+ cx.update_editor(|editor, _| {
+ if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
+ assert_eq!(
+ menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
+ &["bg-yellow"]
+ );
+ } else {
+ panic!("expected completion menu to be open");
+ }
+ });
+}
#[gpui::test]
async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
@@ -5,7 +5,7 @@ use crate::{
Anchor, DisplayPoint, Editor, EditorSnapshot, GoToDefinition, GoToTypeDefinition, InlayId,
SelectPhase,
};
-use gpui::{Task, ViewContext};
+use gpui::{px, Task, ViewContext};
use language::{Bias, ToOffset};
use lsp::LanguageServerId;
use project::{
@@ -13,6 +13,7 @@ use project::{
ResolveState,
};
use std::ops::Range;
+use theme::ActiveTheme as _;
use util::TryFutureExt;
#[derive(Debug, Default)]
@@ -485,40 +486,45 @@ pub fn show_link_definition(
});
if any_definition_does_not_contain_current_location {
- // todo!()
- // // Highlight symbol using theme link definition highlight style
- // let style = theme::current(cx).editor.link_definition;
- // let highlight_range =
- // symbol_range.unwrap_or_else(|| match &trigger_point {
- // TriggerPoint::Text(trigger_anchor) => {
- // let snapshot = &snapshot.buffer_snapshot;
- // // If no symbol range returned from language server, use the surrounding word.
- // let (offset_range, _) =
- // snapshot.surrounding_word(*trigger_anchor);
- // RangeInEditor::Text(
- // snapshot.anchor_before(offset_range.start)
- // ..snapshot.anchor_after(offset_range.end),
- // )
- // }
- // TriggerPoint::InlayHint(highlight, _, _) => {
- // RangeInEditor::Inlay(highlight.clone())
- // }
- // });
-
- // match highlight_range {
- // RangeInEditor::Text(text_range) => this
- // .highlight_text::<LinkGoToDefinitionState>(
- // vec![text_range],
- // style,
- // cx,
- // ),
- // RangeInEditor::Inlay(highlight) => this
- // .highlight_inlays::<LinkGoToDefinitionState>(
- // vec![highlight],
- // style,
- // cx,
- // ),
- // }
+ let style = gpui::HighlightStyle {
+ underline: Some(gpui::UnderlineStyle {
+ thickness: px(1.),
+ ..Default::default()
+ }),
+ color: Some(gpui::red()),
+ ..Default::default()
+ };
+ let highlight_range =
+ symbol_range.unwrap_or_else(|| match &trigger_point {
+ TriggerPoint::Text(trigger_anchor) => {
+ let snapshot = &snapshot.buffer_snapshot;
+ // If no symbol range returned from language server, use the surrounding word.
+ let (offset_range, _) =
+ snapshot.surrounding_word(*trigger_anchor);
+ RangeInEditor::Text(
+ snapshot.anchor_before(offset_range.start)
+ ..snapshot.anchor_after(offset_range.end),
+ )
+ }
+ TriggerPoint::InlayHint(highlight, _, _) => {
+ RangeInEditor::Inlay(highlight.clone())
+ }
+ });
+
+ match highlight_range {
+ RangeInEditor::Text(text_range) => this
+ .highlight_text::<LinkGoToDefinitionState>(
+ vec![text_range],
+ style,
+ cx,
+ ),
+ RangeInEditor::Inlay(highlight) => this
+ .highlight_inlays::<LinkGoToDefinitionState>(
+ vec![highlight],
+ style,
+ cx,
+ ),
+ }
} else {
hide_link_definition(this, cx);
}