diff options
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 61 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 73 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 22 |
5 files changed, 98 insertions, 61 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 8d508a3ba..a74f9f27b 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -28,7 +28,7 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
28 | type_definition_provider: None, | 28 | type_definition_provider: None, |
29 | implementation_provider: None, | 29 | implementation_provider: None, |
30 | references_provider: Some(true), | 30 | references_provider: Some(true), |
31 | document_highlight_provider: None, | 31 | document_highlight_provider: Some(true), |
32 | document_symbol_provider: Some(true), | 32 | document_symbol_provider: Some(true), |
33 | workspace_symbol_provider: Some(true), | 33 | workspace_symbol_provider: Some(true), |
34 | code_action_provider: Some(CodeActionProviderCapability::Simple(true)), | 34 | code_action_provider: Some(CodeActionProviderCapability::Simple(true)), |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 0d6e62727..7230fb101 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}; | 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 | ||
@@ -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, |
@@ -82,7 +87,6 @@ impl Conv for CompletionItem { | |||
82 | InsertText::Snippet { text } => { | 87 | InsertText::Snippet { text } => { |
83 | res.insert_text = Some(text); | 88 | res.insert_text = Some(text); |
84 | res.insert_text_format = Some(InsertTextFormat::Snippet); | 89 | res.insert_text_format = Some(InsertTextFormat::Snippet); |
85 | res.kind = Some(languageserver_types::CompletionItemKind::Keyword); | ||
86 | } | 90 | } |
87 | } | 91 | } |
88 | res | 92 | res |
@@ -267,12 +271,20 @@ impl TryConvWith for SourceChange { | |||
267 | }) | 271 | }) |
268 | } | 272 | } |
269 | }; | 273 | }; |
270 | let source_file_edits = self.source_file_edits.try_conv_with(world)?; | 274 | let mut document_changes: Vec<DocumentChangeOperation> = Vec::new(); |
271 | 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 | }; | ||
272 | Ok(req::SourceChange { | 285 | Ok(req::SourceChange { |
273 | label: self.label, | 286 | label: self.label, |
274 | source_file_edits, | 287 | workspace_edit, |
275 | file_system_edits, | ||
276 | cursor_position, | 288 | cursor_position, |
277 | }) | 289 | }) |
278 | } | 290 | } |
@@ -302,27 +314,40 @@ impl TryConvWith for SourceFileEdit { | |||
302 | 314 | ||
303 | impl TryConvWith for FileSystemEdit { | 315 | impl TryConvWith for FileSystemEdit { |
304 | type Ctx = ServerWorld; | 316 | type Ctx = ServerWorld; |
305 | type Output = req::FileSystemEdit; | 317 | type Output = ResourceOp; |
306 | fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> { | 318 | fn try_conv_with(self, world: &ServerWorld) -> Result<ResourceOp> { |
307 | let res = match self { | 319 | let res = match self { |
308 | FileSystemEdit::CreateFile { source_root, path } => { | 320 | FileSystemEdit::CreateFile { source_root, path } => { |
309 | let uri = world.path_to_uri(source_root, &path)?; | 321 | let uri = world.path_to_uri(source_root, &path)?.to_string(); |
310 | req::FileSystemEdit::CreateFile { uri } | 322 | ResourceOp::Create(CreateFile { uri, options: None }) |
311 | } | 323 | } |
312 | FileSystemEdit::MoveFile { | 324 | FileSystemEdit::MoveFile { |
313 | src, | 325 | src, |
314 | dst_source_root, | 326 | dst_source_root, |
315 | dst_path, | 327 | dst_path, |
316 | } => { | 328 | } => { |
317 | let src = world.file_id_to_uri(src)?; | 329 | let old_uri = world.file_id_to_uri(src)?.to_string(); |
318 | 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(); |
319 | req::FileSystemEdit::MoveFile { src, dst } | 331 | ResourceOp::Rename(RenameFile { |
332 | old_uri, | ||
333 | new_uri, | ||
334 | options: None, | ||
335 | }) | ||
320 | } | 336 | } |
321 | }; | 337 | }; |
322 | Ok(res) | 338 | Ok(res) |
323 | } | 339 | } |
324 | } | 340 | } |
325 | 341 | ||
342 | impl TryConvWith for &NavigationTarget { | ||
343 | type Ctx = ServerWorld; | ||
344 | type Output = Location; | ||
345 | fn try_conv_with(self, world: &ServerWorld) -> Result<Location> { | ||
346 | let line_index = world.analysis().file_line_index(self.file_id()); | ||
347 | to_location(self.file_id(), self.range(), &world, &line_index) | ||
348 | } | ||
349 | } | ||
350 | |||
326 | pub fn to_location( | 351 | pub fn to_location( |
327 | file_id: FileId, | 352 | file_id: FileId, |
328 | range: TextRange, | 353 | range: TextRange, |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index d425b6733..06dd373c0 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -300,6 +300,7 @@ fn on_request( | |||
300 | .on::<req::Rename>(handlers::handle_rename)? | 300 | .on::<req::Rename>(handlers::handle_rename)? |
301 | .on::<req::References>(handlers::handle_references)? | 301 | .on::<req::References>(handlers::handle_references)? |
302 | .on::<req::Formatting>(handlers::handle_formatting)? | 302 | .on::<req::Formatting>(handlers::handle_formatting)? |
303 | .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)? | ||
303 | .finish(); | 304 | .finish(); |
304 | match req { | 305 | match req { |
305 | Ok(id) => { | 306 | Ok(id) => { |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 3b7a14a5c..b5792f3b8 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -6,9 +6,8 @@ use languageserver_types::{ | |||
6 | DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, | 6 | DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, |
7 | FoldingRangeParams, Location, MarkupContent, MarkupKind, MarkedString, Position, | 7 | FoldingRangeParams, Location, MarkupContent, MarkupKind, MarkedString, Position, |
8 | PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, | 8 | PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, |
9 | Range, | 9 | Range, WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, |
10 | WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents, | 10 | HoverContents, DocumentFormattingParams, DocumentHighlight, |
11 | DocumentFormattingParams, | ||
12 | }; | 11 | }; |
13 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity}; | 12 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity}; |
14 | use ra_syntax::{TextUnit, text_utils::intersect}; | 13 | use ra_syntax::{TextUnit, text_utils::intersect}; |
@@ -189,12 +188,11 @@ pub fn handle_workspace_symbol( | |||
189 | 188 | ||
190 | fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> { | 189 | fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> { |
191 | let mut res = Vec::new(); | 190 | let mut res = Vec::new(); |
192 | for (file_id, symbol) in world.analysis().symbol_search(query)? { | 191 | for nav in world.analysis().symbol_search(query)? { |
193 | let line_index = world.analysis().file_line_index(file_id); | ||
194 | let info = SymbolInformation { | 192 | let info = SymbolInformation { |
195 | name: symbol.name.to_string(), | 193 | name: nav.name().to_string(), |
196 | kind: symbol.kind.conv(), | 194 | kind: nav.kind().conv(), |
197 | location: to_location(file_id, symbol.node_range, world, &line_index)?, | 195 | location: nav.try_conv_with(world)?, |
198 | container_name: None, | 196 | container_name: None, |
199 | deprecated: None, | 197 | deprecated: None, |
200 | }; | 198 | }; |
@@ -213,12 +211,11 @@ pub fn handle_goto_definition( | |||
213 | None => return Ok(None), | 211 | None => return Ok(None), |
214 | Some(it) => it, | 212 | Some(it) => it, |
215 | }; | 213 | }; |
216 | let mut res = Vec::new(); | 214 | let res = rr |
217 | for (file_id, symbol) in rr.resolves_to { | 215 | .resolves_to |
218 | let line_index = world.analysis().file_line_index(file_id); | 216 | .into_iter() |
219 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 217 | .map(|nav| nav.try_conv_with(&world)) |
220 | res.push(location) | 218 | .collect::<Result<Vec<_>>>()?; |
221 | } | ||
222 | Ok(Some(req::GotoDefinitionResponse::Array(res))) | 219 | Ok(Some(req::GotoDefinitionResponse::Array(res))) |
223 | } | 220 | } |
224 | 221 | ||
@@ -227,13 +224,12 @@ pub fn handle_parent_module( | |||
227 | params: req::TextDocumentPositionParams, | 224 | params: req::TextDocumentPositionParams, |
228 | ) -> Result<Vec<Location>> { | 225 | ) -> Result<Vec<Location>> { |
229 | let position = params.try_conv_with(&world)?; | 226 | let position = params.try_conv_with(&world)?; |
230 | let mut res = Vec::new(); | 227 | world |
231 | for (file_id, symbol) in world.analysis().parent_module(position)? { | 228 | .analysis() |
232 | let line_index = world.analysis().file_line_index(file_id); | 229 | .parent_module(position)? |
233 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 230 | .into_iter() |
234 | res.push(location); | 231 | .map(|nav| nav.try_conv_with(&world)) |
235 | } | 232 | .collect::<Result<Vec<_>>>() |
236 | Ok(res) | ||
237 | } | 233 | } |
238 | 234 | ||
239 | pub fn handle_runnables( | 235 | pub fn handle_runnables( |
@@ -257,6 +253,7 @@ pub fn handle_runnables( | |||
257 | range: runnable.range.conv_with(&line_index), | 253 | range: runnable.range.conv_with(&line_index), |
258 | label: match &runnable.kind { | 254 | label: match &runnable.kind { |
259 | RunnableKind::Test { name } => format!("test {}", name), | 255 | RunnableKind::Test { name } => format!("test {}", name), |
256 | RunnableKind::TestMod { path } => format!("test-mod {}", path), | ||
260 | RunnableKind::Bin => "run binary".to_string(), | 257 | RunnableKind::Bin => "run binary".to_string(), |
261 | }, | 258 | }, |
262 | bin: "cargo".to_string(), | 259 | bin: "cargo".to_string(), |
@@ -308,6 +305,15 @@ pub fn handle_runnables( | |||
308 | res.push(name.to_string()); | 305 | res.push(name.to_string()); |
309 | res.push("--nocapture".to_string()); | 306 | res.push("--nocapture".to_string()); |
310 | } | 307 | } |
308 | RunnableKind::TestMod { path } => { | ||
309 | res.push("test".to_string()); | ||
310 | if let Some(spec) = spec { | ||
311 | spec.push_to(&mut res); | ||
312 | } | ||
313 | res.push("--".to_string()); | ||
314 | res.push(path.to_string()); | ||
315 | res.push("--nocapture".to_string()); | ||
316 | } | ||
311 | RunnableKind::Bin => { | 317 | RunnableKind::Bin => { |
312 | res.push("run".to_string()); | 318 | res.push("run".to_string()); |
313 | if let Some(spec) = spec { | 319 | if let Some(spec) = spec { |
@@ -508,8 +514,8 @@ pub fn handle_hover( | |||
508 | Some(it) => it, | 514 | Some(it) => it, |
509 | }; | 515 | }; |
510 | let mut result = Vec::new(); | 516 | let mut result = Vec::new(); |
511 | for (file_id, symbol) in rr.resolves_to { | 517 | for nav in rr.resolves_to { |
512 | if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? { | 518 | if let Some(docs) = world.analysis().doc_text_for(nav)? { |
513 | result.push(docs); | 519 | result.push(docs); |
514 | } | 520 | } |
515 | } | 521 | } |
@@ -668,6 +674,27 @@ pub fn handle_code_action( | |||
668 | Ok(Some(CodeActionResponse::Commands(res))) | 674 | Ok(Some(CodeActionResponse::Commands(res))) |
669 | } | 675 | } |
670 | 676 | ||
677 | pub fn handle_document_highlight( | ||
678 | world: ServerWorld, | ||
679 | params: req::TextDocumentPositionParams, | ||
680 | ) -> Result<Option<Vec<DocumentHighlight>>> { | ||
681 | let file_id = params.text_document.try_conv_with(&world)?; | ||
682 | let line_index = world.analysis().file_line_index(file_id); | ||
683 | |||
684 | let refs = world | ||
685 | .analysis() | ||
686 | .find_all_refs(params.try_conv_with(&world)?)?; | ||
687 | |||
688 | Ok(Some( | ||
689 | refs.into_iter() | ||
690 | .map(|r| DocumentHighlight { | ||
691 | range: r.1.conv_with(&line_index), | ||
692 | kind: None, | ||
693 | }) | ||
694 | .collect(), | ||
695 | )) | ||
696 | } | ||
697 | |||
671 | pub fn publish_diagnostics( | 698 | pub fn publish_diagnostics( |
672 | world: &ServerWorld, | 699 | world: &ServerWorld, |
673 | file_id: FileId, | 700 | file_id: FileId, |
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 { |