Skip to content

Commit 6492ec2

Browse files
authored
Impl displaying signature from LSP (lapce#1720)
1 parent e65d64b commit 6492ec2

File tree

23 files changed

+970
-106
lines changed

23 files changed

+970
-106
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
### Features/Changes
6+
- [#1720](https://github.com/lapce/lapce/pull/1720): Display signature/parameter information from LSP
67

78
### Bug Fixes
89

defaults/keymaps-macos.toml

+5
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ key = "meta+i"
200200
command = "get_completion"
201201
mode = "i"
202202

203+
[[keymaps]]
204+
key = "ctrl+shift+space"
205+
command = "get_signature"
206+
mode = "i"
207+
203208
[[keymaps]]
204209
key = "meta+."
205210
command = "show_code_actions"

defaults/keymaps-nonmacos.toml

+5
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ key = "ctrl+i"
218218
command = "get_completion"
219219
mode = "i"
220220

221+
[[keymaps]]
222+
key = "ctrl+shift+space"
223+
command = "get_signature"
224+
mode = "i"
225+
221226
[[keymaps]]
222227
key = "ctrl+."
223228
command = "show_code_actions"

defaults/settings.toml

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ scroll-beyond-last-line = true
1818
cursor-surrounding-lines = 1
1919
sticky-header = true
2020
completion-show-documentation = true
21+
show-signature = true
22+
signature-label-code-block = true
2123
auto-closing-matching-pairs = true
2224
hover-delay = 300 # ms
2325
modal-mode-relative-line-numbers = true

lapce-core/src/command.rs

+2
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ pub enum FocusCommand {
257257
ShowCodeActions,
258258
#[strum(serialize = "get_completion")]
259259
GetCompletion,
260+
#[strum(serialize = "get_signature")]
261+
GetSignature,
260262
/// This will close a modal, such as the settings window or completion
261263
#[strum(message = "Close Modal")]
262264
#[strum(serialize = "modal.close")]

lapce-data/src/command.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ use lapce_xi_rope::{spans::Spans, Rope};
2525
use lsp_types::{
2626
CodeActionOrCommand, CodeActionResponse, CompletionItem, CompletionResponse,
2727
InlayHint, Location, MessageType, Position, ProgressParams,
28-
PublishDiagnosticsParams, SelectionRange, TextEdit, WorkspaceEdit,
28+
PublishDiagnosticsParams, SelectionRange, SignatureHelp, TextEdit,
29+
WorkspaceEdit,
2930
};
3031
use serde_json::Value;
3132
use strum::{self, EnumMessage, IntoEnumIterator};
@@ -560,6 +561,11 @@ pub enum LapceUICommand {
560561
CancelCompletion(usize),
561562
ResolveCompletion(BufferId, u64, usize, Box<CompletionItem>),
562563
UpdateCompletion(usize, String, CompletionResponse, PluginId),
564+
UpdateSignature {
565+
request_id: usize,
566+
resp: SignatureHelp,
567+
plugin_id: PluginId,
568+
},
563569
UpdateHover(usize, Arc<Vec<RichText>>),
564570
UpdateVoltReadme(RichText),
565571
UpdateInlayHints {

lapce-data/src/config.rs

+8
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ pub struct EditorConfig {
340340
desc = "If the editor should show the documentation of the current completion item"
341341
)]
342342
pub completion_show_documentation: bool,
343+
#[field_names(
344+
desc = "If the editor should show the signature of the function as the parameters are being typed"
345+
)]
346+
pub show_signature: bool,
347+
#[field_names(
348+
desc = "If the signature view should put the codeblock into a label. This might not work nicely for LSPs which provide invalid code for their labels."
349+
)]
350+
pub signature_label_code_block: bool,
343351
#[field_names(
344352
desc = "Whether the editor should disable automatic closing of matching pairs"
345353
)]

lapce-data/src/data.rs

