mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
Use ty's completions in playground (#18425)
This commit is contained in:
parent
d1cb8e2142
commit
67d94d9ec8
3 changed files with 82 additions and 7 deletions
|
@ -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,
|
||||
|
|
2
playground/package-lock.json
generated
2
playground/package-lock.json
generated
|
@ -6484,7 +6484,7 @@
|
|||
}
|
||||
},
|
||||
"ruff/ruff_wasm": {
|
||||
"version": "0.11.8",
|
||||
"version": "0.11.10",
|
||||
"license": "MIT"
|
||||
},
|
||||
"shared": {
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue