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 { from(from: CodeActionOptions) -> Self18 fn from(from: CodeActionOptions) -> Self { 19 Self::Options(from) 20 } 21 } 22 23 impl From<bool> for CodeActionProviderCapability { from(from: bool) -> Self24 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 { from(comand: Command) -> Self140 fn from(comand: Command) -> Self { 141 CodeActionOrCommand::Command(comand) 142 } 143 } 144 145 impl From<CodeAction> for CodeActionOrCommand { from(action: CodeAction) -> Self146 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 new(tag: &'static str) -> Self206 pub const fn new(tag: &'static str) -> Self { 207 CodeActionKind(Cow::Borrowed(tag)) 208 } 209 as_str(&self) -> &str210 pub fn as_str(&self) -> &str { 211 &self.0 212 } 213 } 214 215 impl From<String> for CodeActionKind { from(from: String) -> Self216 fn from(from: String) -> Self { 217 CodeActionKind(Cow::from(from)) 218 } 219 } 220 221 impl From<&'static str> for CodeActionKind { from(from: &'static str) -> Self222 fn from(from: &'static str) -> Self { 223 CodeActionKind::new(from) 224 } 225 } 226 227 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] 228 #[serde(rename_all = "camelCase")] 229 pub struct CodeAction { 230 /// A short, human-readable, title for this code action. 231 pub title: String, 232 233 /// The kind of the code action. 234 /// Used to filter code actions. 235 #[serde(skip_serializing_if = "Option::is_none")] 236 pub kind: Option<CodeActionKind>, 237 238 /// The diagnostics that this code action resolves. 239 #[serde(skip_serializing_if = "Option::is_none")] 240 pub diagnostics: Option<Vec<Diagnostic>>, 241 242 /// The workspace edit this code action performs. 243 #[serde(skip_serializing_if = "Option::is_none")] 244 pub edit: Option<WorkspaceEdit>, 245 246 /// A command this code action executes. If a code action 247 /// provides an edit and a command, first the edit is 248 /// executed and then the command. 249 #[serde(skip_serializing_if = "Option::is_none")] 250 pub command: Option<Command>, 251 252 /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted 253 /// by keybindings. 254 /// A quick fix should be marked preferred if it properly addresses the underlying error. 255 /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take. 256 /// 257 /// since 3.15.0 258 #[serde(skip_serializing_if = "Option::is_none")] 259 pub is_preferred: Option<bool>, 260 261 /// Marks that the code action cannot currently be applied. 262 /// 263 /// Clients should follow the following guidelines regarding disabled code actions: 264 /// 265 /// - Disabled code actions are not shown in automatic 266 /// [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) 267 /// code action menu. 268 /// 269 /// - Disabled actions are shown as faded out in the code action menu when the user request 270 /// a more specific type of code action, such as refactorings. 271 /// 272 /// - If the user has a keybinding that auto applies a code action and only a disabled code 273 /// actions are returned, the client should show the user an error message with `reason` 274 /// in the editor. 275 /// 276 /// since 3.16.0 277 #[serde(skip_serializing_if = "Option::is_none")] 278 pub disabled: Option<CodeActionDisabled>, 279 280 /// A data entry field that is preserved on a code action between 281 /// a `textDocument/codeAction` and a `codeAction/resolve` request. 282 /// 283 /// since 3.16.0 284 #[serde(skip_serializing_if = "Option::is_none")] 285 pub data: Option<Value>, 286 } 287 288 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] 289 #[serde(rename_all = "camelCase")] 290 pub struct CodeActionDisabled { 291 /// Human readable description of why the code action is currently disabled. 292 /// 293 /// This is displayed in the code actions UI. 294 pub reason: String, 295 } 296 297 /// Contains additional diagnostic information about the context in which 298 /// a code action is run. 299 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] 300 pub struct CodeActionContext { 301 /// An array of diagnostics. 302 pub diagnostics: Vec<Diagnostic>, 303 304 /// Requested kind of actions to return. 305 /// 306 /// Actions not of this kind are filtered out by the client before being shown. So servers 307 /// can omit computing them. 308 #[serde(skip_serializing_if = "Option::is_none")] 309 pub only: Option<Vec<CodeActionKind>>, 310 } 311 312 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] 313 #[serde(rename_all = "camelCase")] 314 pub struct CodeActionOptions { 315 /// CodeActionKinds that this server may return. 316 /// 317 /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server 318 /// may list out every specific kind they provide. 319 #[serde(skip_serializing_if = "Option::is_none")] 320 pub code_action_kinds: Option<Vec<CodeActionKind>>, 321 322 #[serde(flatten)] 323 pub work_done_progress_options: WorkDoneProgressOptions, 324 325 /// The server provides support to resolve additional 326 /// information for a code action. 327 /// 328 /// since 3.16.0 329 #[serde(skip_serializing_if = "Option::is_none")] 330 pub resolve_provider: Option<bool>, 331 } 332 333 #[cfg(test)] 334 mod tests { 335 use super::*; 336 use crate::tests::test_serialization; 337 338 #[test] test_code_action_response()339 fn test_code_action_response() { 340 test_serialization( 341 &vec![ 342 CodeActionOrCommand::Command(Command { 343 title: "title".to_string(), 344 command: "command".to_string(), 345 arguments: None, 346 }), 347 CodeActionOrCommand::CodeAction(CodeAction { 348 title: "title".to_string(), 349 kind: Some(CodeActionKind::QUICKFIX), 350 command: None, 351 diagnostics: None, 352 edit: None, 353 is_preferred: None, 354 ..CodeAction::default() 355 }), 356 ], 357 r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#, 358 ) 359 } 360 } 361