diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/typing/on_enter.rs | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 57 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 27 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/main.rs | 46 |
7 files changed, 72 insertions, 86 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 5ac002d82..d983cd910 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -309,7 +309,8 @@ impl Analysis { | |||
309 | 309 | ||
310 | /// Returns an edit which should be applied when opening a new line, fixing | 310 | /// Returns an edit which should be applied when opening a new line, fixing |
311 | /// up minor stuff like continuing the comment. | 311 | /// up minor stuff like continuing the comment. |
312 | pub fn on_enter(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> { | 312 | /// The edit will be a snippet (with `$0`). |
313 | pub fn on_enter(&self, position: FilePosition) -> Cancelable<Option<TextEdit>> { | ||
313 | self.with_db(|db| typing::on_enter(&db, position)) | 314 | self.with_db(|db| typing::on_enter(&db, position)) |
314 | } | 315 | } |
315 | 316 | ||
diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs index e7d64b4f6..a40d8af9c 100644 --- a/crates/ra_ide/src/typing/on_enter.rs +++ b/crates/ra_ide/src/typing/on_enter.rs | |||
@@ -11,9 +11,7 @@ use ra_syntax::{ | |||
11 | }; | 11 | }; |
12 | use ra_text_edit::TextEdit; | 12 | use ra_text_edit::TextEdit; |
13 | 13 | ||
14 | use crate::{SourceChange, SourceFileEdit}; | 14 | pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> { |
15 | |||
16 | pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> { | ||
17 | let parse = db.parse(position.file_id); | 15 | let parse = db.parse(position.file_id); |
18 | let file = parse.tree(); | 16 | let file = parse.tree(); |
19 | let comment = file | 17 | let comment = file |
@@ -41,9 +39,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour | |||
41 | let inserted = format!("\n{}{} $0", indent, prefix); | 39 | let inserted = format!("\n{}{} $0", indent, prefix); |
42 | let edit = TextEdit::insert(position.offset, inserted); | 40 | let edit = TextEdit::insert(position.offset, inserted); |
43 | 41 | ||
44 | let mut res = SourceChange::from(SourceFileEdit { edit, file_id: position.file_id }); | 42 | Some(edit) |
45 | res.is_snippet = true; | ||
46 | Some(res) | ||
47 | } | 43 | } |
48 | 44 | ||
49 | fn followed_by_comment(comment: &ast::Comment) -> bool { | 45 | fn followed_by_comment(comment: &ast::Comment) -> bool { |
@@ -90,9 +86,8 @@ mod tests { | |||
90 | let (analysis, file_id) = single_file(&before); | 86 | let (analysis, file_id) = single_file(&before); |
91 | let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; | 87 | let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; |
92 | 88 | ||
93 | assert_eq!(result.source_file_edits.len(), 1); | ||
94 | let mut actual = before.to_string(); | 89 | let mut actual = before.to_string(); |
95 | result.source_file_edits[0].edit.apply(&mut actual); | 90 | result.apply(&mut actual); |
96 | Some(actual) | 91 | Some(actual) |
97 | } | 92 | } |
98 | 93 | ||
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 780fc9317..345693524 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -85,6 +85,8 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
85 | experimental: Some(json!({ | 85 | experimental: Some(json!({ |
86 | "joinLines": true, | 86 | "joinLines": true, |
87 | "ssr": true, | 87 | "ssr": true, |
88 | "onEnter": true, | ||
89 | "parentModule": true, | ||
88 | })), | 90 | })), |
89 | } | 91 | } |
90 | } | 92 | } |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 52e4fcbec..acb1dacb6 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::{collections::HashMap, path::PathBuf}; | 3 | use std::{collections::HashMap, path::PathBuf}; |
4 | 4 | ||
5 | use lsp_types::request::Request; | 5 | use lsp_types::request::Request; |
6 | use lsp_types::{Location, Position, Range, TextDocumentIdentifier}; | 6 | use lsp_types::{Position, Range, TextDocumentIdentifier}; |
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | use serde::{Deserialize, Serialize}; | 8 | use serde::{Deserialize, Serialize}; |
9 | 9 | ||
@@ -50,7 +50,7 @@ impl Request for ExpandMacro { | |||
50 | #[serde(rename_all = "camelCase")] | 50 | #[serde(rename_all = "camelCase")] |
51 | pub struct ExpandMacroParams { | 51 | pub struct ExpandMacroParams { |
52 | pub text_document: TextDocumentIdentifier, | 52 | pub text_document: TextDocumentIdentifier, |
53 | pub position: Option<Position>, | 53 | pub position: Position, |
54 | } | 54 | } |
55 | 55 | ||
56 | #[derive(Deserialize, Serialize, Debug)] | 56 | #[derive(Deserialize, Serialize, Debug)] |
@@ -79,8 +79,8 @@ pub enum ParentModule {} | |||
79 | 79 | ||
80 | impl Request for ParentModule { | 80 | impl Request for ParentModule { |
81 | type Params = lsp_types::TextDocumentPositionParams; | 81 | type Params = lsp_types::TextDocumentPositionParams; |
82 | type Result = Vec<Location>; | 82 | type Result = Option<lsp_types::GotoDefinitionResponse>; |
83 | const METHOD: &'static str = "rust-analyzer/parentModule"; | 83 | const METHOD: &'static str = "experimental/parentModule"; |
84 | } | 84 | } |
85 | 85 | ||
86 | pub enum JoinLines {} | 86 | pub enum JoinLines {} |
@@ -102,8 +102,8 @@ pub enum OnEnter {} | |||
102 | 102 | ||
103 | impl Request for OnEnter { | 103 | impl Request for OnEnter { |
104 | type Params = lsp_types::TextDocumentPositionParams; | 104 | type Params = lsp_types::TextDocumentPositionParams; |
105 | type Result = Option<SnippetWorkspaceEdit>; | 105 | type Result = Option<Vec<SnippetTextEdit>>; |
106 | const METHOD: &'static str = "rust-analyzer/onEnter"; | 106 | const METHOD: &'static str = "experimental/onEnter"; |
107 | } | 107 | } |
108 | 108 | ||
109 | pub enum Runnables {} | 109 | pub enum Runnables {} |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index d73107968..1f910ff82 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -72,15 +72,10 @@ pub fn handle_expand_macro( | |||
72 | let _p = profile("handle_expand_macro"); | 72 | let _p = profile("handle_expand_macro"); |
73 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; | 73 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; |
74 | let line_index = world.analysis().file_line_index(file_id)?; | 74 | let line_index = world.analysis().file_line_index(file_id)?; |
75 | let offset = params.position.map(|p| from_proto::offset(&line_index, p)); | 75 | let offset = from_proto::offset(&line_index, params.position); |
76 | 76 | ||
77 | match offset { | 77 | let res = world.analysis().expand_macro(FilePosition { file_id, offset })?; |
78 | None => Ok(None), | 78 | Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) |
79 | Some(offset) => { | ||
80 | let res = world.analysis().expand_macro(FilePosition { file_id, offset })?; | ||
81 | Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) | ||
82 | } | ||
83 | } | ||
84 | } | 79 | } |
85 | 80 | ||
86 | pub fn handle_selection_range( | 81 | pub fn handle_selection_range( |
@@ -174,13 +169,17 @@ pub fn handle_join_lines( | |||
174 | pub fn handle_on_enter( | 169 | pub fn handle_on_enter( |
175 | world: WorldSnapshot, | 170 | world: WorldSnapshot, |
176 | params: lsp_types::TextDocumentPositionParams, | 171 | params: lsp_types::TextDocumentPositionParams, |
177 | ) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> { | 172 | ) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { |
178 | let _p = profile("handle_on_enter"); | 173 | let _p = profile("handle_on_enter"); |
179 | let position = from_proto::file_position(&world, params)?; | 174 | let position = from_proto::file_position(&world, params)?; |
180 | match world.analysis().on_enter(position)? { | 175 | let edit = match world.analysis().on_enter(position)? { |
181 | None => Ok(None), | 176 | None => return Ok(None), |
182 | Some(source_change) => to_proto::snippet_workspace_edit(&world, source_change).map(Some), | 177 | Some(it) => it, |
183 | } | 178 | }; |
179 | let line_index = world.analysis().file_line_index(position.file_id)?; | ||
180 | let line_endings = world.file_line_endings(position.file_id); | ||
181 | let edit = to_proto::snippet_text_edit_vec(&line_index, line_endings, true, edit); | ||
182 | Ok(Some(edit)) | ||
184 | } | 183 | } |
185 | 184 | ||
186 | // Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`. | 185 | // Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`. |
@@ -345,11 +344,8 @@ pub fn handle_goto_definition( | |||
345 | None => return Ok(None), | 344 | None => return Ok(None), |
346 | Some(it) => it, | 345 | Some(it) => it, |
347 | }; | 346 | }; |
348 | let res = to_proto::goto_definition_response( | 347 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
349 | &world, | 348 | let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; |
350 | FileRange { file_id: position.file_id, range: nav_info.range }, | ||
351 | nav_info.info, | ||
352 | )?; | ||
353 | Ok(Some(res)) | 349 | Ok(Some(res)) |
354 | } | 350 | } |
355 | 351 | ||
@@ -363,11 +359,8 @@ pub fn handle_goto_implementation( | |||
363 | None => return Ok(None), | 359 | None => return Ok(None), |
364 | Some(it) => it, | 360 | Some(it) => it, |
365 | }; | 361 | }; |
366 | let res = to_proto::goto_definition_response( | 362 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
367 | &world, | 363 | let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; |
368 | FileRange { file_id: position.file_id, range: nav_info.range }, | ||
369 | nav_info.info, | ||
370 | )?; | ||
371 | Ok(Some(res)) | 364 | Ok(Some(res)) |
372 | } | 365 | } |
373 | 366 | ||
@@ -381,26 +374,20 @@ pub fn handle_goto_type_definition( | |||
381 | None => return Ok(None), | 374 | None => return Ok(None), |
382 | Some(it) => it, | 375 | Some(it) => it, |
383 | }; | 376 | }; |
384 | let res = to_proto::goto_definition_response( | 377 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
385 | &world, | 378 | let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; |
386 | FileRange { file_id: position.file_id, range: nav_info.range }, | ||
387 | nav_info.info, | ||
388 | )?; | ||
389 | Ok(Some(res)) | 379 | Ok(Some(res)) |
390 | } | 380 | } |
391 | 381 | ||
392 | pub fn handle_parent_module( | 382 | pub fn handle_parent_module( |
393 | world: WorldSnapshot, | 383 | world: WorldSnapshot, |
394 | params: lsp_types::TextDocumentPositionParams, | 384 | params: lsp_types::TextDocumentPositionParams, |
395 | ) -> Result<Vec<Location>> { | 385 | ) -> Result<Option<lsp_types::GotoDefinitionResponse>> { |
396 | let _p = profile("handle_parent_module"); | 386 | let _p = profile("handle_parent_module"); |
397 | let position = from_proto::file_position(&world, params)?; | 387 | let position = from_proto::file_position(&world, params)?; |
398 | world | 388 | let navs = world.analysis().parent_module(position)?; |
399 | .analysis() | 389 | let res = to_proto::goto_definition_response(&world, None, navs)?; |
400 | .parent_module(position)? | 390 | Ok(Some(res)) |
401 | .into_iter() | ||
402 | .map(|it| to_proto::location(&world, it.file_range())) | ||
403 | .collect::<Result<Vec<_>>>() | ||
404 | } | 391 | } |
405 | 392 | ||
406 | pub fn handle_runnables( | 393 | pub fn handle_runnables( |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index ebaad4d19..8e8e7033d 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -135,6 +135,18 @@ pub(crate) fn text_edit_vec( | |||
135 | text_edit.into_iter().map(|indel| self::text_edit(line_index, line_endings, indel)).collect() | 135 | text_edit.into_iter().map(|indel| self::text_edit(line_index, line_endings, indel)).collect() |
136 | } | 136 | } |
137 | 137 | ||
138 | pub(crate) fn snippet_text_edit_vec( | ||
139 | line_index: &LineIndex, | ||
140 | line_endings: LineEndings, | ||
141 | is_snippet: bool, | ||
142 | text_edit: TextEdit, | ||
143 | ) -> Vec<lsp_ext::SnippetTextEdit> { | ||
144 | text_edit | ||
145 | .into_iter() | ||
146 | .map(|indel| self::snippet_text_edit(line_index, line_endings, is_snippet, indel)) | ||
147 | .collect() | ||
148 | } | ||
149 | |||
138 | pub(crate) fn completion_item( | 150 | pub(crate) fn completion_item( |
139 | line_index: &LineIndex, | 151 | line_index: &LineIndex, |
140 | line_endings: LineEndings, | 152 | line_endings: LineEndings, |
@@ -392,13 +404,20 @@ pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_t | |||
392 | 404 | ||
393 | pub(crate) fn location_link( | 405 | pub(crate) fn location_link( |
394 | world: &WorldSnapshot, | 406 | world: &WorldSnapshot, |
395 | src: FileRange, | 407 | src: Option<FileRange>, |
396 | target: NavigationTarget, | 408 | target: NavigationTarget, |
397 | ) -> Result<lsp_types::LocationLink> { | 409 | ) -> Result<lsp_types::LocationLink> { |
398 | let src_location = location(world, src)?; | 410 | let origin_selection_range = match src { |
411 | Some(src) => { | ||
412 | let line_index = world.analysis().file_line_index(src.file_id)?; | ||
413 | let range = range(&line_index, src.range); | ||
414 | Some(range) | ||
415 | } | ||
416 | None => None, | ||
417 | }; | ||
399 | let (target_uri, target_range, target_selection_range) = location_info(world, target)?; | 418 | let (target_uri, target_range, target_selection_range) = location_info(world, target)?; |
400 | let res = lsp_types::LocationLink { | 419 | let res = lsp_types::LocationLink { |
401 | origin_selection_range: Some(src_location.range), | 420 | origin_selection_range, |
402 | target_uri, | 421 | target_uri, |
403 | target_range, | 422 | target_range, |
404 | target_selection_range, | 423 | target_selection_range, |
@@ -421,7 +440,7 @@ fn location_info( | |||
421 | 440 | ||
422 | pub(crate) fn goto_definition_response( | 441 | pub(crate) fn goto_definition_response( |
423 | world: &WorldSnapshot, | 442 | world: &WorldSnapshot, |
424 | src: FileRange, | 443 | src: Option<FileRange>, |
425 | targets: Vec<NavigationTarget>, | 444 | targets: Vec<NavigationTarget>, |
426 | ) -> Result<lsp_types::GotoDefinitionResponse> { | 445 | ) -> Result<lsp_types::GotoDefinitionResponse> { |
427 | if world.config.client_caps.location_link { | 446 | if world.config.client_caps.location_link { |
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 738a9a8e3..b1bfc968a 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs | |||
@@ -473,23 +473,14 @@ fn main() {{}} | |||
473 | text_document: server.doc_id("src/m0.rs"), | 473 | text_document: server.doc_id("src/m0.rs"), |
474 | position: Position { line: 0, character: 5 }, | 474 | position: Position { line: 0, character: 5 }, |
475 | }, | 475 | }, |
476 | json!({ | 476 | json!([{ |
477 | "documentChanges": [ | 477 | "insertTextFormat": 2, |
478 | { | 478 | "newText": "\n/// $0", |
479 | "edits": [ | 479 | "range": { |
480 | { | 480 | "end": { "character": 5, "line": 0 }, |
481 | "insertTextFormat": 2, | 481 | "start": { "character": 5, "line": 0 } |
482 | "newText": "\n/// $0", | ||
483 | "range": { | ||
484 | "end": { "character": 5, "line": 0 }, | ||
485 | "start": { "character": 5, "line": 0 } | ||
486 | } | ||
487 | } | ||
488 | ], | ||
489 | "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null } | ||
490 | } | 482 | } |
491 | ] | 483 | }]), |
492 | }), | ||
493 | ); | 484 | ); |
494 | let elapsed = start.elapsed(); | 485 | let elapsed = start.elapsed(); |
495 | assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed); | 486 | assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed); |
@@ -519,23 +510,14 @@ version = \"0.0.0\" | |||
519 | text_document: server.doc_id("src/main.rs"), | 510 | text_document: server.doc_id("src/main.rs"), |
520 | position: Position { line: 0, character: 8 }, | 511 | position: Position { line: 0, character: 8 }, |
521 | }, | 512 | }, |
522 | json!({ | 513 | json!([{ |
523 | "documentChanges": [ | 514 | "insertTextFormat": 2, |
524 | { | 515 | "newText": "\r\n/// $0", |
525 | "edits": [ | 516 | "range": { |
526 | { | 517 | "end": { "line": 0, "character": 8 }, |
527 | "insertTextFormat": 2, | 518 | "start": { "line": 0, "character": 8 } |
528 | "newText": "\r\n/// $0", | ||
529 | "range": { | ||
530 | "end": { "line": 0, "character": 8 }, | ||
531 | "start": { "line": 0, "character": 8 } | ||
532 | } | ||
533 | } | ||
534 | ], | ||
535 | "textDocument": { "uri": "file:///[..]src/main.rs", "version": null } | ||
536 | } | 519 | } |
537 | ] | 520 | }]), |
538 | }), | ||
539 | ); | 521 | ); |
540 | } | 522 | } |
541 | 523 | ||