use anyhow::Result;
use lsp_types::{
InitializeParams, InitializeResult, ServerCapabilities, TextDocumentIdentifier, Uri,
};
use ropey::Rope;
use crate::App;
pub trait LspClient {
fn server_capabilities(&self) -> &ServerCapabilities;
fn initialize(
&self,
params: InitializeParams,
cx: &mut App,
) -> crate::Task<Result<InitializeResult>>;
fn shutdown(&self, cx: &mut App) -> crate::Task<Result<()>>;
fn completions(
&self,
params: lsp_types::CompletionParams,
cx: &mut App,
) -> crate::Task<Result<lsp_types::CompletionResponse>>;
fn hover(
&self,
params: lsp_types::HoverParams,
cx: &mut App,
) -> crate::Task<Result<Option<lsp_types::Hover>>>;
fn definition(
&self,
params: lsp_types::GotoDefinitionParams,
cx: &mut App,
) -> crate::Task<Result<lsp_types::GotoDefinitionResponse>>;
fn references(
&self,
params: lsp_types::ReferenceParams,
cx: &mut App,
) -> crate::Task<Result<Vec<lsp_types::Location>>>;
fn diagnostics(
&self,
params: lsp_types::DocumentDiagnosticParams,
cx: &mut App,
) -> crate::Task<Result<lsp_types::DocumentDiagnosticReport>>;
fn semantic_tokens_full(
&self,
params: lsp_types::SemanticTokensParams,
cx: &mut App,
) -> crate::Task<Result<Option<lsp_types::SemanticTokensResult>>>;
fn semantic_tokens_range(
&self,
params: lsp_types::SemanticTokensRangeParams,
cx: &mut App,
) -> crate::Task<Result<Option<lsp_types::SemanticTokensRangeResult>>>;
fn code_actions(
&self,
params: lsp_types::CodeActionParams,
cx: &mut App,
) -> crate::Task<Result<Vec<lsp_types::CodeActionOrCommand>>>;
fn formatting(
&self,
params: lsp_types::DocumentFormattingParams,
cx: &mut App,
) -> crate::Task<Result<Vec<lsp_types::TextEdit>>>;
fn rename(
&self,
params: lsp_types::RenameParams,
cx: &mut App,
) -> crate::Task<Result<Option<lsp_types::WorkspaceEdit>>>;
fn document_highlights(
&self,
params: lsp_types::DocumentHighlightParams,
cx: &mut App,
) -> crate::Task<Result<Vec<lsp_types::DocumentHighlight>>>;
fn signature_help(
&self,
params: lsp_types::SignatureHelpParams,
cx: &mut App,
) -> crate::Task<Result<Option<lsp_types::SignatureHelp>>>;
fn did_change(
&self,
identifier: TextDocumentIdentifier,
changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
cx: &mut App,
);
fn did_open(
&self,
identifier: TextDocumentIdentifier,
language_id: &str,
text: &str,
cx: &mut App,
);
fn did_close(&self, identifier: TextDocumentIdentifier, cx: &mut App);
fn did_save(&self, identifier: TextDocumentIdentifier, text: Option<String>, cx: &mut App);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LspState {
Disconnected,
Initializing,
Connected,
ShuttingDown,
Error,
}
#[derive(Debug, Clone)]
pub struct DocumentVersion {
pub uri: Uri,
pub version: i32,
}
impl DocumentVersion {
pub fn new(uri: Uri) -> Self {
Self { uri, version: 0 }
}
pub fn increment(&mut self) -> i32 {
self.version += 1;
self.version
}
}
pub struct PositionMapping;
impl PositionMapping {
pub fn offset_to_position(text: &Rope, offset: usize) -> lsp_types::Position {
use ropey::LineType;
let line = text.byte_to_line_idx(offset, LineType::LF);
let line_start = text.line_to_byte_idx(line, LineType::LF);
let column = offset - line_start;
lsp_types::Position::new(line as u32, column as u32)
}
pub fn position_to_offset(text: &Rope, position: lsp_types::Position) -> usize {
use ropey::LineType;
let line = position.line as usize;
let last_line = text.len_lines(LineType::LF).saturating_sub(1);
let line = line.min(last_line);
let line_start = text.line_to_byte_idx(line, LineType::LF);
let column = position.character as usize;
(line_start + column).min(text.len())
}
}