codive_lsp/
types.rs

1//! LSP types and re-exports
2//!
3//! This module provides type definitions used throughout the LSP integration,
4//! re-exporting common types from `lsp-types` for convenience.
5
6use serde::{Deserialize, Serialize};
7
8// Re-export commonly used LSP types
9pub use lsp_types::{
10    CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, Diagnostic,
11    DiagnosticSeverity, DocumentSymbol, DocumentSymbolResponse, GotoDefinitionResponse, Hover,
12    HoverContents, Location, MarkedString, MarkupContent, MarkupKind, Position, Range,
13    SymbolInformation, SymbolKind, TextDocumentIdentifier, TextDocumentPositionParams, Uri,
14    WorkspaceSymbolResponse,
15};
16pub use url::Url;
17
18/// Status of an LSP server connection
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct LspStatus {
21    /// Server ID (e.g., "rust-analyzer", "typescript")
22    pub id: String,
23    /// Human-readable name
24    pub name: String,
25    /// Project root this server is handling
26    pub root: String,
27    /// Connection status
28    pub status: LspConnectionStatus,
29}
30
31/// Connection status for an LSP server
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(rename_all = "lowercase")]
34pub enum LspConnectionStatus {
35    /// Server is connected and ready
36    Connected,
37    /// Server failed to initialize
38    Error,
39    /// Server is starting up
40    Starting,
41}
42
43/// Result from an LSP operation
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(untagged)]
46pub enum LspResult {
47    /// Definition/reference locations
48    Locations(Vec<Location>),
49    /// Hover information
50    Hover(Option<Hover>),
51    /// Document symbols (flat or hierarchical)
52    DocumentSymbols(DocumentSymbolResponse),
53    /// Workspace symbols
54    WorkspaceSymbols(WorkspaceSymbolResponse),
55    /// Call hierarchy items
56    CallHierarchyItems(Vec<CallHierarchyItem>),
57    /// Incoming calls
58    IncomingCalls(Vec<CallHierarchyIncomingCall>),
59    /// Outgoing calls
60    OutgoingCalls(Vec<CallHierarchyOutgoingCall>),
61    /// Diagnostics
62    Diagnostics(Vec<Diagnostic>),
63    /// Empty result
64    Empty,
65}
66
67/// LSP operation types
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
69#[serde(rename_all = "camelCase")]
70pub enum LspOperation {
71    /// textDocument/definition
72    GoToDefinition,
73    /// textDocument/references
74    FindReferences,
75    /// textDocument/hover
76    Hover,
77    /// textDocument/documentSymbol
78    DocumentSymbol,
79    /// workspace/symbol
80    WorkspaceSymbol,
81    /// textDocument/implementation
82    GoToImplementation,
83    /// textDocument/prepareCallHierarchy
84    PrepareCallHierarchy,
85    /// callHierarchy/incomingCalls
86    IncomingCalls,
87    /// callHierarchy/outgoingCalls
88    OutgoingCalls,
89}
90
91impl std::fmt::Display for LspOperation {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        match self {
94            LspOperation::GoToDefinition => write!(f, "goToDefinition"),
95            LspOperation::FindReferences => write!(f, "findReferences"),
96            LspOperation::Hover => write!(f, "hover"),
97            LspOperation::DocumentSymbol => write!(f, "documentSymbol"),
98            LspOperation::WorkspaceSymbol => write!(f, "workspaceSymbol"),
99            LspOperation::GoToImplementation => write!(f, "goToImplementation"),
100            LspOperation::PrepareCallHierarchy => write!(f, "prepareCallHierarchy"),
101            LspOperation::IncomingCalls => write!(f, "incomingCalls"),
102            LspOperation::OutgoingCalls => write!(f, "outgoingCalls"),
103        }
104    }
105}
106
107impl std::str::FromStr for LspOperation {
108    type Err = String;
109
110    fn from_str(s: &str) -> Result<Self, Self::Err> {
111        match s {
112            "goToDefinition" => Ok(LspOperation::GoToDefinition),
113            "findReferences" => Ok(LspOperation::FindReferences),
114            "hover" => Ok(LspOperation::Hover),
115            "documentSymbol" => Ok(LspOperation::DocumentSymbol),
116            "workspaceSymbol" => Ok(LspOperation::WorkspaceSymbol),
117            "goToImplementation" => Ok(LspOperation::GoToImplementation),
118            "prepareCallHierarchy" => Ok(LspOperation::PrepareCallHierarchy),
119            "incomingCalls" => Ok(LspOperation::IncomingCalls),
120            "outgoingCalls" => Ok(LspOperation::OutgoingCalls),
121            _ => Err(format!("Unknown LSP operation: {}", s)),
122        }
123    }
124}
125
126/// Symbol kinds that are typically most useful for navigation
127pub const IMPORTANT_SYMBOL_KINDS: &[SymbolKind] = &[
128    SymbolKind::CLASS,
129    SymbolKind::FUNCTION,
130    SymbolKind::METHOD,
131    SymbolKind::INTERFACE,
132    SymbolKind::VARIABLE,
133    SymbolKind::CONSTANT,
134    SymbolKind::STRUCT,
135    SymbolKind::ENUM,
136];
137
138/// Format a diagnostic for display
139pub fn format_diagnostic(diagnostic: &Diagnostic) -> String {
140    let severity = match diagnostic.severity {
141        Some(DiagnosticSeverity::ERROR) => "ERROR",
142        Some(DiagnosticSeverity::WARNING) => "WARN",
143        Some(DiagnosticSeverity::INFORMATION) => "INFO",
144        Some(DiagnosticSeverity::HINT) => "HINT",
145        None => "UNKNOWN",
146        _ => "UNKNOWN",
147    };
148
149    let line = diagnostic.range.start.line + 1;
150    let col = diagnostic.range.start.character + 1;
151
152    format!("{} [{}:{}] {}", severity, line, col, diagnostic.message)
153}