Skip to main content

rust_analyzer_cli/lsp/
types.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Serialize, Deserialize)]
5pub struct DaemonStatusResponse {
6    pub ready: bool,
7    pub indexed_at: Option<String>,
8    pub workspace_root: String,
9    pub process_id: u32,
10}
11
12#[derive(Debug, Serialize, Deserialize)]
13pub struct SymbolQueryRequest {
14    pub name: String,
15    pub kind: String,
16    pub exact: bool,
17}
18
19#[derive(Debug, Serialize, Deserialize)]
20pub struct SymbolItem {
21    pub name: String,
22    pub kind: String,
23    pub file: String,
24    pub line: u32,
25    pub col: u32,
26    pub container_name: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub body: Option<String>,
29}
30
31#[derive(Debug, Serialize, Deserialize)]
32pub struct OutlineQueryRequest {
33    pub file: PathBuf,
34}
35
36#[derive(Debug, Serialize, Deserialize)]
37pub struct OutlineItem {
38    pub name: String,
39    pub kind: String,
40    pub detail: Option<String>,
41    pub line: u32,
42    pub col: u32,
43    pub end_line: u32,
44    pub children: Vec<OutlineItem>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub body: Option<String>,
47}
48
49#[derive(Debug, Serialize, Deserialize)]
50pub struct DefinitionQueryRequest {
51    pub file: PathBuf,
52    pub line: u32,
53    pub col: u32,
54}
55
56#[derive(Debug, Serialize, Deserialize)]
57pub struct DefinitionItem {
58    pub file: String,
59    pub line: u32,
60    pub col: u32,
61    pub end_line: u32,
62    pub end_col: u32,
63    pub snippet: Option<String>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub body: Option<String>,
66}
67
68
69#[derive(Debug, Serialize, Deserialize)]
70pub struct CursorQueryRequest {
71    pub file: PathBuf,
72    pub line: u32,
73    pub col: u32,
74    pub mode: String, // "incoming", "outgoing", "references"
75    pub depth: u32,
76}
77
78#[derive(Debug, Serialize, Deserialize)]
79pub struct CursorItem {
80    pub name: String,
81    pub kind: String,
82    pub file: String,
83    pub line: u32,
84    pub col: u32,
85    pub caller_or_callee: Option<String>,
86}
87
88#[derive(Debug, Serialize, Deserialize)]
89pub struct TypeHierarchyQueryRequest {
90    pub file: PathBuf,
91    pub line: u32,
92    pub col: u32,
93    pub mode: String, // "supertypes", "subtypes"
94    pub depth: u32,
95}
96
97#[derive(Debug, Serialize, Deserialize)]
98pub struct TypeHierarchyItemResult {
99    pub name: String,
100    pub kind: String,
101    pub file: String,
102    pub line: u32,
103    pub col: u32,
104    pub detail: Option<String>,
105}
106
107
108#[derive(Debug, Serialize, Deserialize)]
109pub struct BodyItem {
110    pub file: String,
111    pub line: u32,
112    pub col: u32,
113    pub end_line: u32,
114    pub end_col: u32,
115    pub body: String,
116    pub total_lines: usize,
117    pub is_truncated: bool,
118}
119
120#[derive(Debug, Serialize, Deserialize)]
121pub struct CheckQueryRequest {
122
123    pub target: Option<String>,
124}
125
126#[derive(Debug, Serialize, Deserialize)]
127pub struct CheckDiagnosticItem {
128    pub message: String,
129    pub level: String, // "error", "warning"
130    pub file: Option<String>,
131    pub line: Option<u32>,
132    pub col: Option<u32>,
133}
134
135#[derive(Debug, Serialize, Deserialize)]
136pub struct CheckResponse {
137    pub success: bool,
138    pub diagnostics: Vec<CheckDiagnosticItem>,
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_daemon_status_json_roundtrip() {
147        let status = DaemonStatusResponse {
148            ready: true,
149            indexed_at: Some("2026-07-31T10:00:00Z".to_string()),
150            workspace_root: "/path/to/workspace".to_string(),
151            process_id: 12345,
152        };
153        let json = serde_json::to_string(&status).unwrap();
154        let decoded: DaemonStatusResponse = serde_json::from_str(&json).unwrap();
155        assert!(decoded.ready);
156        assert_eq!(decoded.process_id, 12345);
157        assert_eq!(decoded.workspace_root, "/path/to/workspace");
158    }
159
160    #[test]
161    fn test_symbol_item_json_roundtrip() {
162        let item = SymbolItem {
163            name: "LspClient".to_string(),
164            kind: "struct".to_string(),
165            file: "src/lsp/client.rs".to_string(),
166            line: 15,
167            col: 1,
168            container_name: Some("lsp".to_string()),
169            body: None,
170        };
171
172        let json = serde_json::to_string(&item).unwrap();
173        let decoded: SymbolItem = serde_json::from_str(&json).unwrap();
174        assert_eq!(decoded.name, "LspClient");
175        assert_eq!(decoded.kind, "struct");
176    }
177}
178