1use serde::{Deserialize, Serialize};
7
8pub 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#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct LspStatus {
21 pub id: String,
23 pub name: String,
25 pub root: String,
27 pub status: LspConnectionStatus,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(rename_all = "lowercase")]
34pub enum LspConnectionStatus {
35 Connected,
37 Error,
39 Starting,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(untagged)]
46pub enum LspResult {
47 Locations(Vec<Location>),
49 Hover(Option<Hover>),
51 DocumentSymbols(DocumentSymbolResponse),
53 WorkspaceSymbols(WorkspaceSymbolResponse),
55 CallHierarchyItems(Vec<CallHierarchyItem>),
57 IncomingCalls(Vec<CallHierarchyIncomingCall>),
59 OutgoingCalls(Vec<CallHierarchyOutgoingCall>),
61 Diagnostics(Vec<Diagnostic>),
63 Empty,
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
69#[serde(rename_all = "camelCase")]
70pub enum LspOperation {
71 GoToDefinition,
73 FindReferences,
75 Hover,
77 DocumentSymbol,
79 WorkspaceSymbol,
81 GoToImplementation,
83 PrepareCallHierarchy,
85 IncomingCalls,
87 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
126pub 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
138pub 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}