tinymist_query/
goto_definition.rsuse crate::prelude::*;
#[derive(Debug, Clone)]
pub struct GotoDefinitionRequest {
pub path: PathBuf,
pub position: LspPosition,
}
impl StatefulRequest for GotoDefinitionRequest {
type Response = GotoDefinitionResponse;
fn request(self, ctx: &mut LocalContext, graph: LspComputeGraph) -> Option<Self::Response> {
let doc = graph.snap.success_doc.as_ref();
let source = ctx.source_by_path(&self.path).ok()?;
let syntax = ctx.classify_for_decl(&source, self.position)?;
let origin_selection_range = ctx.to_lsp_range(syntax.node().range(), &source);
let def = ctx.def_of_syntax(&source, doc, syntax)?;
let fid = def.file_id()?;
let name_range = def.name_range(ctx.shared()).unwrap_or_default();
let full_range = def.full_range().unwrap_or_else(|| name_range.clone());
let res = Some(GotoDefinitionResponse::Link(vec![LocationLink {
origin_selection_range: Some(origin_selection_range),
target_uri: ctx.uri_for_id(fid).ok()?,
target_range: ctx.to_lsp_range_(full_range, fid)?,
target_selection_range: ctx.to_lsp_range_(name_range, fid)?,
}]));
crate::log_debug_ct!("goto_definition: {fid:?} {res:?}");
res
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::syntax::find_module_level_docs;
use crate::tests::*;
#[test]
fn test() {
snapshot_testing("goto_definition", &|ctx, path| {
let source = ctx.source_by_path(&path).unwrap();
let docs = find_module_level_docs(&source).unwrap_or_default();
let properties = get_test_properties(&docs);
let doc = compile_doc_for_test(ctx, &properties);
let request = GotoDefinitionRequest {
path: path.clone(),
position: find_test_position(&source),
};
let result = request.request(ctx, doc.clone());
assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
});
}
}