diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 53 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 5 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 22 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 32 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/main.rs | 23 |
6 files changed, 79 insertions, 60 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 1107ffc8b..e8eb3940f 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -1,11 +1,16 @@ | |||
1 | use languageserver_types::{ | 1 | use languageserver_types::{ |
2 | self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, | 2 | self, CreateFile, DocumentChangeOperation, DocumentChanges, InsertTextFormat, Location, |
3 | TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, InsertTextFormat, | 3 | Position, Range, RenameFile, ResourceOp, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, |
4 | TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, | ||
5 | WorkspaceEdit, | ||
4 | }; | 6 | }; |
5 | use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition,FileRange, CompletionItem, CompletionItemKind, InsertText, NavigationTarget}; | 7 | use ra_analysis::{ |
6 | use ra_editor::{LineCol, LineIndex, translate_offset_with_edit}; | 8 | CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit, |
7 | use ra_text_edit::{AtomTextEdit, TextEdit}; | 9 | InsertText, NavigationTarget, SourceChange, SourceFileEdit, |
10 | }; | ||
11 | use ra_editor::{translate_offset_with_edit, LineCol, LineIndex}; | ||
8 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; | 12 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; |
13 | use ra_text_edit::{AtomTextEdit, TextEdit}; | ||
9 | 14 | ||
10 | use crate::{req, server_world::ServerWorld, Result}; | 15 | use crate::{req, server_world::ServerWorld, Result}; |
11 | 16 | ||
@@ -39,7 +44,7 @@ impl Conv for SyntaxKind { | |||
39 | SyntaxKind::TYPE_DEF => SymbolKind::TypeParameter, | 44 | SyntaxKind::TYPE_DEF => SymbolKind::TypeParameter, |
40 | SyntaxKind::STATIC_DEF => SymbolKind::Constant, | 45 | SyntaxKind::STATIC_DEF => SymbolKind::Constant, |
41 | SyntaxKind::CONST_DEF => SymbolKind::Constant, | 46 | SyntaxKind::CONST_DEF => SymbolKind::Constant, |
42 | SyntaxKind::IMPL_ITEM => SymbolKind::Object, | 47 | SyntaxKind::IMPL_BLOCK => SymbolKind::Object, |
43 | _ => SymbolKind::Variable, | 48 | _ => SymbolKind::Variable, |
44 | } | 49 | } |
45 | } | 50 | } |
@@ -49,7 +54,7 @@ impl Conv for CompletionItemKind { | |||
49 | type Output = ::languageserver_types::CompletionItemKind; | 54 | type Output = ::languageserver_types::CompletionItemKind; |
50 | 55 | ||
51 | fn conv(self) -> <Self as Conv>::Output { | 56 | fn conv(self) -> <Self as Conv>::Output { |
52 | use ::languageserver_types::CompletionItemKind::*; | 57 | use languageserver_types::CompletionItemKind::*; |
53 | match self { | 58 | match self { |
54 | CompletionItemKind::Keyword => Keyword, | 59 | CompletionItemKind::Keyword => Keyword, |
55 | CompletionItemKind::Snippet => Snippet, | 60 | CompletionItemKind::Snippet => Snippet, |
@@ -266,12 +271,20 @@ impl TryConvWith for SourceChange { | |||
266 | }) | 271 | }) |
267 | } | 272 | } |
268 | }; | 273 | }; |
269 | let source_file_edits = self.source_file_edits.try_conv_with(world)?; | 274 | let mut document_changes: Vec<DocumentChangeOperation> = Vec::new(); |
270 | let file_system_edits = self.file_system_edits.try_conv_with(world)?; | 275 | for resource_op in self.file_system_edits.try_conv_with(world)? { |
276 | document_changes.push(DocumentChangeOperation::Op(resource_op)); | ||
277 | } | ||
278 | for text_document_edit in self.source_file_edits.try_conv_with(world)? { | ||
279 | document_changes.push(DocumentChangeOperation::Edit(text_document_edit)); | ||
280 | } | ||
281 | let workspace_edit = WorkspaceEdit { | ||
282 | changes: None, | ||
283 | document_changes: Some(DocumentChanges::Operations(document_changes)), | ||
284 | }; | ||
271 | Ok(req::SourceChange { | 285 | Ok(req::SourceChange { |
272 | label: self.label, | 286 | label: self.label, |
273 | source_file_edits, | 287 | workspace_edit, |
274 | file_system_edits, | ||
275 | cursor_position, | 288 | cursor_position, |
276 | }) | 289 | }) |
277 | } | 290 | } |
@@ -301,21 +314,25 @@ impl TryConvWith for SourceFileEdit { | |||
301 | 314 | ||
302 | impl TryConvWith for FileSystemEdit { | 315 | impl TryConvWith for FileSystemEdit { |
303 | type Ctx = ServerWorld; | 316 | type Ctx = ServerWorld; |
304 | type Output = req::FileSystemEdit; | 317 | type Output = ResourceOp; |
305 | fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> { | 318 | fn try_conv_with(self, world: &ServerWorld) -> Result<ResourceOp> { |
306 | let res = match self { | 319 | let res = match self { |
307 | FileSystemEdit::CreateFile { source_root, path } => { | 320 | FileSystemEdit::CreateFile { source_root, path } => { |
308 | let uri = world.path_to_uri(source_root, &path)?; | 321 | let uri = world.path_to_uri(source_root, &path)?.to_string(); |
309 | req::FileSystemEdit::CreateFile { uri } | 322 | ResourceOp::Create(CreateFile { uri, options: None }) |
310 | } | 323 | } |
311 | FileSystemEdit::MoveFile { | 324 | FileSystemEdit::MoveFile { |
312 | src, | 325 | src, |
313 | dst_source_root, | 326 | dst_source_root, |
314 | dst_path, | 327 | dst_path, |
315 | } => { | 328 | } => { |
316 | let src = world.file_id_to_uri(src)?; | 329 | let old_uri = world.file_id_to_uri(src)?.to_string(); |
317 | let dst = world.path_to_uri(dst_source_root, &dst_path)?; | 330 | let new_uri = world.path_to_uri(dst_source_root, &dst_path)?.to_string(); |
318 | req::FileSystemEdit::MoveFile { src, dst } | 331 | ResourceOp::Rename(RenameFile { |
332 | old_uri, | ||
333 | new_uri, | ||
334 | options: None, | ||
335 | }) | ||
319 | } | 336 | } |
320 | }; | 337 | }; |
321 | Ok(res) | 338 | Ok(res) |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 06dd373c0..60d9671de 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -350,7 +350,7 @@ fn on_notification( | |||
350 | .write() | 350 | .write() |
351 | .add_file_overlay(&path, params.text_document.text) | 351 | .add_file_overlay(&path, params.text_document.text) |
352 | { | 352 | { |
353 | subs.add_sub(FileId(file_id.0)); | 353 | subs.add_sub(FileId(file_id.0.into())); |
354 | } | 354 | } |
355 | return Ok(()); | 355 | return Ok(()); |
356 | } | 356 | } |
@@ -379,7 +379,7 @@ fn on_notification( | |||
379 | .to_file_path() | 379 | .to_file_path() |
380 | .map_err(|()| format_err!("invalid uri: {}", uri))?; | 380 | .map_err(|()| format_err!("invalid uri: {}", uri))?; |
381 | if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { | 381 | if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { |
382 | subs.remove_sub(FileId(file_id.0)); | 382 | subs.remove_sub(FileId(file_id.0.into())); |
383 | } | 383 | } |
384 | let params = req::PublishDiagnosticsParams { | 384 | let params = req::PublishDiagnosticsParams { |
385 | uri, | 385 | uri, |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 06ae9a64a..2fc4d3649 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -337,7 +337,10 @@ pub fn handle_runnables( | |||
337 | None => return Ok(None), | 337 | None => return Ok(None), |
338 | }; | 338 | }; |
339 | let file_id = world.analysis().crate_root(crate_id)?; | 339 | let file_id = world.analysis().crate_root(crate_id)?; |
340 | let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0)); | 340 | let path = world |
341 | .vfs | ||
342 | .read() | ||
343 | .file2path(ra_vfs::VfsFile(file_id.0.into())); | ||
341 | let res = world.workspaces.iter().find_map(|ws| { | 344 | let res = world.workspaces.iter().find_map(|ws| { |
342 | let tgt = ws.target_by_root(&path)?; | 345 | let tgt = ws.target_by_root(&path)?; |
343 | let res = CargoTargetSpec { | 346 | let res = CargoTargetSpec { |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 747ab8a8c..b41e90328 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use serde::{Serialize, Deserialize}; | ||
2 | use languageserver_types::{Location, Position, Range, TextDocumentIdentifier, Url}; | 1 | use languageserver_types::{Location, Position, Range, TextDocumentIdentifier, Url}; |
3 | use rustc_hash::FxHashMap; | 2 | use rustc_hash::FxHashMap; |
3 | use serde::{Deserialize, Serialize}; | ||
4 | use url_serde; | 4 | use url_serde; |
5 | 5 | ||
6 | pub use languageserver_types::{ | 6 | pub use languageserver_types::{ |
@@ -8,7 +8,7 @@ pub use languageserver_types::{ | |||
8 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, | 8 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, |
9 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, | 9 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, |
10 | PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit, | 10 | PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit, |
11 | TextDocumentPositionParams, TextEdit, WorkspaceSymbolParams, | 11 | TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | pub enum SyntaxTree {} | 14 | pub enum SyntaxTree {} |
@@ -151,26 +151,10 @@ pub struct Runnable { | |||
151 | #[serde(rename_all = "camelCase")] | 151 | #[serde(rename_all = "camelCase")] |
152 | pub struct SourceChange { | 152 | pub struct SourceChange { |
153 | pub label: String, | 153 | pub label: String, |
154 | pub source_file_edits: Vec<TextDocumentEdit>, | 154 | pub workspace_edit: WorkspaceEdit, |
155 | pub file_system_edits: Vec<FileSystemEdit>, | ||
156 | pub cursor_position: Option<TextDocumentPositionParams>, | 155 | pub cursor_position: Option<TextDocumentPositionParams>, |
157 | } | 156 | } |
158 | 157 | ||
159 | #[derive(Serialize, Debug)] | ||
160 | #[serde(tag = "type", rename_all = "camelCase")] | ||
161 | pub enum FileSystemEdit { | ||
162 | CreateFile { | ||
163 | #[serde(with = "url_serde")] | ||
164 | uri: Url, | ||
165 | }, | ||
166 | MoveFile { | ||
167 | #[serde(with = "url_serde")] | ||
168 | src: Url, | ||
169 | #[serde(with = "url_serde")] | ||
170 | dst: Url, | ||
171 | }, | ||
172 | } | ||
173 | |||
174 | pub enum InternalFeedback {} | 158 | pub enum InternalFeedback {} |
175 | 159 | ||
176 | impl Notification for InternalFeedback { | 160 | impl Notification for InternalFeedback { |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index c183c25af..ebf2b15cc 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -49,7 +49,7 @@ impl ServerWorldState { | |||
49 | let (mut vfs, roots) = Vfs::new(roots); | 49 | let (mut vfs, roots) = Vfs::new(roots); |
50 | for r in roots { | 50 | for r in roots { |
51 | let is_local = vfs.root2path(r).starts_with(&root); | 51 | let is_local = vfs.root2path(r).starts_with(&root); |
52 | change.add_root(SourceRootId(r.0), is_local); | 52 | change.add_root(SourceRootId(r.0.into()), is_local); |
53 | } | 53 | } |
54 | 54 | ||
55 | let mut crate_graph = CrateGraph::default(); | 55 | let mut crate_graph = CrateGraph::default(); |
@@ -60,7 +60,7 @@ impl ServerWorldState { | |||
60 | for tgt in pkg.targets(ws) { | 60 | for tgt in pkg.targets(ws) { |
61 | let root = tgt.root(ws); | 61 | let root = tgt.root(ws); |
62 | if let Some(file_id) = vfs.load(root) { | 62 | if let Some(file_id) = vfs.load(root) { |
63 | let file_id = FileId(file_id.0); | 63 | let file_id = FileId(file_id.0.into()); |
64 | let crate_id = crate_graph.add_crate_root(file_id); | 64 | let crate_id = crate_graph.add_crate_root(file_id); |
65 | if tgt.kind(ws) == TargetKind::Lib { | 65 | if tgt.kind(ws) == TargetKind::Lib { |
66 | pkg_to_lib_crate.insert(pkg, crate_id); | 66 | pkg_to_lib_crate.insert(pkg, crate_id); |
@@ -113,14 +113,19 @@ impl ServerWorldState { | |||
113 | if root_path.starts_with(&self.root) { | 113 | if root_path.starts_with(&self.root) { |
114 | self.roots_to_scan -= 1; | 114 | self.roots_to_scan -= 1; |
115 | for (file, path, text) in files { | 115 | for (file, path, text) in files { |
116 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); | 116 | change.add_file( |
117 | SourceRootId(root.0.into()), | ||
118 | FileId(file.0.into()), | ||
119 | path, | ||
120 | text, | ||
121 | ); | ||
117 | } | 122 | } |
118 | } else { | 123 | } else { |
119 | let files = files | 124 | let files = files |
120 | .into_iter() | 125 | .into_iter() |
121 | .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text)) | 126 | .map(|(vfsfile, path, text)| (FileId(vfsfile.0.into()), path, text)) |
122 | .collect(); | 127 | .collect(); |
123 | libs.push((SourceRootId(root.0), files)); | 128 | libs.push((SourceRootId(root.0.into()), files)); |
124 | } | 129 | } |
125 | } | 130 | } |
126 | VfsChange::AddFile { | 131 | VfsChange::AddFile { |
@@ -129,13 +134,18 @@ impl ServerWorldState { | |||
129 | path, | 134 | path, |
130 | text, | 135 | text, |
131 | } => { | 136 | } => { |
132 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); | 137 | change.add_file( |
138 | SourceRootId(root.0.into()), | ||
139 | FileId(file.0.into()), | ||
140 | path, | ||
141 | text, | ||
142 | ); | ||
133 | } | 143 | } |
134 | VfsChange::RemoveFile { root, file, path } => { | 144 | VfsChange::RemoveFile { root, file, path } => { |
135 | change.remove_file(SourceRootId(root.0), FileId(file.0), path) | 145 | change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path) |
136 | } | 146 | } |
137 | VfsChange::ChangeFile { file, text } => { | 147 | VfsChange::ChangeFile { file, text } => { |
138 | change.change_file(FileId(file.0), text); | 148 | change.change_file(FileId(file.0.into()), text); |
139 | } | 149 | } |
140 | } | 150 | } |
141 | } | 151 | } |
@@ -173,18 +183,18 @@ impl ServerWorld { | |||
173 | .read() | 183 | .read() |
174 | .path2file(&path) | 184 | .path2file(&path) |
175 | .ok_or_else(|| format_err!("unknown file: {}", path.display()))?; | 185 | .ok_or_else(|| format_err!("unknown file: {}", path.display()))?; |
176 | Ok(FileId(file.0)) | 186 | Ok(FileId(file.0.into())) |
177 | } | 187 | } |
178 | 188 | ||
179 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { | 189 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { |
180 | let path = self.vfs.read().file2path(VfsFile(id.0)); | 190 | let path = self.vfs.read().file2path(VfsFile(id.0.into())); |
181 | let url = Url::from_file_path(&path) | 191 | let url = Url::from_file_path(&path) |
182 | .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?; | 192 | .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?; |
183 | Ok(url) | 193 | Ok(url) |
184 | } | 194 | } |
185 | 195 | ||
186 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { | 196 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { |
187 | let base = self.vfs.read().root2path(VfsRoot(root.0)); | 197 | let base = self.vfs.read().root2path(VfsRoot(root.0.into())); |
188 | let path = path.to_path(base); | 198 | let path = path.to_path(base); |
189 | let url = Url::from_file_path(&path) | 199 | let url = Url::from_file_path(&path) |
190 | .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?; | 200 | .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?; |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index b0e1e65b6..4cae44eab 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs | |||
@@ -1,8 +1,12 @@ | |||
1 | mod support; | 1 | mod support; |
2 | 2 | ||
3 | use languageserver_types::{ | ||
4 | CodeActionContext, DocumentFormattingParams, FormattingOptions, Position, Range, | ||
5 | }; | ||
6 | use ra_lsp_server::req::{ | ||
7 | CodeActionParams, CodeActionRequest, Formatting, Runnables, RunnablesParams, | ||
8 | }; | ||
3 | use serde_json::json; | 9 | use serde_json::json; |
4 | use ra_lsp_server::req::{Runnables, RunnablesParams, CodeActionRequest, CodeActionParams, Formatting}; | ||
5 | use languageserver_types::{Position, Range, CodeActionContext, DocumentFormattingParams, FormattingOptions}; | ||
6 | 10 | ||
7 | use crate::support::project; | 11 | use crate::support::project; |
8 | 12 | ||
@@ -203,14 +207,15 @@ fn main() {} | |||
203 | "arguments": [ | 207 | "arguments": [ |
204 | { | 208 | { |
205 | "cursorPosition": null, | 209 | "cursorPosition": null, |
206 | "fileSystemEdits": [ | 210 | "workspaceEdit": { |
207 | { | 211 | "documentChanges": [ |
208 | "type": "createFile", | 212 | { |
213 | "kind": "create", | ||
209 | "uri": "file:///[..]/src/bar.rs" | 214 | "uri": "file:///[..]/src/bar.rs" |
210 | } | 215 | } |
211 | ], | 216 | ] |
212 | "label": "create module", | 217 | }, |
213 | "sourceFileEdits": [] | 218 | "label": "create module" |
214 | } | 219 | } |
215 | ], | 220 | ], |
216 | "command": "ra-lsp.applySourceChange", | 221 | "command": "ra-lsp.applySourceChange", |