Skip to content

Commit fd6b6bf

Browse files
UnboundVariableUnboundVariable
authored andcommitted
[ty] Added support for document highlights in playground. (#19540)
This PR adds support for the "document highlights" feature in the ty playground. --------- Co-authored-by: UnboundVariable <unbound@gmail.com>
1 parent a4c6ebe commit fd6b6bf

File tree

3 files changed

+110
-4
lines changed

3 files changed

+110
-4
lines changed

crates/ty_ide/src/goto.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,6 @@ impl GotoTarget<'_> {
308308
}
309309
}
310310

311-
// TODO: Handle string literals that map to TypedDict fields
312311
_ => None,
313312
}
314313
}

crates/ty_wasm/src/lib.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use ruff_python_formatter::formatted_file;
1515
use ruff_source_file::{LineIndex, OneIndexed, SourceLocation};
1616
use ruff_text_size::{Ranged, TextSize};
1717
use ty_ide::{
18-
MarkupKind, NavigationTargets, RangedValue, goto_declaration, goto_definition, goto_references,
19-
goto_type_definition, hover, inlay_hints, signature_help,
18+
MarkupKind, NavigationTargets, RangedValue, document_highlights, goto_declaration,
19+
goto_definition, goto_references, goto_type_definition, hover, inlay_hints, signature_help,
2020
};
2121
use ty_project::metadata::options::Options;
2222
use ty_project::metadata::value::ValueSource;
@@ -528,6 +528,34 @@ impl Workspace {
528528
.and_then(|s| u32::try_from(s).ok()),
529529
}))
530530
}
531+
532+
#[wasm_bindgen(js_name = "documentHighlights")]
533+
pub fn document_highlights(
534+
&self,
535+
file_id: &FileHandle,
536+
position: Position,
537+
) -> Result<Vec<DocumentHighlight>, Error> {
538+
let source = source_text(&self.db, file_id.file);
539+
let index = line_index(&self.db, file_id.file);
540+
541+
let offset = position.to_text_size(&source, &index, self.position_encoding)?;
542+
543+
let Some(targets) = document_highlights(&self.db, file_id.file, offset) else {
544+
return Ok(Vec::new());
545+
};
546+
547+
Ok(targets
548+
.into_iter()
549+
.map(|target| DocumentHighlight {
550+
range: Range::from_file_range(
551+
&self.db,
552+
target.file_range(),
553+
self.position_encoding,
554+
),
555+
kind: target.kind().into(),
556+
})
557+
.collect())
558+
}
531559
}
532560

