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, 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, 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, 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