diff options
author | Aleksey Kladov <[email protected]> | 2018-08-13 00:38:34 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-13 00:38:34 +0100 |
commit | be742a587704f27f4e503c50f549aa9ec1527fcc (patch) | |
tree | fb15d3dd05c64c441c9cddbbce6aee3776d6ddd1 /crates/server/src/main_loop/handlers.rs | |
parent | 25aebb5225da91d34a2cb946f93435f9f7e82a47 (diff) |
Apply code actions
Diffstat (limited to 'crates/server/src/main_loop/handlers.rs')
-rw-r--r-- | crates/server/src/main_loop/handlers.rs | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index c6db22289..d4ae2a368 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs | |||
@@ -1,15 +1,18 @@ | |||
1 | use std::collections::HashMap; | ||
2 | |||
1 | use languageserver_types::{ | 3 | use languageserver_types::{ |
2 | Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, | 4 | Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, |
3 | Command | 5 | Command, TextDocumentIdentifier, WorkspaceEdit |
4 | }; | 6 | }; |
5 | use libanalysis::World; | 7 | use libanalysis::World; |
6 | use libeditor; | 8 | use libeditor; |
7 | use serde_json::to_value; | 9 | use libsyntax2::TextUnit; |
10 | use serde_json::{to_value, from_value}; | ||
8 | 11 | ||
9 | use ::{ | 12 | use ::{ |
10 | req::{self, Decoration}, Result, | 13 | req::{self, Decoration}, Result, |
11 | util::FilePath, | 14 | util::FilePath, |
12 | conv::{Conv, ConvWith}, | 15 | conv::{Conv, ConvWith, MapConvWith}, |
13 | }; | 16 | }; |
14 | 17 | ||
15 | pub fn handle_syntax_tree( | 18 | pub fn handle_syntax_tree( |
@@ -29,9 +32,9 @@ pub fn handle_extend_selection( | |||
29 | let file = world.file_syntax(&path)?; | 32 | let file = world.file_syntax(&path)?; |
30 | let line_index = world.file_line_index(&path)?; | 33 | let line_index = world.file_line_index(&path)?; |
31 | let selections = params.selections.into_iter() | 34 | let selections = params.selections.into_iter() |
32 | .map(|r| r.conv_with(&line_index)) | 35 | .map_conv_with(&line_index) |
33 | .map(|r| libeditor::extend_selection(&file, r).unwrap_or(r)) | 36 | .map(|r| libeditor::extend_selection(&file, r).unwrap_or(r)) |
34 | .map(|r| r.conv_with(&line_index)) | 37 | .map_conv_with(&line_index) |
35 | .collect(); | 38 | .collect(); |
36 | Ok(req::ExtendSelectionResult { selections }) | 39 | Ok(req::ExtendSelectionResult { selections }) |
37 | } | 40 | } |
@@ -78,18 +81,71 @@ pub fn handle_code_action( | |||
78 | let line_index = world.file_line_index(&path)?; | 81 | let line_index = world.file_line_index(&path)?; |
79 | let offset = params.range.conv_with(&line_index).start(); | 82 | let offset = params.range.conv_with(&line_index).start(); |
80 | let ret = if libeditor::flip_comma(&file, offset).is_some() { | 83 | let ret = if libeditor::flip_comma(&file, offset).is_some() { |
81 | Some(vec![apply_code_action_cmd(ActionId::FlipComma)]) | 84 | let cmd = apply_code_action_cmd( |
85 | ActionId::FlipComma, | ||
86 | params.text_document, | ||
87 | offset, | ||
88 | ); | ||
89 | Some(vec![cmd]) | ||
82 | } else { | 90 | } else { |
83 | None | 91 | None |
84 | }; | 92 | }; |
85 | Ok(ret) | 93 | Ok(ret) |
86 | } | 94 | } |
87 | 95 | ||
88 | fn apply_code_action_cmd(id: ActionId) -> Command { | 96 | pub fn handle_execute_command( |
97 | world: World, | ||
98 | mut params: req::ExecuteCommandParams, | ||
99 | ) -> Result<req::ApplyWorkspaceEditParams> { | ||
100 | if params.command.as_str() != "apply_code_action" { | ||
101 | bail!("unknown cmd: {:?}", params.command); | ||
102 | } | ||
103 | if params.arguments.len() != 1 { | ||
104 | bail!("expected single arg, got {}", params.arguments.len()); | ||
105 | } | ||
106 | let arg = params.arguments.pop().unwrap(); | ||
107 | let arg: ActionRequest = from_value(arg)?; | ||
108 | match arg.id { | ||
109 | ActionId::FlipComma => { | ||
110 | let path = arg.text_document.file_path()?; | ||
111 | let file = world.file_syntax(&path)?; | ||
112 | let line_index = world.file_line_index(&path)?; | ||
113 | let edit = match libeditor::flip_comma(&file, arg.offset) { | ||
114 | Some(edit) => edit(), | ||
115 | None => bail!("command not applicable"), | ||
116 | }; | ||
117 | let mut changes = HashMap::new(); | ||
118 | changes.insert( | ||
119 | arg.text_document.uri, | ||
120 | edit.conv_with(&line_index), | ||
121 | ); | ||
122 | let edit = WorkspaceEdit { | ||
123 | changes: Some(changes), | ||
124 | document_changes: None, | ||
125 | }; | ||
126 | |||
127 | Ok(req::ApplyWorkspaceEditParams { edit }) | ||
128 | } | ||
129 | } | ||
130 | } | ||
131 | |||
132 | #[derive(Serialize, Deserialize)] | ||
133 | struct ActionRequest { | ||
134 | id: ActionId, | ||
135 | text_document: TextDocumentIdentifier, | ||
136 | offset: TextUnit, | ||
137 | } | ||
138 | |||
139 | fn apply_code_action_cmd(id: ActionId, doc: TextDocumentIdentifier, offset: TextUnit) -> Command { | ||
140 | let action_request = ActionRequest { | ||
141 | id, | ||
142 | text_document: doc, | ||
143 | offset, | ||
144 | }; | ||
89 | Command { | 145 | Command { |
90 | title: id.title().to_string(), | 146 | title: id.title().to_string(), |
91 | command: "apply_code_action".to_string(), | 147 | command: "apply_code_action".to_string(), |
92 | arguments: Some(vec![to_value(id).unwrap()]), | 148 | arguments: Some(vec![to_value(action_request).unwrap()]), |
93 | } | 149 | } |
94 | } | 150 | } |
95 | 151 | ||