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 SemanticRequest for GotoDefinitionRequest {
27 type Response = GotoDefinitionResponse;
28
29 fn request(self, ctx: &mut LocalContext) -> Option<Self::Response> {
30 let source = ctx.source_by_path(&self.path).ok()?;
31 let syntax = ctx.classify_for_decl(&source, self.position)?;
32 let origin_selection_range = ctx.to_lsp_range(syntax.node().range(), &source);
33
34 let def = ctx.def_of_syntax_or_dyn(&source, syntax)?;
35
36 let fid = def.file_id()?;
37 let name_range = def.name_range(ctx.shared()).unwrap_or_default();
38 let full_range = def.full_range().unwrap_or_else(|| name_range.clone());
39
40 let res = Some(GotoDefinitionResponse::Link(vec![LocationLink {
41 origin_selection_range: Some(origin_selection_range),
42 target_uri: ctx.uri_for_id(fid).ok()?,
43 target_range: ctx.to_lsp_range_(full_range, fid)?,
44 target_selection_range: ctx.to_lsp_range_(name_range, fid)?,
45 }]));
46
47 crate::log_debug_ct!("goto_definition: {fid:?} {res:?}");
48 res
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::tests::*;
56
57 #[test]
58 fn test() {
59 snapshot_testing("goto_definition", &|ctx, path| {
60 let source = ctx.source_by_path(&path).unwrap();
61
62 let request = GotoDefinitionRequest {
63 path: path.clone(),
64 position: find_test_position(&source),
65 };
66
67 let result = request.request(ctx);
68 assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
69 });
70 }
71}