pytest_language_server/providers/
document_symbol.rs1use super::Backend;
7use tower_lsp_server::jsonrpc::Result;
8use tower_lsp_server::ls_types::*;
9use tracing::info;
10
11impl Backend {
12 pub async fn handle_document_symbol(
17 &self,
18 params: DocumentSymbolParams,
19 ) -> Result<Option<DocumentSymbolResponse>> {
20 let uri = params.text_document.uri;
21
22 info!("document_symbol request: uri={:?}", uri);
23
24 let Some(file_path) = self.uri_to_path(&uri) else {
25 return Ok(None);
26 };
27
28 let mut symbols: Vec<DocumentSymbol> = Vec::new();
30
31 for entry in self.fixture_db.definitions.iter() {
33 for definition in entry.value() {
34 if definition.file_path != file_path {
36 continue;
37 }
38
39 if definition.is_third_party {
41 continue;
42 }
43
44 let line = Self::internal_line_to_lsp(definition.line);
45 let start_char = definition.start_char as u32;
46 let end_char = definition.end_char as u32;
47
48 let selection_range = Self::create_range(line, start_char, line, end_char);
50
51 let end_line = Self::internal_line_to_lsp(definition.end_line);
53 let range = Self::create_range(line, 0, end_line, 0);
54
55 let detail = definition
57 .return_type
58 .as_ref()
59 .map(|rt| format!("-> {}", rt));
60
61 #[allow(deprecated)] let symbol = DocumentSymbol {
63 name: definition.name.clone(),
64 detail,
65 kind: SymbolKind::FUNCTION,
66 tags: None,
67 deprecated: None,
68 range,
69 selection_range,
70 children: None,
71 };
72
73 symbols.push(symbol);
74 }
75 }
76
77 symbols.sort_by_key(|s| s.range.start.line);
79
80 info!(
81 "Returning {} document symbols for {:?}",
82 symbols.len(),
83 file_path
84 );
85
86 if symbols.is_empty() {
87 Ok(None)
88 } else {
89 Ok(Some(DocumentSymbolResponse::Nested(symbols)))
90 }
91 }
92}