+50
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ use crate::{
7676
rename::RenameData,
7777
search::SearchData,
7878
settings::LapceSettingsPanelData,
79+
signature::SignatureData,
7980
source_control::SourceControlData,
8081
split::{SplitDirection, SplitMoveDirection},
8182
terminal::TerminalSplitData,
@@ -626,6 +627,7 @@ pub struct LapceTabData {
626627
pub title: Arc<TitleData>,
627628
pub main_split: LapceMainSplitData,
628629
pub completion: Arc<CompletionData>,
630+
pub signature: Arc<SignatureData>,
629631
pub hover: Arc<HoverData>,
630632
pub rename: Arc<RenameData>,
631633
pub terminal: Arc<TerminalSplitData>,
@@ -721,6 +723,7 @@ impl LapceTabData {
721723
let palette = Arc::new(PaletteData::new(config.clone(), proxy.clone()));
722724
let completion = Arc::new(CompletionData::new(config.clone()));
723725
let hover = Arc::new(HoverData::new());
726+
let signature = Arc::new(SignatureData::new());
724727
let rename = Arc::new(RenameData::new());
725728
let source_control = Arc::new(SourceControlData::new());
726729
let settings = Arc::new(LapceSettingsPanelData::new());
@@ -840,6 +843,7 @@ impl LapceTabData {
840843
title,
841844
main_split,
842845
completion,
846+
signature,
843847
hover,
844848
rename,
845849
terminal,
@@ -937,6 +941,7 @@ impl LapceTabData {
937941
view_id: editor_view_id,
938942
main_split: self.main_split.clone(),
939943
completion: self.completion.clone(),
944+
signature: self.signature.clone(),
940945
hover: self.hover.clone(),
941946
rename: self.rename.clone(),
942947
focus_area: self.focus_area.clone(),
@@ -985,6 +990,7 @@ impl LapceTabData {
985990
doc: &Arc<Document>,
986991
) {
987992
self.completion = editor_buffer_data.completion.clone();
993+
self.signature = editor_buffer_data.signature.clone();
988994
self.hover = editor_buffer_data.hover.clone();
989995
self.rename = editor_buffer_data.rename.clone();
990996
self.main_split = editor_buffer_data.main_split.clone();
@@ -1074,6 +1080,50 @@ impl LapceTabData {
10741080
}
10751081
}
10761082

1083+
pub fn signature_origin(
1084+
&self,
1085+
text: &mut PietText,
1086+
tab_size: Size,
1087+
signature_size: Size,
1088+
config: &LapceConfig,
1089+
) -> Point {
1090+
let editor = self.main_split.active_editor();
1091+
let editor = match editor {
1092+
Some(editor) => editor,
1093+
None => return Point::ZERO,
1094+
};
1095+
1096+
match &editor.content {
1097+
BufferContent::File(_) | BufferContent::Scratch(_, _) => {
1098+
let doc = self.main_split.editor_doc(editor.view_id);
1099+
let offset = self.signature.offset;
1100+
let (point_above, _point_below) =
1101+
doc.points_of_offset(text, offset, &editor.view, config);
1102+
1103+
let mut origin = *editor.window_origin.borrow()
1104+
- self.window_origin.borrow().to_vec2()
1105+
+ Vec2::new(point_above.x - 5.0, point_above.y)
1106+
- Vec2::new(0.0, signature_size.height);
1107+
1108+
// TODO: What about if the signature's position is past the tab size?
1109+
1110+
if origin.x + signature_size.width + 1.0 > tab_size.width {
1111+
origin.x = tab_size.width - signature_size.width - 1.0;
1112+
}
1113+
1114+
if origin.x <= 0.0 {
1115+
origin.x = 0.0;
1116+
}
1117+
1118+
origin
1119+
}
1120+
BufferContent::SettingsValue(_) | BufferContent::Local(_) => {
1121+
*editor.window_origin.borrow()
1122+
- self.window_origin.borrow().to_vec2()
1123+
}
1124+
}
1125+
}
1126+
10771127
pub fn rename_origin(
10781128
&self,
10791129
text: &mut PietText,

lapce-data/src/editor.rs

+61
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use crate::{
5555
proxy::{path_from_url, LapceProxy},
5656
rename::RenameData,
5757
selection_range::SelectionRangeDirection,
58+
signature::{SignatureData, SignatureStatus},
5859
source_control::SourceControlData,
5960
split::{SplitDirection, SplitMoveDirection},
6061
};
@@ -208,6 +209,7 @@ pub struct LapceEditorBufferData {
208209
pub editor: Arc<LapceEditorData>,
209210
pub doc: Arc<Document>,
210211
pub completion: Arc<CompletionData>,
212+
pub signature: Arc<SignatureData>,
211213
pub hover: Arc<HoverData>,
212214
pub rename: Arc<RenameData>,
213215
pub main_split: LapceMainSplitData,
@@ -341,6 +343,12 @@ impl LapceEditorBufferData {
341343
&& self.completion.len() > 0
342344
}
343345

346+
/// Check if there are signatures that are being rendered
347+
fn has_signature(&self) -> bool {
348+
self.signature.status != SignatureStatus::Inactive
349+
&& !self.signature.is_empty()
350+
}
351+
344352
fn has_hover(&self) -> bool {
345353
self.hover.status != HoverStatus::Inactive && !self.hover.is_empty()
346354
}
@@ -612,6 +620,14 @@ impl LapceEditorBufferData {
612620
completion.cancel();
613621
}
614622

623+
pub fn cancel_signature(&mut self) {
624+
if self.signature.status == SignatureStatus::Inactive {
625+
return;
626+
}
627+
let signature = Arc::make_mut(&mut self.signature);
628+
signature.cancel();
629+
}
630+
615631
pub fn cancel_hover(&mut self) {
616632
let hover = Arc::make_mut(&mut self.hover);
617633
hover.cancel();
@@ -781,6 +797,34 @@ impl LapceEditorBufferData {
781797
}
782798
}
783799

800+
fn update_signature(&mut self) {
801+
if self.get_mode() != Mode::Insert {
802+
self.cancel_signature();
803+
return;
804+
}
805+
if !self.doc.loaded() || !self.doc.content().is_file() {
806+
return;
807+
}
808+
809+
let offset = self.editor.cursor.offset();
810+
let start_offset = self.doc.buffer().prev_code_boundary(offset);
811+
812+
let signature = Arc::make_mut(&mut self.signature);
813+
814+
signature.buffer_id = self.doc.id();
815+
signature.offset = start_offset;
816+
signature.status = SignatureStatus::Started;
817+
signature.request_id += 1;
818+
819+
let start_pos = self.doc.buffer().offset_to_position(start_offset);
820+
signature.request(
821+
self.proxy.clone(),
822+
signature.request_id,
823+
self.doc.content().path().unwrap().into(),
824+
start_pos,
825+
);
826+
}
827+
784828
/// return true if there's existing hover and it's not changed
785829
pub fn check_hover(
786830
&mut self,
@@ -1416,6 +1460,10 @@ impl LapceEditorBufferData {
14161460
}
14171461
}
14181462
self.cancel_completion();
1463+
// Cancel but then immediately try to see if there's a signature to provide
1464+
// TODO: Can we be smarter about this?
1465+
self.cancel_signature();
1466+
self.update_signature();
14191467
self.cancel_hover();
14201468
CommandExecuted::Yes
14211469
}
@@ -1447,8 +1495,11 @@ impl LapceEditorBufferData {
14471495

14481496
if show_completion(cmd, &doc_before_edit, &deltas) {
14491497
self.update_completion(ctx, false);
1498+
// TODO: This can be requested in more specific cases based on the LSP supplied trigger
1499+
self.update_signature();
14501500
} else {
14511501
self.cancel_completion();
1502+
self.cancel_signature();
14521503
}
14531504
self.apply_deltas(&deltas);
14541505

@@ -1478,6 +1529,9 @@ impl LapceEditorBufferData {
14781529
if self.has_completions() {
14791530
self.cancel_completion();
14801531
}
1532+
if self.has_signature() {
1533+
self.cancel_signature();
1534+
}
14811535
if self.has_hover() {
14821536
self.cancel_hover();
14831537
}
@@ -1822,6 +1876,7 @@ impl LapceEditorBufferData {
18221876
if last_placeholder {
18231877
Arc::make_mut(&mut self.editor).snippet = None;
18241878
}
1879+
self.update_signature();
18251880
self.cancel_completion();
18261881
}
18271882
}
@@ -1848,6 +1903,7 @@ impl LapceEditorBufferData {
18481903
.cursor
18491904
.set_insert(selection);
18501905
}
1906+
self.update_signature();
18511907
self.cancel_completion();
18521908
}
18531909
}
@@ -1902,6 +1958,9 @@ impl LapceEditorBufferData {
19021958
// we allow empty inputs to allow for cases where the user wants to get the autocompletion beforehand
19031959
self.update_completion(ctx, true);
19041960
}
1961+
GetSignature => {
1962+
self.update_signature();
1963+
}
19051964
GotoDefinition => {
19061965
if let BufferContent::File(path) = self.doc.content() {
19071966
let offset = self.editor.cursor.offset();
@@ -2392,6 +2451,7 @@ impl LapceEditorBufferData {
23922451
let cursor = &mut Arc::make_mut(&mut self.editor).cursor;
23932452
self.doc
23942453
.do_multi_selection(ctx.text(), cursor, cmd, &view, &self.config);
2454+
self.cancel_signature();
23952455
self.cancel_completion();
23962456
CommandExecuted::Yes
23972457
}
@@ -2465,6 +2525,7 @@ impl KeyPressFocus for LapceEditorBufferData {
24652525
.all(|c| c.is_whitespace() || c.is_ascii_whitespace())
24662526
{
24672527
self.update_completion(ctx, false);
2528+
self.update_signature();
24682529
} else {
24692530
self.cancel_completion();
24702531
}

0 commit comments

Comments
 (0)