tinymist_query/
goto_definition.rs1use crate::prelude::*;
2
3#[derive(Debug, Clone)]
19pub struct GotoDefinitionRequest {
20 pub path: PathBuf,
22 pub position: LspPosition,
24}
25
26impl StatefulRequest for GotoDefinitionRequest {
27 type Response = GotoDefinitionResponse;
28
29 fn request(self, ctx: &mut LocalContext, graph: LspComputeGraph) -> Option<Self::Response> {
30 let doc = graph.snap.success_doc.as_ref();
31 let source = ctx.source_by_path(&self.path).ok()?;
32 let syntax = ctx.classify_for_decl(&source, self.position)?;
33 let origin_selection_range = ctx.to_lsp_range(syntax.node().range(), &source);
34
35 let def = ctx.def_of_syntax_or_dyn(&source, doc, syntax)?;
36
37 let fid = def.file_id()?;
38 let name_range = def.name_range(ctx.shared()).unwrap_or_default();
39 let full_range = def.full_range().unwrap_or_else(|| name_range.clone());
40
41 let res = Some(GotoDefinitionResponse::Link(vec![LocationLink {
42 origin_selection_range: Some(origin_selection_range),
43 target_uri: ctx.uri_for_id(fid).ok()?,
44 target_range: ctx.to_lsp_range_(full_range, fid)?,
45 target_selection_range: ctx.to_lsp_range_(name_range, fid)?,
46 }]));
47
48 crate::log_debug_ct!("goto_definition: {fid:?} {res:?}");
49 res
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::syntax::find_module_level_docs;
57 use crate::tests::*;
58
59 #[test]
60 fn test() {
61 snapshot_testing("goto_definition", &|ctx, path| {
62 let source = ctx.source_by_path(&path).unwrap();
63
64 let docs = find_module_level_docs(&source).unwrap_or_default();
65 let properties = get_test_properties(&docs);
66 let doc = compile_doc_for_test(ctx, &properties);
67
68 let request = GotoDefinitionRequest {
69 path: path.clone(),
70 position: find_test_position(&source),
71 };
72
73 let result = request.request(ctx, doc.clone());
74 assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
75 });
76 }
77}