use serde::{Deserialize, Serialize};
pub use lsp_types::{
CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, Diagnostic,
DiagnosticSeverity, DocumentSymbol, DocumentSymbolResponse, GotoDefinitionResponse, Hover,
HoverContents, Location, MarkedString, MarkupContent, MarkupKind, Position, Range,
SymbolInformation, SymbolKind, TextDocumentIdentifier, TextDocumentPositionParams, Uri,
WorkspaceSymbolResponse,
};
pub use url::Url;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LspStatus {
pub id: String,
pub name: String,
pub root: String,
pub status: LspConnectionStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LspConnectionStatus {
Connected,
Error,
Starting,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LspResult {
Locations(Vec<Location>),
Hover(Option<Hover>),
DocumentSymbols(DocumentSymbolResponse),
WorkspaceSymbols(WorkspaceSymbolResponse),
CallHierarchyItems(Vec<CallHierarchyItem>),
IncomingCalls(Vec<CallHierarchyIncomingCall>),
OutgoingCalls(Vec<CallHierarchyOutgoingCall>),
Diagnostics(Vec<Diagnostic>),
Empty,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum LspOperation {
GoToDefinition,
FindReferences,
Hover,
DocumentSymbol,
WorkspaceSymbol,
GoToImplementation,
PrepareCallHierarchy,
IncomingCalls,
OutgoingCalls,
}
impl std::fmt::Display for LspOperation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LspOperation::GoToDefinition => write!(f, "goToDefinition"),
LspOperation::FindReferences => write!(f, "findReferences"),
LspOperation::Hover => write!(f, "hover"),
LspOperation::DocumentSymbol => write!(f, "documentSymbol"),
LspOperation::WorkspaceSymbol => write!(f, "workspaceSymbol"),
LspOperation::GoToImplementation => write!(f, "goToImplementation"),
LspOperation::PrepareCallHierarchy => write!(f, "prepareCallHierarchy"),
LspOperation::IncomingCalls => write!(f, "incomingCalls"),
LspOperation::OutgoingCalls => write!(f, "outgoingCalls"),
}
}
}
impl std::str::FromStr for LspOperation {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"goToDefinition" => Ok(LspOperation::GoToDefinition),
"findReferences" => Ok(LspOperation::FindReferences),
"hover" => Ok(LspOperation::Hover),
"documentSymbol" => Ok(LspOperation::DocumentSymbol),
"workspaceSymbol" => Ok(LspOperation::WorkspaceSymbol),
"goToImplementation" => Ok(LspOperation::GoToImplementation),
"prepareCallHierarchy" => Ok(LspOperation::PrepareCallHierarchy),
"incomingCalls" => Ok(LspOperation::IncomingCalls),
"outgoingCalls" => Ok(LspOperation::OutgoingCalls),
_ => Err(format!("Unknown LSP operation: {}", s)),
}
}
}
pub const IMPORTANT_SYMBOL_KINDS: &[SymbolKind] = &[
SymbolKind::CLASS,
SymbolKind::FUNCTION,
SymbolKind::METHOD,
SymbolKind::INTERFACE,
SymbolKind::VARIABLE,
SymbolKind::CONSTANT,
SymbolKind::STRUCT,
SymbolKind::ENUM,
];
pub fn format_diagnostic(diagnostic: &Diagnostic) -> String {
let severity = match diagnostic.severity {
Some(DiagnosticSeverity::ERROR) => "ERROR",
Some(DiagnosticSeverity::WARNING) => "WARN",
Some(DiagnosticSeverity::INFORMATION) => "INFO",
Some(DiagnosticSeverity::HINT) => "HINT",
None => "UNKNOWN",
_ => "UNKNOWN",
};
let line = diagnostic.range.start.line + 1;
let col = diagnostic.range.start.character + 1;
format!("{} [{}:{}] {}", severity, line, col, diagnostic.message)
}