533561
pub(crate) fn into_error<E: std::fmt::Display>(err: E) -> Error {
@@ -954,6 +982,33 @@ pub struct ParameterInformation {
954982
pub documentation: Option<String>,
955983
}
956984

985+
#[wasm_bindgen]
986+
pub struct DocumentHighlight {
987+
#[wasm_bindgen(readonly)]
988+
pub range: Range,
989+
990+
#[wasm_bindgen(readonly)]
991+
pub kind: DocumentHighlightKind,
992+
}
993+
994+
#[wasm_bindgen]
995+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
996+
pub enum DocumentHighlightKind {
997+
Text = 1,
998+
Read = 2,
999+
Write = 3,
1000+
}
1001+
1002+
impl From<ty_ide::ReferenceKind> for DocumentHighlightKind {
1003+
fn from(kind: ty_ide::ReferenceKind) -> Self {
1004+
match kind {
1005+
ty_ide::ReferenceKind::Read => DocumentHighlightKind::Read,
1006+
ty_ide::ReferenceKind::Write => DocumentHighlightKind::Write,
1007+
ty_ide::ReferenceKind::Other => DocumentHighlightKind::Text,
1008+
}
1009+
}
1010+
}
1011+
9571012
#[wasm_bindgen]
9581013
impl SemanticToken {
9591014
pub fn kinds() -> Vec<String> {

playground/ty/src/Editor/Editor.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import {
2424
Severity,
2525
type Workspace,
2626
CompletionKind,
27+
DocumentHighlight,
28+
DocumentHighlightKind,
2729
} from "ty_wasm";
2830
import { FileId, ReadonlyFiles } from "../Playground";
2931
import { isPythonFile } from "./Files";
@@ -156,7 +158,8 @@ class PlaygroundServer
156158
languages.CompletionItemProvider,
157159
languages.DocumentSemanticTokensProvider,
158160
languages.DocumentRangeSemanticTokensProvider,
159-
languages.SignatureHelpProvider
161+
languages.SignatureHelpProvider,
162+
languages.DocumentHighlightProvider
160163
{
161164
private typeDefinitionProviderDisposable: IDisposable;
162165
private declarationProviderDisposable: IDisposable;
@@ -170,6 +173,7 @@ class PlaygroundServer
170173
private semanticTokensDisposable: IDisposable;
171174
private rangeSemanticTokensDisposable: IDisposable;
172175
private signatureHelpDisposable: IDisposable;
176+
private documentHighlightDisposable: IDisposable;
173177

174178
constructor(
175179
private monaco: Monaco,
@@ -207,6 +211,8 @@ class PlaygroundServer
207211
monaco.languages.registerDocumentFormattingEditProvider("python", this);
208212
this.signatureHelpDisposable =
209213
monaco.languages.registerSignatureHelpProvider("python", this);
214+
this.documentHighlightDisposable =
215+
monaco.languages.registerDocumentHighlightProvider("python", this);
210216
}
211217

212218
triggerCharacters: string[] = ["."];
@@ -365,6 +371,36 @@ class PlaygroundServer
365371
};
366372
}
367373

374+
provideDocumentHighlights(
375+
model: editor.ITextModel,
376+
position: Position,
377+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
378+
_token: CancellationToken,
379+
): languages.ProviderResult<languages.DocumentHighlight[]> {
380+
const workspace = this.props.workspace;
381+
const selectedFile = this.props.files.selected;
382+
383+
if (selectedFile == null) {
384+
return;
385+
}
386+
387+
const selectedHandle = this.props.files.handles[selectedFile];
388+
389+
if (selectedHandle == null) {
390+
return;
391+
}
392+
393+
const highlights = workspace.documentHighlights(
394+
selectedHandle,
395+
new TyPosition(position.lineNumber, position.column),
396+
);
397+
398+
return highlights.map((highlight: DocumentHighlight) => ({
399+
range: tyRangeToMonacoRange(highlight.range),
400+
kind: mapDocumentHighlightKind(highlight.kind),
401+
}));
402+
}
403+
368404
provideInlayHints(
369405
_model: editor.ITextModel,
370406
range: Range,
@@ -707,6 +743,7 @@ class PlaygroundServer
707743
this.semanticTokensDisposable.dispose();
708744
this.completionDisposable.dispose();
709745
this.signatureHelpDisposable.dispose();
746+
this.documentHighlightDisposable.dispose();
710747
}
711748
}
712749

@@ -836,3 +873,18 @@ function mapCompletionKind(kind: CompletionKind): CompletionItemKind {
836873
return CompletionItemKind.TypeParameter;
837874
}
838875
}
876+
877+
function mapDocumentHighlightKind(
878+
kind: DocumentHighlightKind,
879+
): languages.DocumentHighlightKind {
880+
switch (kind) {
881+
case DocumentHighlightKind.Text:
882+
return languages.DocumentHighlightKind.Text;
883+
case DocumentHighlightKind.Read:
884+
return languages.DocumentHighlightKind.Read;
885+
case DocumentHighlightKind.Write:
886+
return languages.DocumentHighlightKind.Write;
887+
default:
888+
return languages.DocumentHighlightKind.Text;
889+
}
890+
}

0 commit comments

Comments
 (0)