1 | use crate::{ |
2 | Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier, |
3 | WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit, |
4 | }; |
5 | use serde::{Deserialize, Serialize}; |
6 | |
7 | use serde_json::Value; |
8 | |
9 | use std::borrow::Cow; |
10 | #[derive (Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] |
11 | #[serde(untagged)] |
12 | pub enum CodeActionProviderCapability { |
13 | Simple(bool), |
14 | Options(CodeActionOptions), |
15 | } |
16 | |
17 | impl From<CodeActionOptions> for CodeActionProviderCapability { |
18 | fn from(from: CodeActionOptions) -> Self { |
19 | Self::Options(from) |
20 | } |
21 | } |
22 | |
23 | impl 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" )] |
31 | pub 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" )] |
87 | pub 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" )] |
94 | pub 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" )] |
101 | pub 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" )] |
112 | pub 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 |
130 | pub type CodeActionResponse = Vec<CodeActionOrCommand>; |
131 | |
132 | #[derive (Debug, Clone, PartialEq, Deserialize, Serialize)] |
133 | #[serde(untagged)] |
134 | pub enum CodeActionOrCommand { |
135 | Command(Command), |
136 | CodeAction(CodeAction), |
137 | } |
138 | |
139 | impl From<Command> for CodeActionOrCommand { |
140 | fn from(command: Command) -> Self { |
141 | CodeActionOrCommand::Command(command) |
142 | } |
143 | } |
144 | |
145 | impl 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)] |
152 | pub struct CodeActionKind(Cow<'static, str>); |
153 | |
154 | impl 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 | |
224 | impl From<String> for CodeActionKind { |
225 | fn from(from: String) -> Self { |
226 | CodeActionKind(Cow::from(from)) |
227 | } |
228 | } |
229 | |
230 | impl 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" )] |
238 | pub 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" )] |
299 | pub 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)] |
311 | pub struct CodeActionTriggerKind(i32); |
312 | lsp_enum! { |
313 | impl 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" )] |
329 | pub 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" )] |
349 | pub 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)] |
369 | mod 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 | |