Skip to content

Commit 426fa4b

Browse files
authored
[ty] Add signature help provider to playground (#19276)
1 parent b0b65c2 commit 426fa4b

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

crates/ty_wasm/src/lib.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use ruff_notebook::Notebook;
1414
use ruff_python_formatter::formatted_file;
1515
use ruff_source_file::{LineIndex, OneIndexed, SourceLocation};
1616
use ruff_text_size::{Ranged, TextSize};
17+
use ty_ide::signature_help;
1718
use ty_ide::{MarkupKind, goto_type_definition, hover, inlay_hints};
1819
use ty_project::ProjectMetadata;
1920
use ty_project::metadata::options::Options;
@@ -385,6 +386,51 @@ impl Workspace {
385386

386387
Ok(result)
387388
}
389+
390+
#[wasm_bindgen(js_name = "signatureHelp")]
391+
pub fn signature_help(
392+
&self,
393+
file_id: &FileHandle,
394+
position: Position,
395+
) -> Result<Option<SignatureHelp>, Error> {
396+
let source = source_text(&self.db, file_id.file);
397+
let index = line_index(&self.db, file_id.file);
398+
399+
let offset = position.to_text_size(&source, &index, self.position_encoding)?;
400+
401+
let Some(signature_help_info) = signature_help(&self.db, file_id.file, offset) else {
402+
return Ok(None);
403+
};
404+
405+
let signatures = signature_help_info
406+
.signatures
407+
.into_iter()
408+
.map(|sig| {
409+
let parameters = sig
410+
.parameters
411+
.into_iter()
412+
.map(|param| ParameterInformation {
413+
label: param.label,
414+
documentation: param.documentation,
415+
})
416+
.collect();
417+
418+
SignatureInformation {
419+
label: sig.label,
420+
documentation: sig.documentation,
421+
parameters,
422+
active_parameter: sig.active_parameter.and_then(|p| u32::try_from(p).ok()),
423+
}
424+
})
425+
.collect();
426+
427+
Ok(Some(SignatureHelp {
428+
signatures,
429+
active_signature: signature_help_info
430+
.active_signature
431+
.and_then(|s| u32::try_from(s).ok()),
432+
}))
433+
}
388434
}
389435

390436
pub(crate) fn into_error<E: std::fmt::Display>(err: E) -> Error {
@@ -749,6 +795,35 @@ pub struct SemanticToken {
749795
pub range: Range,
750796
}
751797

798+
#[wasm_bindgen]
799+
#[derive(Clone)]
800+
pub struct SignatureHelp {
801+
#[wasm_bindgen(getter_with_clone)]
802+
pub signatures: Vec<SignatureInformation>,
803+
pub active_signature: Option<u32>,
804+
}
805+
806+
#[wasm_bindgen]
807+
#[derive(Clone)]
808+
pub struct SignatureInformation {
809+
#[wasm_bindgen(getter_with_clone)]
810+
pub label: String,
811+
#[wasm_bindgen(getter_with_clone)]
812+
pub documentation: Option<String>,
813+
#[wasm_bindgen(getter_with_clone)]
814+
pub parameters: Vec<ParameterInformation>,
815+
pub active_parameter: Option<u32>,
816+
}
817+
818+
#[wasm_bindgen]
819+
#[derive(Clone)]
820+
pub struct ParameterInformation {
821+
#[wasm_bindgen(getter_with_clone)]
822+
pub label: String,
823+
#[wasm_bindgen(getter_with_clone)]
824+
pub documentation: Option<String>,
825+
}
826+
752827
#[wasm_bindgen]
753828
impl SemanticToken {
754829
pub fn kinds() -> Vec<String> {

playground/ty/src/Editor/Editor.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ class PlaygroundServer
152152
languages.DocumentFormattingEditProvider,
153153
languages.CompletionItemProvider,
154154
languages.DocumentSemanticTokensProvider,
155-
languages.DocumentRangeSemanticTokensProvider
155+
languages.DocumentRangeSemanticTokensProvider,
156+
languages.SignatureHelpProvider
156157
{
157158
private typeDefinitionProviderDisposable: IDisposable;
158159
private editorOpenerDisposable: IDisposable;
@@ -162,6 +163,7 @@ class PlaygroundServer
162163
private completionDisposable: IDisposable;
163164
private semanticTokensDisposable: IDisposable;
164165
private rangeSemanticTokensDisposable: IDisposable;
166+
private signatureHelpDisposable: IDisposable;
165167

166168
constructor(
167169
private monaco: Monaco,
@@ -191,9 +193,13 @@ class PlaygroundServer
191193
this.editorOpenerDisposable = monaco.editor.registerEditorOpener(this);
192194
this.formatDisposable =
193195
monaco.languages.registerDocumentFormattingEditProvider("python", this);
196+
this.signatureHelpDisposable =
197+
monaco.languages.registerSignatureHelpProvider("python", this);
194198
}
195199

196200
triggerCharacters: string[] = ["."];
201+
signatureHelpTriggerCharacters: string[] = ["(", ","];
202+
signatureHelpRetriggerCharacters: string[] = [")"];
197203

198204
getLegend(): languages.SemanticTokensLegend {
199205
return {
@@ -292,6 +298,61 @@ class PlaygroundServer
292298

293299
resolveCompletionItem: undefined;
294300

301+
provideSignatureHelp(
302+
model: editor.ITextModel,
303+
position: Position,
304+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
305+
_token: CancellationToken,
306+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
307+
_context: languages.SignatureHelpContext,
308+
): languages.ProviderResult<languages.SignatureHelpResult> {
309+
const selectedFile = this.props.files.selected;
310+
311+
if (selectedFile == null) {
312+
return;
313+
}
314+
315+
const selectedHandle = this.props.files.handles[selectedFile];
316+
317+
if (selectedHandle == null) {
318+
return;
319+
}
320+
321+
const signatureHelp = this.props.workspace.signatureHelp(
322+
selectedHandle,
323+
new TyPosition(position.lineNumber, position.column),
324+
);
325+
326+
if (signatureHelp == null) {
327+
return undefined;
328+
}
329+
330+
return {
331+
dispose() {},
332+
value: {
333+
signatures: signatureHelp.signatures.map((sig) => ({
334+
label: sig.label,
335+
documentation: sig.documentation
336+
? { value: sig.documentation }
337+
: undefined,
338+
parameters: sig.parameters.map((param) => ({
339+
label: param.label,
340+
documentation: param.documentation
341+
? { value: param.documentation }
342+
: undefined,
343+
})),
344+
activeParameter: sig.active_parameter,
345+
})),
346+
activeSignature: signatureHelp.active_signature ?? 0,
347+
activeParameter:
348+
signatureHelp.active_signature != null
349+
? (signatureHelp.signatures[signatureHelp.active_signature]
350+
?.active_parameter ?? 0)
351+
: 0,
352+
},
353+
};
354+
}
355+
295356
provideInlayHints(
296357
_model: editor.ITextModel,
297358
range: Range,
@@ -569,6 +630,7 @@ class PlaygroundServer
569630
this.rangeSemanticTokensDisposable.dispose();
570631
this.semanticTokensDisposable.dispose();
571632
this.completionDisposable.dispose();
633+
this.signatureHelpDisposable.dispose();
572634
}
573635
}
574636

0 commit comments

Comments
 (0)