use ecow::EcoString;
use lsp_types::InsertTextFormat;
use serde::{Deserialize, Serialize};
use crate::StrRef;
use super::LspRange;
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum CompletionKind {
Syntax,
Func,
Type,
Param,
Field,
#[default]
Constant,
Reference,
Symbol(EcoString),
Variable,
Module,
File,
Folder,
}
impl From<&CompletionKind> for lsp_types::CompletionItemKind {
fn from(value: &CompletionKind) -> Self {
match value {
CompletionKind::Syntax => Self::SNIPPET,
CompletionKind::Func => Self::FUNCTION,
CompletionKind::Param => Self::VARIABLE,
CompletionKind::Field => Self::FIELD,
CompletionKind::Variable => Self::VARIABLE,
CompletionKind::Constant => Self::CONSTANT,
CompletionKind::Reference => Self::REFERENCE,
CompletionKind::Symbol(_) => Self::FIELD,
CompletionKind::Type => Self::CLASS,
CompletionKind::Module => Self::MODULE,
CompletionKind::File => Self::FILE,
CompletionKind::Folder => Self::FOLDER,
}
}
}
impl serde::Serialize for CompletionKind {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
<&Self as Into<lsp_types::CompletionItemKind>>::into(self).serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for CompletionKind {
fn deserialize<D>(deserializer: D) -> Result<CompletionKind, D::Error>
where
D: serde::Deserializer<'de>,
{
let kind = lsp_types::CompletionItemKind::deserialize(deserializer)?;
Ok(match kind {
lsp_types::CompletionItemKind::SNIPPET => CompletionKind::Syntax,
lsp_types::CompletionItemKind::FUNCTION => CompletionKind::Func,
lsp_types::CompletionItemKind::VARIABLE => CompletionKind::Param,
lsp_types::CompletionItemKind::FIELD => CompletionKind::Field,
lsp_types::CompletionItemKind::CONSTANT => CompletionKind::Constant,
lsp_types::CompletionItemKind::REFERENCE => CompletionKind::Reference,
lsp_types::CompletionItemKind::CLASS => CompletionKind::Type,
lsp_types::CompletionItemKind::MODULE => CompletionKind::Module,
lsp_types::CompletionItemKind::FILE => CompletionKind::File,
lsp_types::CompletionItemKind::FOLDER => CompletionKind::Folder,
_ => CompletionKind::Variable,
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Completion {
pub kind: CompletionKind,
pub label: EcoString,
pub label_details: Option<EcoString>,
pub sort_text: Option<EcoString>,
pub filter_text: Option<EcoString>,
pub apply: Option<EcoString>,
pub detail: Option<EcoString>,
pub additional_text_edits: Option<Vec<EcoTextEdit>>,
pub command: Option<LspCompletionCommand>,
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionList {
pub is_incomplete: bool,
pub items: Vec<CompletionItem>,
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CompletionItemLabelDetails {
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<EcoString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<EcoString>,
}
impl From<EcoString> for CompletionItemLabelDetails {
fn from(description: EcoString) -> Self {
Self {
detail: None,
description: Some(description),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EcoTextEdit {
pub range: LspRange,
pub new_text: EcoString,
}
impl EcoTextEdit {
pub fn new(range: LspRange, new_text: EcoString) -> EcoTextEdit {
EcoTextEdit { range, new_text }
}
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CompletionItem {
pub label: EcoString,
#[serde(skip_serializing_if = "Option::is_none")]
pub label_details: Option<CompletionItemLabelDetails>,
pub kind: CompletionKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<EcoString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_text: Option<EcoString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_text: Option<EcoString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub insert_text: Option<EcoString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub insert_text_format: Option<InsertTextFormat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text_edit: Option<EcoTextEdit>,
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_text_edits: Option<Vec<EcoTextEdit>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<LspCompletionCommand>,
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct LspCompletionCommand {
pub title: EcoString,
pub command: StrRef,
}
impl From<StrRef> for LspCompletionCommand {
fn from(command: StrRef) -> Self {
Self {
title: EcoString::default(),
command,
}
}
}