Skip to main content

lsp_types_max/
code_action.rs

1use crate::{
2    Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier,
3    WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit,
4};
5use serde::{Deserialize, Serialize};
6
7use serde_json::Value;
8
9use std::borrow::Cow;
10#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
11#[serde(untagged)]
12pub enum CodeActionProviderCapability {
13    Simple(bool),
14    Options(CodeActionOptions),
15}
16
17impl From<CodeActionOptions> for CodeActionProviderCapability {
18    fn from(from: CodeActionOptions) -> Self {
19        Self::Options(from)
20    }
21}
22
23impl From<bool> for CodeActionProviderCapability {
24    fn from(from: bool) -> Self {
25        Self::Simple(from)
26    }
27}
28
29#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
30#[serde(rename_all = "camelCase")]
31pub struct CodeActionClientCapabilities {
32    ///
33    /// This capability supports dynamic registration.
34    ///
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub dynamic_registration: Option<bool>,
37
38    /// The client support code action literals as a valid
39    /// response of the `textDocument/codeAction` request.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub code_action_literal_support: Option<CodeActionLiteralSupport>,
42
43    /// Whether code action supports the `isPreferred` property.
44    ///
45    /// @since 3.15.0
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub is_preferred_support: Option<bool>,
48
49    /// Whether code action supports the `disabled` property.
50    ///
51    /// @since 3.16.0
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub disabled_support: Option<bool>,
54
55    /// Whether code action supports the `data` property which is
56    /// preserved between a `textDocument/codeAction` and a
57    /// `codeAction/resolve` request.
58    ///
59    /// @since 3.16.0
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub data_support: Option<bool>,
62
63    /// Whether the client supports resolving additional code action
64    /// properties via a separate `codeAction/resolve` request.
65    ///
66    /// @since 3.16.0
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub resolve_support: Option<CodeActionCapabilityResolveSupport>,
69
70    /// Whether the client honors the change annotations in
71    /// text edits and resource operations returned via the
72    /// `CodeAction#edit` property by for example presenting
73    /// the workspace edit in the user interface and asking
74    /// for confirmation.
75    ///
76    /// @since 3.16.0
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub honors_change_annotations: Option<bool>,
79}
80
81/// Whether the client supports resolving additional code action
82/// properties via a separate `codeAction/resolve` request.
83///
84/// @since 3.16.0
85#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
86#[serde(rename_all = "camelCase")]
87pub struct CodeActionCapabilityResolveSupport {
88    /// The properties that a client can resolve lazily.
89    pub properties: Vec<String>,
90}
91
92#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
93#[serde(rename_all = "camelCase")]
94pub struct CodeActionLiteralSupport {
95    /// The code action kind is support with the following value set.
96    pub code_action_kind: CodeActionKindLiteralSupport,
97}
98
99#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
100#[serde(rename_all = "camelCase")]
101pub struct CodeActionKindLiteralSupport {
102    /// The code action kind values the client supports. When this
103    /// property exists the client also guarantees that it will
104    /// handle values outside its set gracefully and falls back
105    /// to a default value when unknown.
106    pub value_set: Vec<String>,
107}
108
109/// Params for the CodeActionRequest
110#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
111#[serde(rename_all = "camelCase")]
112pub struct CodeActionParams {
113    /// The document in which the command was invoked.
114    pub text_document: TextDocumentIdentifier,
115
116    /// The range for which the command was invoked.
117    pub range: Range,
118
119    /// Context carrying additional information.
120    pub context: CodeActionContext,
121
122    #[serde(flatten)]
123    pub work_done_progress_params: WorkDoneProgressParams,
124
125    #[serde(flatten)]
126    pub partial_result_params: PartialResultParams,
127}
128
129/// response for CodeActionRequest
130pub type CodeActionResponse = Vec<CodeActionOrCommand>;
131
132#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
133#[serde(untagged)]
134pub enum CodeActionOrCommand {
135    Command(Command),
136    CodeAction(CodeAction),
137}
138
139impl From<Command> for CodeActionOrCommand {
140    fn from(command: Command) -> Self {
141        CodeActionOrCommand::Command(command)
142    }
143}
144
145impl From<CodeAction> for CodeActionOrCommand {
146    fn from(action: CodeAction) -> Self {
147        CodeActionOrCommand::CodeAction(action)
148    }
149}
150
151#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
152pub struct CodeActionKind(Cow<'static, str>);
153
154impl CodeActionKind {
155    /// Empty kind.
156    pub const EMPTY: CodeActionKind = CodeActionKind::new("");
157
158    /// Base kind for quickfix actions: 'quickfix'
159    pub const QUICKFIX: CodeActionKind = CodeActionKind::new("quickfix");
160
161    /// Base kind for refactoring actions: 'refactor'
162    pub const REFACTOR: CodeActionKind = CodeActionKind::new("refactor");
163    /// Base kind for refactoring move actions: `refactor.move`.
164    ///
165    /// @since 3.18.0
166    #[cfg(feature = "proposed")]
167    pub const REFACTOR_MOVE: CodeActionKind = CodeActionKind::new("refactor.move");
168
169    /// Base kind for refactoring move actions: `refactor.move`.
170    ///
171    /// @since 3.18.0
172    #[cfg(feature = "proposed")]
173    #[allow(non_upper_case_globals)]
174    pub const RefactorMove: CodeActionKind = CodeActionKind::new("refactor.move");
175
176    /// Base kind for refactoring extraction actions: 'refactor.extract'
177    ///
178    /// Example extract actions:
179    ///
180    /// - Extract method
181    /// - Extract function
182    /// - Extract variable
183    /// - Extract interface from class
184    /// - ...
185    pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract");
186
187    /// Base kind for refactoring inline actions: 'refactor.inline'
188    ///
189    /// Example inline actions:
190    ///
191    /// - Inline function
192    /// - Inline variable
193    /// - Inline constant
194    /// - ...
195    pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline");
196
197    /// Base kind for refactoring rewrite actions: 'refactor.rewrite'
198    ///
199    /// Example rewrite actions:
200    ///
201    /// - Convert JavaScript function to class
202    /// - Add or remove parameter
203    /// - Encapsulate field
204    /// - Make method static
205    /// - Move method to base class
206    /// - ...
207    pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite");
208
209    /// Base kind for source actions: `source`
210    ///
211    /// Source code actions apply to the entire file.
212    pub const SOURCE: CodeActionKind = CodeActionKind::new("source");
213
214    /// Base kind for an organize imports source action: `source.organizeImports`
215    pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind =
216        CodeActionKind::new("source.organizeImports");
217
218    /// Base kind for a 'fix all' source action: `source.fixAll`.
219    ///
220    /// 'Fix all' actions automatically fix errors that have a clear fix that
221    /// do not require user input. They should not suppress errors or perform
222    /// unsafe fixes such as generating new types or classes.
223    ///
224    /// @since 3.17.0
225    pub const SOURCE_FIX_ALL: CodeActionKind = CodeActionKind::new("source.fixAll");
226
227    pub const fn new(tag: &'static str) -> Self {
228        CodeActionKind(Cow::Borrowed(tag))
229    }
230
231    pub fn as_str(&self) -> &str {
232        &self.0
233    }
234}
235
236impl From<String> for CodeActionKind {
237    fn from(from: String) -> Self {
238        CodeActionKind(Cow::from(from))
239    }
240}
241
242impl From<&'static str> for CodeActionKind {
243    fn from(from: &'static str) -> Self {
244        CodeActionKind::new(from)
245    }
246}
247
248#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
249#[serde(rename_all = "camelCase")]
250pub struct CodeAction {
251    /// A short, human-readable, title for this code action.
252    pub title: String,
253
254    /// The kind of the code action.
255    /// Used to filter code actions.
256    #[serde(skip_serializing_if = "Option::is_none")]
257    pub kind: Option<CodeActionKind>,
258
259    /// The diagnostics that this code action resolves.
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub diagnostics: Option<Vec<Diagnostic>>,
262
263    /// The workspace edit this code action performs.
264    #[serde(skip_serializing_if = "Option::is_none")]
265    pub edit: Option<WorkspaceEdit>,
266
267    /// A command this code action executes. If a code action
268    /// provides an edit and a command, first the edit is
269    /// executed and then the command.
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub command: Option<Command>,
272
273    /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
274    /// by keybindings.
275    /// A quick fix should be marked preferred if it properly addresses the underlying error.
276    /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
277    ///
278    /// @since 3.15.0
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub is_preferred: Option<bool>,
281
282    /// Marks that the code action cannot currently be applied.
283    ///
284    /// Clients should follow the following guidelines regarding disabled code actions:
285    ///
286    /// - Disabled code actions are not shown in automatic
287    ///   [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
288    ///   code action menu.
289    ///
290    /// - Disabled actions are shown as faded out in the code action menu when the user request
291    ///   a more specific type of code action, such as refactorings.
292    ///
293    /// - If the user has a keybinding that auto applies a code action and only a disabled code
294    ///   actions are returned, the client should show the user an error message with `reason`
295    ///   in the editor.
296    ///
297    /// @since 3.16.0
298    #[serde(skip_serializing_if = "Option::is_none")]
299    pub disabled: Option<CodeActionDisabled>,
300
301    /// A data entry field that is preserved on a code action between
302    /// a `textDocument/codeAction` and a `codeAction/resolve` request.
303    ///
304    /// @since 3.16.0
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub data: Option<Value>,
307
308    /// Tags for this code action.
309    ///
310    /// @since 3.18.0
311    #[serde(skip_serializing_if = "Option::is_none")]
312    #[cfg(feature = "proposed")]
313    pub tags: Option<Vec<CodeActionTag>>,
314
315    /// Optional documentation for the code action kind.
316    ///
317    /// @since 3.18.0
318    #[serde(skip_serializing_if = "Option::is_none")]
319    pub documentation: Option<Vec<CodeActionKindDocumentation>>,
320}
321
322#[cfg(feature = "proposed")]
323#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
324#[serde(transparent)]
325pub struct CodeActionTag(i32);
326
327#[cfg(feature = "proposed")]
328lsp_enum! {
329impl CodeActionTag {
330    pub const LLM_GENERATED: CodeActionTag = CodeActionTag(1);
331}
332}
333
334#[cfg(feature = "proposed")]
335impl CodeActionTag {
336    #[allow(non_upper_case_globals)]
337    pub const LLMGenerated: CodeActionTag = CodeActionTag::LLM_GENERATED;
338}
339
340#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
341#[serde(rename_all = "camelCase")]
342pub struct CodeActionKindDocumentation {
343    pub kind: CodeActionKind,
344    pub command: Command,
345}
346
347#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
348#[serde(rename_all = "camelCase")]
349pub struct CodeActionDisabled {
350    /// Human readable description of why the code action is currently disabled.
351    ///
352    /// This is displayed in the code actions UI.
353    pub reason: String,
354}
355
356/// The reason why code actions were requested.
357///
358/// @since 3.17.0
359#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
360#[serde(transparent)]
361pub struct CodeActionTriggerKind(i32);
362lsp_enum! {
363impl CodeActionTriggerKind {
364    /// Code actions were explicitly requested by the user or by an extension.
365    pub const INVOKED: CodeActionTriggerKind = CodeActionTriggerKind(1);
366
367    /// Code actions were requested automatically.
368    ///
369    /// This typically happens when current selection in a file changes, but can
370    /// also be triggered when file content changes.
371    pub const AUTOMATIC: CodeActionTriggerKind = CodeActionTriggerKind(2);
372}
373}
374
375/// Contains additional diagnostic information about the context in which
376/// a code action is run.
377#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
378#[serde(rename_all = "camelCase")]
379pub struct CodeActionContext {
380    /// An array of diagnostics.
381    pub diagnostics: Vec<Diagnostic>,
382
383    /// Requested kind of actions to return.
384    ///
385    /// Actions not of this kind are filtered out by the client before being shown. So servers
386    /// can omit computing them.
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub only: Option<Vec<CodeActionKind>>,
389
390    /// The reason why code actions were requested.
391    ///
392    /// @since 3.17.0
393    #[serde(skip_serializing_if = "Option::is_none")]
394    pub trigger_kind: Option<CodeActionTriggerKind>,
395
396    /// Version constraint for composition.
397    #[serde(skip_serializing_if = "Option::is_none")]
398    pub version: Option<i32>,
399}
400
401#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Default)]
402#[serde(rename_all = "camelCase")]
403pub struct CodeActionOptions {
404    /// CodeActionKinds that this server may return.
405    ///
406    /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
407    /// may list out every specific kind they provide.
408    #[serde(skip_serializing_if = "Option::is_none")]
409    pub code_action_kinds: Option<Vec<CodeActionKind>>,
410
411    #[serde(flatten)]
412    pub work_done_progress_options: WorkDoneProgressOptions,
413
414    /// The server provides support to resolve additional
415    /// information for a code action.
416    ///
417    /// @since 3.16.0
418    #[serde(skip_serializing_if = "Option::is_none")]
419    pub resolve_provider: Option<bool>,
420}
421
422#[cfg(test)]
423mod tests {
424    use super::*;
425    use crate::tests::test_serialization;
426
427    #[test]
428    fn test_code_action_response() {
429        test_serialization(
430            &vec![
431                CodeActionOrCommand::Command(Command {
432                    title: "title".to_string(),
433                    command: "command".to_string(),
434                    arguments: None,
435                }),
436                CodeActionOrCommand::CodeAction(CodeAction {
437                    title: "title".to_string(),
438                    kind: Some(CodeActionKind::QUICKFIX),
439                    command: None,
440                    diagnostics: None,
441                    edit: None,
442                    is_preferred: None,
443                    ..CodeAction::default()
444                }),
445            ],
446            r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
447        )
448    }
449}