aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-05-25 14:55:25 +0100
committerAleksey Kladov <[email protected]>2020-05-25 14:59:49 +0100
commit0ebb25b29b0988be89f42091fd373ea58d7ff9fb (patch)
tree06bb2df01d20d94ab38f2216d88555df03a826c9
parenta30bdd9795770329e4562d8bfca60ebe2e52dea1 (diff)
Document `parentModule` experimental LSP request
-rw-r--r--crates/rust-analyzer/src/caps.rs1
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs32
-rw-r--r--crates/rust-analyzer/src/to_proto.rs15
-rw-r--r--docs/dev/lsp-extensions.md40
-rw-r--r--editors/code/src/commands.ts6
-rw-r--r--editors/code/src/lsp_ext.ts2
7 files changed, 64 insertions, 38 deletions
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index d55cbb15f..345693524 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -86,6 +86,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
86 "joinLines": true, 86 "joinLines": true,
87 "ssr": true, 87 "ssr": true,
88 "onEnter": true, 88 "onEnter": true,
89 "parentModule": true,
89 })), 90 })),
90 } 91 }
91} 92}
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index c571c62ae..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
@@ -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 {}
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 3ccc95c23..1f910ff82 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -344,11 +344,8 @@ pub fn handle_goto_definition(
344 None => return Ok(None), 344 None => return Ok(None),
345 Some(it) => it, 345 Some(it) => it,
346 }; 346 };
347 let res = to_proto::goto_definition_response( 347 let src = FileRange { file_id: position.file_id, range: nav_info.range };
348 &world, 348 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
349 FileRange { file_id: position.file_id, range: nav_info.range },
350 nav_info.info,
351 )?;
352 Ok(Some(res)) 349 Ok(Some(res))
353} 350}
354 351
@@ -362,11 +359,8 @@ pub fn handle_goto_implementation(
362 None => return Ok(None), 359 None => return Ok(None),
363 Some(it) => it, 360 Some(it) => it,
364 }; 361 };
365 let res = to_proto::goto_definition_response( 362 let src = FileRange { file_id: position.file_id, range: nav_info.range };
366 &world, 363 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
367 FileRange { file_id: position.file_id, range: nav_info.range },
368 nav_info.info,
369 )?;
370 Ok(Some(res)) 364 Ok(Some(res))
371} 365}
372 366
@@ -380,26 +374,20 @@ pub fn handle_goto_type_definition(
380 None => return Ok(None), 374 None => return Ok(None),
381 Some(it) => it, 375 Some(it) => it,
382 }; 376 };
383 let res = to_proto::goto_definition_response( 377 let src = FileRange { file_id: position.file_id, range: nav_info.range };
384 &world, 378 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
385 FileRange { file_id: position.file_id, range: nav_info.range },
386 nav_info.info,
387 )?;
388 Ok(Some(res)) 379 Ok(Some(res))
389} 380}
390 381
391pub fn handle_parent_module( 382pub fn handle_parent_module(
392 world: WorldSnapshot, 383 world: WorldSnapshot,
393 params: lsp_types::TextDocumentPositionParams, 384 params: lsp_types::TextDocumentPositionParams,
394) -> Result<Vec<Location>> { 385) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
395 let _p = profile("handle_parent_module"); 386 let _p = profile("handle_parent_module");
396 let position = from_proto::file_position(&world, params)?; 387 let position = from_proto::file_position(&world, params)?;
397 world 388 let navs = world.analysis().parent_module(position)?;
398 .analysis() 389 let res = to_proto::goto_definition_response(&world, None, navs)?;
399 .parent_module(position)? 390 Ok(Some(res))
400 .into_iter()
401 .map(|it| to_proto::location(&world, it.file_range()))
402 .collect::<Result<Vec<_>>>()
403} 391}
404 392
405pub 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 39d58f1e0..bb7594dbf 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -403,13 +403,20 @@ pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_t
403 403
404pub(crate) fn location_link( 404pub(crate) fn location_link(
405 world: &WorldSnapshot, 405 world: &WorldSnapshot,
406 src: FileRange, 406 src: Option<FileRange>,
407 target: NavigationTarget, 407 target: NavigationTarget,
408) -> Result<lsp_types::LocationLink> { 408) -> Result<lsp_types::LocationLink> {
409 let src_location = location(world, src)?; 409 let origin_selection_range = match src {
410 Some(src) => {
411 let line_index = world.analysis().file_line_index(src.file_id)?;
412 let range = range(&line_index, src.range);
413 Some(range)
414 }
415 None => None,
416 };
410 let (target_uri, target_range, target_selection_range) = location_info(world, target)?; 417 let (target_uri, target_range, target_selection_range) = location_info(world, target)?;
411 let res = lsp_types::LocationLink { 418 let res = lsp_types::LocationLink {
412 origin_selection_range: Some(src_location.range), 419 origin_selection_range,
413 target_uri, 420 target_uri,
414 target_range, 421 target_range,
415 target_selection_range, 422 target_selection_range,
@@ -432,7 +439,7 @@ fn location_info(
432 439
433pub(crate) fn goto_definition_response( 440pub(crate) fn goto_definition_response(
434 world: &WorldSnapshot, 441 world: &WorldSnapshot,
435 src: FileRange, 442 src: Option<FileRange>,
436 targets: Vec<NavigationTarget>, 443 targets: Vec<NavigationTarget>,
437) -> Result<lsp_types::GotoDefinitionResponse> { 444) -> Result<lsp_types::GotoDefinitionResponse> {
438 if world.config.client_caps.location_link { 445 if world.config.client_caps.location_link {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 48147b173..209f470eb 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -87,6 +87,40 @@ Invoking code action at this position will yield two code actions for importing
87* Is a fixed two-level structure enough? 87* Is a fixed two-level structure enough?
88* Should we devise a general way to encode custom interaction protocols for GUI refactorings? 88* Should we devise a general way to encode custom interaction protocols for GUI refactorings?
89 89
90## Parent Module
91
92**Issue:** https://github.com/microsoft/language-server-protocol/issues/1002
93
94**Server Capability:** `{ "parentModule": boolean }`
95
96This request is send from client to server to handle "Goto Parent Module" editor action.
97
98**Method:** `experimental/parentModule`
99
100**Request:** `TextDocumentPositionParams`
101
102**Response:** `Location | Location[] | LocationLink[] | null`
103
104
105### Example
106
107```rust
108// src/main.rs
109mod foo;
110// src/foo.rs
111
112/* cursor here*/
113```
114
115`experimental/parentModule` returns a single `Link` to the `mod foo;` declaration.
116
117### Unresolved Question
118
119* An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules.
120 This is the approach IntelliJ Rust is takeing.
121 However, experience shows that super module (which generally has a feeling of navigation between files) should be separate.
122 If you want super module, but the cursor happens to be inside an overriden function, the behavior with single "gotoSuper" request is surprising.
123
90## Join Lines 124## Join Lines
91 125
92**Issue:** https://github.com/microsoft/language-server-protocol/issues/992 126**Issue:** https://github.com/microsoft/language-server-protocol/issues/992
@@ -108,11 +142,7 @@ interface JoinLinesParams {
108} 142}
109``` 143```
110 144
111**Response:** 145**Response:** `TextEdit[]`
112
113```typescript
114TextEdit[]
115```
116 146
117### Example 147### Example
118 148
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 49e3845d5..86302db37 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -138,10 +138,10 @@ export function parentModule(ctx: Ctx): Cmd {
138 ), 138 ),
139 }); 139 });
140 const loc = response[0]; 140 const loc = response[0];
141 if (loc == null) return; 141 if (!loc) return;
142 142
143 const uri = client.protocol2CodeConverter.asUri(loc.uri); 143 const uri = client.protocol2CodeConverter.asUri(loc.targetUri);
144 const range = client.protocol2CodeConverter.asRange(loc.range); 144 const range = client.protocol2CodeConverter.asRange(loc.targetRange);
145 145
146 const doc = await vscode.workspace.openTextDocument(uri); 146 const doc = await vscode.workspace.openTextDocument(uri);
147 const e = await vscode.window.showTextDocument(doc); 147 const e = await vscode.window.showTextDocument(doc);
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 2a0663261..4da12eb30 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -31,7 +31,7 @@ export interface MatchingBraceParams {
31} 31}
32export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position[], void>("experimental/matchingBrace"); 32export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position[], void>("experimental/matchingBrace");
33 33
34export const parentModule = new lc.RequestType<lc.TextDocumentPositionParams, lc.Location[], void>("rust-analyzer/parentModule"); 34export const parentModule = new lc.RequestType<lc.TextDocumentPositionParams, lc.LocationLink[], void>("experimental/parentModule");
35 35
36export interface JoinLinesParams { 36export interface JoinLinesParams {
37 textDocument: lc.TextDocumentIdentifier; 37 textDocument: lc.TextDocumentIdentifier;