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
164 /// Base kind for refactoring extraction actions: 'refactor.extract'
165 ///
166 /// Example extract actions:
167 ///
168 /// - Extract method
169 /// - Extract function
170 /// - Extract variable
171 /// - Extract interface from class
172 /// - ...
173 pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract");
174
175 /// Base kind for refactoring inline actions: 'refactor.inline'
176 ///
177 /// Example inline actions:
178 ///
179 /// - Inline function
180 /// - Inline variable
181 /// - Inline constant
182 /// - ...
183 pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline");
184
185 /// Base kind for refactoring rewrite actions: 'refactor.rewrite'
186 ///
187 /// Example rewrite actions:
188 ///
189 /// - Convert JavaScript function to class
190 /// - Add or remove parameter
191 /// - Encapsulate field
192 /// - Make method static
193 /// - Move method to base class
194 /// - ...
195 pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite");
196
197 /// Base kind for source actions: `source`
198 ///
199 /// Source code actions apply to the entire file.
200 pub const SOURCE: CodeActionKind = CodeActionKind::new("source");
201
202 /// Base kind for an organize imports source action: `source.organizeImports`
203 pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind =
204 CodeActionKind::new("source.organizeImports");
205
206 /// Base kind for a 'fix all' source action: `source.fixAll`.
207 ///
208 /// 'Fix all' actions automatically fix errors that have a clear fix that
209 /// do not require user input. They should not suppress errors or perform
210 /// unsafe fixes such as generating new types or classes.
211 ///
212 /// @since 3.17.0
213 pub const SOURCE_FIX_ALL: CodeActionKind = CodeActionKind::new("source.fixAll");
214
215 pub const fn new(tag: &'static str) -> Self {
216 CodeActionKind(Cow::Borrowed(tag))
217 }
218
219 pub fn as_str(&self) -> &str {
220 &self.0
221 }
222}
223
224impl From<String> for CodeActionKind {
225 fn from(from: String) -> Self {
226 CodeActionKind(Cow::from(from))
227 }
228}
229
230impl From<&'static str> for CodeActionKind {
231 fn from(from: &'static str) -> Self {
232 CodeActionKind::new(tag:from)
233 }
234}
235
236#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
237#[serde(rename_all = "camelCase")]
238pub struct CodeAction {
239 /// A short, human-readable, title for this code action.
240 pub title: String,
241
242 /// The kind of the code action.
243 /// Used to filter code actions.
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub kind: Option<CodeActionKind>,
246
247 /// The diagnostics that this code action resolves.
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub diagnostics: Option<Vec<Diagnostic>>,
250
251 /// The workspace edit this code action performs.
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub edit: Option<WorkspaceEdit>,
254
255 /// A command this code action executes. If a code action
256 /// provides an edit and a command, first the edit is
257 /// executed and then the command.
258 #[serde(skip_serializing_if = "Option::is_none")]
259 pub command: Option<Command>,
260
261 /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
262 /// by keybindings.
263 /// A quick fix should be marked preferred if it properly addresses the underlying error.
264 /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
265 ///
266 /// @since 3.15.0
267 #[serde(skip_serializing_if = "Option::is_none")]
268 pub is_preferred: Option<bool>,
269
270 /// Marks that the code action cannot currently be applied.
271 ///
272 /// Clients should follow the following guidelines regarding disabled code actions:
273 ///
274 /// - Disabled code actions are not shown in automatic
275 /// [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
276 /// code action menu.
277 ///
278 /// - Disabled actions are shown as faded out in the code action menu when the user request
279 /// a more specific type of code action, such as refactorings.
280 ///
281 /// - If the user has a keybinding that auto applies a code action and only a disabled code
282 /// actions are returned, the client should show the user an error message with `reason`
283 /// in the editor.
284 ///
285 /// @since 3.16.0
286 #[serde(skip_serializing_if = "Option::is_none")]
287 pub disabled: Option<CodeActionDisabled>,
288
289 /// A data entry field that is preserved on a code action between
290 /// a `textDocument/codeAction` and a `codeAction/resolve` request.
291 ///
292 /// @since 3.16.0
293 #[serde(skip_serializing_if = "Option::is_none")]
294 pub data: Option<Value>,
295}
296
297#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
298#[serde(rename_all = "camelCase")]
299pub struct CodeActionDisabled {
300 /// Human readable description of why the code action is currently disabled.
301 ///
302 /// This is displayed in the code actions UI.
303 pub reason: String,
304}
305
306/// The reason why code actions were requested.
307///
308/// @since 3.17.0
309#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
310#[serde(transparent)]
311pub struct CodeActionTriggerKind(i32);
312lsp_enum! {
313impl CodeActionTriggerKind {
314 /// Code actions were explicitly requested by the user or by an extension.
315 pub const INVOKED: CodeActionTriggerKind = CodeActionTriggerKind(1);
316
317 /// Code actions were requested automatically.
318 ///
319 /// This typically happens when current selection in a file changes, but can
320 /// also be triggered when file content changes.
321 pub const AUTOMATIC: CodeActionTriggerKind = CodeActionTriggerKind(2);
322}
323}
324
325/// Contains additional diagnostic information about the context in which
326/// a code action is run.
327#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
328#[serde(rename_all = "camelCase")]
329pub struct CodeActionContext {
330 /// An array of diagnostics.
331 pub diagnostics: Vec<Diagnostic>,
332
333 /// Requested kind of actions to return.
334 ///
335 /// Actions not of this kind are filtered out by the client before being shown. So servers
336 /// can omit computing them.
337 #[serde(skip_serializing_if = "Option::is_none")]
338 pub only: Option<Vec<CodeActionKind>>,
339
340 /// The reason why code actions were requested.
341 ///
342 /// @since 3.17.0
343 #[serde(skip_serializing_if = "Option::is_none")]
344 pub trigger_kind: Option<CodeActionTriggerKind>,
345}
346
347#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Default)]
348#[serde(rename_all = "camelCase")]
349pub struct CodeActionOptions {
350 /// CodeActionKinds that this server may return.
351 ///
352 /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
353 /// may list out every specific kind they provide.
354 #[serde(skip_serializing_if = "Option::is_none")]
355 pub code_action_kinds: Option<Vec<CodeActionKind>>,
356
357 #[serde(flatten)]
358 pub work_done_progress_options: WorkDoneProgressOptions,
359
360 /// The server provides support to resolve additional
361 /// information for a code action.
362 ///
363 /// @since 3.16.0
364 #[serde(skip_serializing_if = "Option::is_none")]
365 pub resolve_provider: Option<bool>,
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371 use crate::tests::test_serialization;
372
373 #[test]
374 fn test_code_action_response() {
375 test_serialization(
376 &vec![
377 CodeActionOrCommand::Command(Command {
378 title: "title".to_string(),
379 command: "command".to_string(),
380 arguments: None,
381 }),
382 CodeActionOrCommand::CodeAction(CodeAction {
383 title: "title".to_string(),
384 kind: Some(CodeActionKind::QUICKFIX),
385 command: None,
386 diagnostics: None,
387 edit: None,
388 is_preferred: None,
389 ..CodeAction::default()
390 }),
391 ],
392 r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
393 )
394 }
395}
396