Use ty's completions in playground (#18425)

This commit is contained in:
Micha Reiser 2025-06-03 10:11:39 +02:00 committed by GitHub
parent d1cb8e2142
commit 67d94d9ec8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 82 additions and 7 deletions

View file

@ -293,6 +293,27 @@ impl Workspace {
}))
}
#[wasm_bindgen]
pub fn completions(
&self,
file_id: &FileHandle,
position: Position,
) -> Result<Vec<Completion>, Error> {
let source = source_text(&self.db, file_id.file);
let index = line_index(&self.db, file_id.file);
let offset = position.to_text_size(&source, &index, self.position_encoding)?;
let completions = ty_ide::completion(&self.db, file_id.file, offset);
Ok(completions
.into_iter()
.map(|completion| Completion {
label: completion.label,
})
.collect())
}
#[wasm_bindgen(js_name = "inlayHints")]
pub fn inlay_hints(&self, file_id: &FileHandle, range: Range) -> Result<Vec<InlayHint>, Error> {
let index = line_index(&self.db, file_id.file);
@ -586,6 +607,7 @@ pub struct LocationLink {
}
#[wasm_bindgen]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Hover {
#[wasm_bindgen(getter_with_clone)]
pub markdown: String,
@ -594,6 +616,14 @@ pub struct Hover {
}
#[wasm_bindgen]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Completion {
#[wasm_bindgen(getter_with_clone)]
pub label: String,
}
#[wasm_bindgen]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InlayHint {
#[wasm_bindgen(getter_with_clone)]
pub markdown: String,

View file

@ -6484,7 +6484,7 @@
}
},
"ruff/ruff_wasm": {
"version": "0.11.8",
"version": "0.11.10",
"license": "MIT"
},
"shared": {

View file

@ -18,16 +18,16 @@ import {
import { useCallback, useEffect, useRef } from "react";
import { Theme } from "shared";
import {
Position as TyPosition,
Range as TyRange,
Severity,
type Workspace,
Position as TyPosition,
} from "ty_wasm";
import IStandaloneCodeEditor = editor.IStandaloneCodeEditor;
import { FileId, ReadonlyFiles } from "../Playground";
import { isPythonFile } from "./Files";
import { Diagnostic } from "./Diagnostics";
import IStandaloneCodeEditor = editor.IStandaloneCodeEditor;
import CompletionItemKind = languages.CompletionItemKind;
type Props = {
visible: boolean;
@ -146,13 +146,15 @@ class PlaygroundServer
editor.ICodeEditorOpener,
languages.HoverProvider,
languages.InlayHintsProvider,
languages.DocumentFormattingEditProvider
languages.DocumentFormattingEditProvider,
languages.CompletionItemProvider
{
private typeDefinitionProviderDisposable: IDisposable;
private editorOpenerDisposable: IDisposable;
private hoverDisposable: IDisposable;
private inlayHintsDisposable: IDisposable;
private formatDisposable: IDisposable;
private completionDisposable: IDisposable;
constructor(
private monaco: Monaco,
@ -168,11 +170,53 @@ class PlaygroundServer
"python",
this,
);
this.completionDisposable = monaco.languages.registerCompletionItemProvider(
"python",
this,
);
this.editorOpenerDisposable = monaco.editor.registerEditorOpener(this);
this.formatDisposable =
monaco.languages.registerDocumentFormattingEditProvider("python", this);
}
triggerCharacters: undefined;
provideCompletionItems(
model: editor.ITextModel,
position: Position,
): languages.ProviderResult<languages.CompletionList> {
const selectedFile = this.props.files.selected;
if (selectedFile == null) {
return;
}
const selectedHandle = this.props.files.handles[selectedFile];
if (selectedHandle == null) {
return;
}
const completions = this.props.workspace.completions(
selectedHandle,
new TyPosition(position.lineNumber, position.column),
);
return {
suggestions: completions.map((completion) => ({
label: completion.label,
kind: CompletionItemKind.Variable,
insertText: completion.label,
// TODO(micha): It's unclear why this field is required for monaco but not VS Code.
// and omitting it works just fine? The LSP doesn't expose this information right now
// which is why we go with undefined for now.
range: undefined as any,
})),
};
}
resolveCompletionItem: undefined;
provideInlayHints(
_model: editor.ITextModel,
range: Range,
@ -194,7 +238,7 @@ class PlaygroundServer
const inlayHints = workspace.inlayHints(
selectedHandle,
MonacoRangeToTyRange(range),
monacoRangeToTyRange(range),
);
if (inlayHints.length === 0) {
@ -447,6 +491,7 @@ class PlaygroundServer
this.typeDefinitionProviderDisposable.dispose();
this.inlayHintsDisposable.dispose();
this.formatDisposable.dispose();
this.editorOpenerDisposable.dispose();
}
}
@ -459,7 +504,7 @@ function tyRangeToMonacoRange(range: TyRange): IRange {
};
}
function MonacoRangeToTyRange(range: IRange): TyRange {
function monacoRangeToTyRange(range: IRange): TyRange {
return new TyRange(
new TyPosition(range.startLineNumber, range.startColumn),
new TyPosition(range.endLineNumber, range.endColumn),