use crate::{ | |
Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier, | |
WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit, | |
}; | |
use serde::{Deserialize, Serialize}; | |
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 CodeActionClientCapabilities { | |
/// | |
/// This capability supports dynamic registration. | |
/// | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub dynamic_registration: Option<bool>, | |
/// The client support code action literals as a valid | |
/// response of the `textDocument/codeAction` request. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub code_action_literal_support: Option<CodeActionLiteralSupport>, | |
/// Whether code action supports the `isPreferred` property. | |
/// | |
/// since 3.15.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub is_preferred_support: Option<bool>, | |
/// Whether code action supports the `disabled` property. | |
/// | |
/// since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub disabled_support: Option<bool>, | |
/// Whether code action supports the `data` property which is | |
/// preserved between a `textDocument/codeAction` and a | |
/// `codeAction/resolve` request. | |
/// | |
/// since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub data_support: Option<bool>, | |
/// Whether the client supports resolving additional code action | |
/// properties via a separate `codeAction/resolve` request. | |
/// | |
/// since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub resolve_support: Option<CodeActionCapabilityResolveSupport>, | |
/// Whether the client honors the change annotations in | |
/// text edits and resource operations returned via the | |
/// `CodeAction#edit` property by for example presenting | |
/// the workspace edit in the user interface and asking | |
/// for confirmation. | |
/// | |
/// @since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub honors_change_annotations: Option<bool>, | |
} | |
/// Whether the client supports resolving additional code action | |
/// properties via a separate `codeAction/resolve` request. | |
/// | |
/// since 3.16.0 | |
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionCapabilityResolveSupport { | |
/// The properties that a client can resolve lazily. | |
pub properties: Vec<String>, | |
} | |
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionLiteralSupport { | |
/// The code action kind is support with the following value set. | |
pub code_action_kind: CodeActionKindLiteralSupport, | |
} | |
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionKindLiteralSupport { | |
/// The code action kind values the client supports. When this | |
/// property exists the client also guarantees that it will | |
/// handle values outside its set gracefully and falls back | |
/// to a default value when unknown. | |
pub value_set: Vec<String>, | |
} | |
/// Params for the CodeActionRequest | |
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionParams { | |
/// The document in which the command was invoked. | |
pub text_document: TextDocumentIdentifier, | |
/// The range for which the command was invoked. | |
pub range: Range, | |
/// Context carrying additional information. | |
pub context: CodeActionContext, | |
#[serde(flatten)] | |
pub work_done_progress_params: WorkDoneProgressParams, | |
#[serde(flatten)] | |
pub partial_result_params: PartialResultParams, | |
} | |
/// response for CodeActionRequest | |
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 { | |
/// Empty kind. | |
pub const EMPTY: CodeActionKind = CodeActionKind::new(""); | |
/// Base kind for quickfix actions: 'quickfix' | |
pub const QUICKFIX: CodeActionKind = CodeActionKind::new("quickfix"); | |
/// Base kind for refactoring actions: 'refactor' | |
pub const REFACTOR: CodeActionKind = CodeActionKind::new("refactor"); | |
/// Base kind for refactoring extraction actions: 'refactor.extract' | |
/// | |
/// Example extract actions: | |
/// | |
/// - Extract method | |
/// - Extract function | |
/// - Extract variable | |
/// - Extract interface from class | |
/// - ... | |
pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract"); | |
/// Base kind for refactoring inline actions: 'refactor.inline' | |
/// | |
/// Example inline actions: | |
/// | |
/// - Inline function | |
/// - Inline variable | |
/// - Inline constant | |
/// - ... | |
pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline"); | |
/// Base kind for refactoring rewrite actions: 'refactor.rewrite' | |
/// | |
/// Example rewrite actions: | |
/// | |
/// - Convert JavaScript function to class | |
/// - Add or remove parameter | |
/// - Encapsulate field | |
/// - Make method static | |
/// - Move method to base class | |
/// - ... | |
pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite"); | |
/// Base kind for source actions: `source` | |
/// | |
/// Source code actions apply to the entire file. | |
pub const SOURCE: CodeActionKind = CodeActionKind::new("source"); | |
/// Base kind for an organize imports source action: `source.organizeImports` | |
pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind = | |
CodeActionKind::new("source.organizeImports"); | |
/// Base kind for a 'fix all' source action: `source.fixAll`. | |
/// | |
/// 'Fix all' actions automatically fix errors that have a clear fix that | |
/// do not require user input. They should not suppress errors or perform | |
/// unsafe fixes such as generating new types or classes. | |
/// | |
/// @since 3.17.0 | |
pub const SOURCE_FIX_ALL: CodeActionKind = CodeActionKind::new("source.fixAll"); | |
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 { | |
/// A short, human-readable, title for this code action. | |
pub title: String, | |
/// The kind of the code action. | |
/// Used to filter code actions. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub kind: Option<CodeActionKind>, | |
/// The diagnostics that this code action resolves. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub diagnostics: Option<Vec<Diagnostic>>, | |
/// The workspace edit this code action performs. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub edit: Option<WorkspaceEdit>, | |
/// A command this code action executes. If a code action | |
/// provides an edit and a command, first the edit is | |
/// executed and then the command. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub command: Option<Command>, | |
/// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted | |
/// by keybindings. | |
/// A quick fix should be marked preferred if it properly addresses the underlying error. | |
/// A refactoring should be marked preferred if it is the most reasonable choice of actions to take. | |
/// | |
/// since 3.15.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub is_preferred: Option<bool>, | |
/// Marks that the code action cannot currently be applied. | |
/// | |
/// Clients should follow the following guidelines regarding disabled code actions: | |
/// | |
/// - Disabled code actions are not shown in automatic | |
/// [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) | |
/// code action menu. | |
/// | |
/// - Disabled actions are shown as faded out in the code action menu when the user request | |
/// a more specific type of code action, such as refactorings. | |
/// | |
/// - If the user has a keybinding that auto applies a code action and only a disabled code | |
/// actions are returned, the client should show the user an error message with `reason` | |
/// in the editor. | |
/// | |
/// since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub disabled: Option<CodeActionDisabled>, | |
/// A data entry field that is preserved on a code action between | |
/// a `textDocument/codeAction` and a `codeAction/resolve` request. | |
/// | |
/// since 3.16.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub data: Option<Value>, | |
} | |
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionDisabled { | |
/// Human readable description of why the code action is currently disabled. | |
/// | |
/// This is displayed in the code actions UI. | |
pub reason: String, | |
} | |
/// The reason why code actions were requested. | |
/// | |
/// @since 3.17.0 | |
#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] | |
#[serde(transparent)] | |
pub struct CodeActionTriggerKind(i32); | |
lsp_enum! { | |
impl CodeActionTriggerKind { | |
/// Code actions were explicitly requested by the user or by an extension. | |
pub const INVOKED: CodeActionTriggerKind = CodeActionTriggerKind(1); | |
/// Code actions were requested automatically. | |
/// | |
/// This typically happens when current selection in a file changes, but can | |
/// also be triggered when file content changes. | |
pub const AUTOMATIC: CodeActionTriggerKind = CodeActionTriggerKind(2); | |
} | |
} | |
/// Contains additional diagnostic information about the context in which | |
/// a code action is run. | |
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionContext { | |
/// An array of diagnostics. | |
pub diagnostics: Vec<Diagnostic>, | |
/// Requested kind of actions to return. | |
/// | |
/// Actions not of this kind are filtered out by the client before being shown. So servers | |
/// can omit computing them. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub only: Option<Vec<CodeActionKind>>, | |
/// The reason why code actions were requested. | |
/// | |
/// @since 3.17.0 | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub trigger_kind: Option<CodeActionTriggerKind>, | |
} | |
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] | |
#[serde(rename_all = "camelCase")] | |
pub struct CodeActionOptions { | |
/// CodeActionKinds that this server may return. | |
/// | |
/// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server | |
/// may list out every specific kind they provide. | |
#[serde(skip_serializing_if = "Option::is_none")] | |
pub code_action_kinds: Option<Vec<CodeActionKind>>, | |
#[serde(flatten)] | |
pub work_done_progress_options: WorkDoneProgressOptions, | |
/// The server provides support to resolve additional | |
/// information for a code action. | |
/// | |
/// since 3.16.0 | |
#[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"}]"#, | |
) | |
} | |
} |