aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/lib.rs3
-rw-r--r--crates/ra_ide/src/typing/on_enter.rs11
-rw-r--r--crates/rust-analyzer/src/caps.rs2
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs12
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs57
-rw-r--r--crates/rust-analyzer/src/to_proto.rs27
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs46
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};
12use ra_text_edit::TextEdit; 12use ra_text_edit::TextEdit;
13 13
14use crate::{SourceChange, SourceFileEdit}; 14pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> {
15
16pub(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
49fn followed_by_comment(comment: &ast::Comment) -> bool { 45fn 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 @@
3use std::{collections::HashMap, path::PathBuf}; 3use std::{collections::HashMap, path::PathBuf};
4 4
5use lsp_types::request::Request; 5use lsp_types::request::Request;
6use lsp_types::{Location, Position, Range, TextDocumentIdentifier}; 6use lsp_types::{Position, Range, TextDocumentIdentifier};
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9 9
@@ -50,7 +50,7 @@ impl Request for ExpandMacro {
50#[serde(rename_all = "camelCase")] 50#[serde(rename_all = "camelCase")]
51pub struct ExpandMacroParams { 51pub 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
80impl Request for ParentModule { 80impl 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
86pub enum JoinLines {} 86pub enum JoinLines {}
@@ -102,8 +102,8 @@ pub enum OnEnter {}
102 102
103impl Request for OnEnter { 103impl 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
109pub enum Runnables {} 109pub 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, &params.text_document.uri)?; 73 let file_id = from_proto::file_id(&world, &params.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
86pub fn handle_selection_range( 81pub fn handle_selection_range(
@@ -174,13 +169,17 @@ pub fn handle_join_lines(
174pub fn handle_on_enter( 169pub 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
392pub fn handle_parent_module( 382pub 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
406pub fn handle_runnables( 393pub 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
138pub(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
138pub(crate) fn completion_item( 150pub(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
393pub(crate) fn location_link( 405pub(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
422pub(crate) fn goto_definition_response( 441pub(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