use crate::{
Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier,
WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit,
};
use serde::{Deserialize, Serialize};
#[cfg(feature = "proposed")]
use serde_json::Value;
use std::borrow::Cow;
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CodeActionProviderCapability {
Simple(bool),
Options(CodeActionOptions),
}
impl From<CodeActionOptions> for CodeActionProviderCapability {
fn from(from: CodeActionOptions) -> Self {
Self::Options(from)
}
}
impl From<bool> for CodeActionProviderCapability {
fn from(from: bool) -> Self {
Self::Simple(from)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionCapability {
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action_literal_support: Option<CodeActionLiteralSupport>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_preferred_support: Option<bool>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_support: Option<bool>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub data_support: Option<bool>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub resolve_support: Option<CodeActionCapabilityResolveSupport>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub honors_change_annotations: Option<bool>,
}
#[cfg(feature = "proposed")]
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionCapabilityResolveSupport {
pub properties: Vec<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionLiteralSupport {
pub code_action_kind: CodeActionKindLiteralSupport,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionKindLiteralSupport {
pub value_set: Vec<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionParams {
pub text_document: TextDocumentIdentifier,
pub range: Range,
pub context: CodeActionContext,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
pub type CodeActionResponse = Vec<CodeActionOrCommand>;
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CodeActionOrCommand {
Command(Command),
CodeAction(CodeAction),
}
impl From<Command> for CodeActionOrCommand {
fn from(comand: Command) -> Self {
CodeActionOrCommand::Command(comand)
}
}
impl From<CodeAction> for CodeActionOrCommand {
fn from(action: CodeAction) -> Self {
CodeActionOrCommand::CodeAction(action)
}
}
#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
pub struct CodeActionKind(Cow<'static, str>);
impl CodeActionKind {
pub const EMPTY: CodeActionKind = CodeActionKind::new("");
pub const QUICKFIX: CodeActionKind = CodeActionKind::new("quickfix");
pub const REFACTOR: CodeActionKind = CodeActionKind::new("refactor");
pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract");
pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline");
pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite");
pub const SOURCE: CodeActionKind = CodeActionKind::new("source");
pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind =
CodeActionKind::new("source.organizeImports");
pub const fn new(tag: &'static str) -> Self {
CodeActionKind(Cow::Borrowed(tag))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for CodeActionKind {
fn from(from: String) -> Self {
CodeActionKind(Cow::from(from))
}
}
impl From<&'static str> for CodeActionKind {
fn from(from: &'static str) -> Self {
CodeActionKind::new(from)
}
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeAction {
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<CodeActionKind>,
#[serde(skip_serializing_if = "Option::is_none")]
pub diagnostics: Option<Vec<Diagnostic>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub edit: Option<WorkspaceEdit>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<Command>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_preferred: Option<bool>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled: Option<CodeActionDisabled>,
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
#[cfg(feature = "proposed")]
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionDisabled {
pub reason: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct CodeActionContext {
pub diagnostics: Vec<Diagnostic>,
#[serde(skip_serializing_if = "Option::is_none")]
pub only: Option<Vec<CodeActionKind>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action_kinds: Option<Vec<CodeActionKind>>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
#[serde(skip_serializing_if = "Option::is_none")]
pub resolve_provider: Option<bool>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::test_serialization;
#[test]
fn test_code_action_response() {
test_serialization(
&vec![
CodeActionOrCommand::Command(Command {
title: "title".to_string(),
command: "command".to_string(),
arguments: None,
}),
CodeActionOrCommand::CodeAction(CodeAction {
title: "title".to_string(),
kind: Some(CodeActionKind::QUICKFIX),
command: None,
diagnostics: None,
edit: None,
is_preferred: None,
..CodeAction::default()
}),
],
r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
)
}
}