Skip to main content

mcpls_core/bridge/translator/
dto.rs

1//! Public MCP-facing result/data-transfer types returned by the tool-call
2//! handlers in the sibling domain modules.
3
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7/// Position in a document (1-based for MCP).
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
9pub struct Position2D {
10    /// Line number (1-based).
11    pub line: u32,
12    /// Character offset (1-based).
13    pub character: u32,
14}
15
16/// A 1-based MCP position taken as input by `Translator::handle_*` methods.
17///
18/// Kept distinct from [`Position2D`] (which carries an *output* position back
19/// to the caller) so passing a position into a handler always goes through a
20/// named-field struct literal (`Position { line, character }`) instead of two
21/// adjacent bare `u32` arguments -- a call site that swaps `line` and
22/// `character` no longer compiles instead of silently sending a wrong
23/// position to the LSP server (#322).
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub struct Position {
26    /// Line number (1-based).
27    pub line: u32,
28    /// Character offset (1-based).
29    pub character: u32,
30}
31
32/// Range in a document (1-based for MCP).
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
34pub struct Range {
35    /// Start position.
36    pub start: Position2D,
37    /// End position.
38    pub end: Position2D,
39}
40
41/// Location in a document.
42#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
43pub struct Location {
44    /// URI of the document.
45    pub uri: String,
46    /// Range within the document.
47    pub range: Range,
48}
49
50/// Result of a hover request.
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct HoverResult {
53    /// Hover contents as markdown string.
54    pub contents: String,
55    /// Optional range the hover applies to.
56    pub range: Option<Range>,
57}
58
59/// Result of a definition request.
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61pub struct DefinitionResult {
62    /// Locations of the definition.
63    pub locations: Vec<Location>,
64}
65
66/// Result of a references request.
67#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
68pub struct ReferencesResult {
69    /// Locations of all references.
70    pub locations: Vec<Location>,
71}
72
73/// Diagnostic severity.
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
75#[serde(rename_all = "lowercase")]
76pub enum DiagnosticSeverity {
77    /// Error diagnostic.
78    Error,
79    /// Warning diagnostic.
80    Warning,
81    /// Informational diagnostic.
82    Information,
83    /// Hint diagnostic.
84    Hint,
85}
86
87/// A single diagnostic.
88#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
89pub struct Diagnostic {
90    /// Range where the diagnostic applies.
91    pub range: Range,
92    /// Severity of the diagnostic.
93    pub severity: DiagnosticSeverity,
94    /// Diagnostic message.
95    pub message: String,
96    /// Optional diagnostic code.
97    pub code: Option<String>,
98}
99
100/// Result of a diagnostics request.
101#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
102pub struct DiagnosticsResult {
103    /// List of diagnostics for the document.
104    pub diagnostics: Vec<Diagnostic>,
105}
106
107/// A text edit operation.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct TextEdit {
110    /// Range to replace.
111    pub range: Range,
112    /// New text.
113    pub new_text: String,
114}
115
116/// Changes to a document.
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct DocumentChanges {
119    /// URI of the document.
120    pub uri: String,
121    /// List of edits to apply.
122    pub edits: Vec<TextEdit>,
123}
124
125/// Result of a rename request.
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct RenameResult {
128    /// Changes to apply across documents.
129    pub changes: Vec<DocumentChanges>,
130}
131
132/// A completion item.
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct Completion {
135    /// Label of the completion.
136    pub label: String,
137    /// Kind of completion.
138    pub kind: Option<String>,
139    /// Detail information.
140    pub detail: Option<String>,
141    /// Documentation.
142    pub documentation: Option<String>,
143}
144
145/// Result of a completions request.
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct CompletionsResult {
148    /// List of completion items.
149    pub items: Vec<Completion>,
150}
151
152/// A document symbol.
153#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
154pub struct Symbol {
155    /// Name of the symbol.
156    pub name: String,
157    /// Kind of symbol.
158    pub kind: String,
159    /// Range of the symbol.
160    pub range: Range,
161    /// Selection range (identifier location).
162    pub selection_range: Range,
163    /// Child symbols.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub children: Option<Vec<Self>>,
166}
167
168/// Result of a document symbols request.
169#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
170pub struct DocumentSymbolsResult {
171    /// List of symbols in the document.
172    pub symbols: Vec<Symbol>,
173}
174
175/// Result of a format document request.
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct FormatDocumentResult {
178    /// List of edits to format the document.
179    pub edits: Vec<TextEdit>,
180}
181
182/// A workspace symbol.
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct WorkspaceSymbol {
185    /// Name of the symbol.
186    pub name: String,
187    /// Kind of symbol.
188    pub kind: String,
189    /// Location of the symbol.
190    pub location: Location,
191    /// Optional container name (parent scope).
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub container_name: Option<String>,
194}
195
196/// Result of workspace symbol search.
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct WorkspaceSymbolResult {
199    /// List of symbols found.
200    pub symbols: Vec<WorkspaceSymbol>,
201}
202
203/// A single code action.
204#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct CodeAction {
206    /// Title of the code action.
207    pub title: String,
208    /// Kind of code action (quickfix, refactor, etc.).
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub kind: Option<String>,
211    /// Diagnostics that this action resolves.
212    #[serde(skip_serializing_if = "Vec::is_empty", default)]
213    pub diagnostics: Vec<Diagnostic>,
214    /// Workspace edit to apply.
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub edit: Option<WorkspaceEditDescription>,
217    /// Command to execute.
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub command: Option<CommandDescription>,
220    /// Whether this is the preferred action.
221    #[serde(default)]
222    pub is_preferred: bool,
223}
224
225/// Description of a workspace edit.
226#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct WorkspaceEditDescription {
228    /// Changes to apply to documents.
229    pub changes: Vec<DocumentChanges>,
230}
231
232/// Description of a command.
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct CommandDescription {
235    /// Title of the command.
236    pub title: String,
237    /// Command identifier.
238    pub command: String,
239    /// Command arguments.
240    #[serde(skip_serializing_if = "Vec::is_empty", default)]
241    pub arguments: Vec<serde_json::Value>,
242}
243
244/// Result of code actions request.
245#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct CodeActionsResult {
247    /// Available code actions.
248    pub actions: Vec<CodeAction>,
249}
250
251/// A call hierarchy item.
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct CallHierarchyItemResult {
254    /// Name of the symbol.
255    pub name: String,
256    /// LSP numeric symbol kind (e.g. 12 for Function).
257    pub kind: u32,
258    /// More detail for this item.
259    #[serde(skip_serializing_if = "Option::is_none")]
260    pub detail: Option<String>,
261    /// URI of the document.
262    pub uri: String,
263    /// Range of the symbol.
264    pub range: Range,
265    /// Selection range (identifier location).
266    ///
267    /// Serialized as `selectionRange` (camelCase) so that the value returned by
268    /// `prepare_call_hierarchy` round-trips correctly when the MCP client passes
269    /// it back to `get_incoming_calls` / `get_outgoing_calls`, which deserialize
270    /// it as `lsp_types::CallHierarchyItem` (camelCase).
271    #[serde(rename = "selectionRange")]
272    pub selection_range: Range,
273    /// Opaque data to pass to incoming/outgoing calls.
274    #[serde(skip_serializing_if = "Option::is_none")]
275    pub data: Option<serde_json::Value>,
276}
277
278/// Result of call hierarchy prepare request.
279#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct CallHierarchyPrepareResult {
281    /// List of callable items at the position.
282    pub items: Vec<CallHierarchyItemResult>,
283}
284
285/// An incoming call (caller of the current item).
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct IncomingCall {
288    /// The item that calls the current item.
289    pub from: CallHierarchyItemResult,
290    /// Ranges where the call occurs.
291    pub from_ranges: Vec<Range>,
292}
293
294/// Result of incoming calls request.
295#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct IncomingCallsResult {
297    /// List of incoming calls.
298    pub calls: Vec<IncomingCall>,
299}
300
301/// An outgoing call (callee from the current item).
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct OutgoingCall {
304    /// The item being called.
305    pub to: CallHierarchyItemResult,
306    /// Ranges where the call occurs.
307    pub from_ranges: Vec<Range>,
308}
309
310/// Result of outgoing calls request.
311#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct OutgoingCallsResult {
313    /// List of outgoing calls.
314    pub calls: Vec<OutgoingCall>,
315}
316
317/// Result of server logs request.
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ServerLogsResult {
320    /// List of log entries.
321    pub logs: Vec<crate::bridge::notifications::LogEntry>,
322}
323
324/// Result of server messages request.
325#[derive(Debug, Clone, Serialize, Deserialize)]
326pub struct ServerMessagesResult {
327    /// List of server messages.
328    pub messages: Vec<crate::bridge::notifications::ServerMessage>,
329}
330
331/// A single parameter in a signature.
332#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct SignatureParameter {
334    /// Label of the parameter.
335    pub label: String,
336    /// Optional documentation for the parameter.
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub documentation: Option<String>,
339}
340
341/// A single signature overload.
342#[derive(Debug, Clone, Serialize, Deserialize)]
343pub struct SignatureInfo {
344    /// Full label of the signature.
345    pub label: String,
346    /// Optional documentation for the signature.
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub documentation: Option<String>,
349    /// Parameters of the signature.
350    pub parameters: Vec<SignatureParameter>,
351}
352
353/// Result of a signature help request.
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct SignatureHelpResult {
356    /// Available signatures.
357    pub signatures: Vec<SignatureInfo>,
358    /// Index of the active signature.
359    #[serde(skip_serializing_if = "Option::is_none")]
360    pub active_signature: Option<u32>,
361    /// Index of the active parameter within the active signature.
362    #[serde(skip_serializing_if = "Option::is_none")]
363    pub active_parameter: Option<u32>,
364}
365
366/// Result of a go-to-implementation or go-to-type-definition request.
367#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct LocationsResult {
369    /// Locations found.
370    pub locations: Vec<Location>,
371}
372
373/// A single inlay hint entry.
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct InlayHintEntry {
376    /// Position of the hint (1-based MCP).
377    pub position: Position2D,
378    /// Label text for the hint.
379    pub label: String,
380    /// Hint kind (1 = Type, 2 = Parameter).
381    #[serde(skip_serializing_if = "Option::is_none")]
382    pub kind: Option<u8>,
383    /// Whether to add a space before the hint.
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub padding_left: Option<bool>,
386    /// Whether to add a space after the hint.
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub padding_right: Option<bool>,
389    /// Tooltip text.
390    #[serde(skip_serializing_if = "Option::is_none")]
391    pub tooltip: Option<String>,
392}
393
394/// Result of an inlay hints request.
395#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct InlayHintsResult {
397    /// List of inlay hints.
398    pub hints: Vec<InlayHintEntry>,
399}