blob: 6cc39e0d0809b840fe287151f9d353a750207f81 [file] [log] [blame]
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(command: Command) -> Self {
CodeActionOrCommand::Command(command)
}
}
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, Default)]
#[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"}]"#,
)
}
}