mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #4611
4611: Document `parentModule` experimental LSP request r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
19700b2e31
7 changed files with 64 additions and 38 deletions
|
@ -86,6 +86,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
|
||||||
"joinLines": true,
|
"joinLines": true,
|
||||||
"ssr": true,
|
"ssr": true,
|
||||||
"onEnter": true,
|
"onEnter": true,
|
||||||
|
"parentModule": true,
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use lsp_types::request::Request;
|
use lsp_types::request::Request;
|
||||||
use lsp_types::{Location, Position, Range, TextDocumentIdentifier};
|
use lsp_types::{Position, Range, TextDocumentIdentifier};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@ pub enum ParentModule {}
|
||||||
|
|
||||||
impl Request for ParentModule {
|
impl Request for ParentModule {
|
||||||
type Params = lsp_types::TextDocumentPositionParams;
|
type Params = lsp_types::TextDocumentPositionParams;
|
||||||
type Result = Vec<Location>;
|
type Result = Option<lsp_types::GotoDefinitionResponse>;
|
||||||
const METHOD: &'static str = "rust-analyzer/parentModule";
|
const METHOD: &'static str = "experimental/parentModule";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum JoinLines {}
|
pub enum JoinLines {}
|
||||||
|
|
|
@ -344,11 +344,8 @@ pub fn handle_goto_definition(
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
};
|
};
|
||||||
let res = to_proto::goto_definition_response(
|
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||||
&world,
|
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||||
FileRange { file_id: position.file_id, range: nav_info.range },
|
|
||||||
nav_info.info,
|
|
||||||
)?;
|
|
||||||
Ok(Some(res))
|
Ok(Some(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,11 +359,8 @@ pub fn handle_goto_implementation(
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
};
|
};
|
||||||
let res = to_proto::goto_definition_response(
|
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||||
&world,
|
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||||
FileRange { file_id: position.file_id, range: nav_info.range },
|
|
||||||
nav_info.info,
|
|
||||||
)?;
|
|
||||||
Ok(Some(res))
|
Ok(Some(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,26 +374,20 @@ pub fn handle_goto_type_definition(
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
};
|
};
|
||||||
let res = to_proto::goto_definition_response(
|
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||||
&world,
|
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||||
FileRange { file_id: position.file_id, range: nav_info.range },
|
|
||||||
nav_info.info,
|
|
||||||
)?;
|
|
||||||
Ok(Some(res))
|
Ok(Some(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_parent_module(
|
pub fn handle_parent_module(
|
||||||
world: WorldSnapshot,
|
world: WorldSnapshot,
|
||||||
params: lsp_types::TextDocumentPositionParams,
|
params: lsp_types::TextDocumentPositionParams,
|
||||||
) -> Result<Vec<Location>> {
|
) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
|
||||||
let _p = profile("handle_parent_module");
|
let _p = profile("handle_parent_module");
|
||||||
let position = from_proto::file_position(&world, params)?;
|
let position = from_proto::file_position(&world, params)?;
|
||||||
world
|
let navs = world.analysis().parent_module(position)?;
|
||||||
.analysis()
|
let res = to_proto::goto_definition_response(&world, None, navs)?;
|
||||||
.parent_module(position)?
|
Ok(Some(res))
|
||||||
.into_iter()
|
|
||||||
.map(|it| to_proto::location(&world, it.file_range()))
|
|
||||||
.collect::<Result<Vec<_>>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_runnables(
|
pub fn handle_runnables(
|
||||||
|
|
|
@ -403,13 +403,20 @@ pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_t
|
||||||
|
|
||||||
pub(crate) fn location_link(
|
pub(crate) fn location_link(
|
||||||
world: &WorldSnapshot,
|
world: &WorldSnapshot,
|
||||||
src: FileRange,
|
src: Option<FileRange>,
|
||||||
target: NavigationTarget,
|
target: NavigationTarget,
|
||||||
) -> Result<lsp_types::LocationLink> {
|
) -> Result<lsp_types::LocationLink> {
|
||||||
let src_location = location(world, src)?;
|
let origin_selection_range = match src {
|
||||||
|
Some(src) => {
|
||||||
|
let line_index = world.analysis().file_line_index(src.file_id)?;
|
||||||
|
let range = range(&line_index, src.range);
|
||||||
|
Some(range)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
let (target_uri, target_range, target_selection_range) = location_info(world, target)?;
|
let (target_uri, target_range, target_selection_range) = location_info(world, target)?;
|
||||||
let res = lsp_types::LocationLink {
|
let res = lsp_types::LocationLink {
|
||||||
origin_selection_range: Some(src_location.range),
|
origin_selection_range,
|
||||||
target_uri,
|
target_uri,
|
||||||
target_range,
|
target_range,
|
||||||
target_selection_range,
|
target_selection_range,
|
||||||
|
@ -432,7 +439,7 @@ fn location_info(
|
||||||
|
|
||||||
pub(crate) fn goto_definition_response(
|
pub(crate) fn goto_definition_response(
|
||||||
world: &WorldSnapshot,
|
world: &WorldSnapshot,
|
||||||
src: FileRange,
|
src: Option<FileRange>,
|
||||||
targets: Vec<NavigationTarget>,
|
targets: Vec<NavigationTarget>,
|
||||||
) -> Result<lsp_types::GotoDefinitionResponse> {
|
) -> Result<lsp_types::GotoDefinitionResponse> {
|
||||||
if world.config.client_caps.location_link {
|
if world.config.client_caps.location_link {
|
||||||
|
|
|
@ -87,6 +87,40 @@ Invoking code action at this position will yield two code actions for importing
|
||||||
* Is a fixed two-level structure enough?
|
* Is a fixed two-level structure enough?
|
||||||
* Should we devise a general way to encode custom interaction protocols for GUI refactorings?
|
* Should we devise a general way to encode custom interaction protocols for GUI refactorings?
|
||||||
|
|
||||||
|
## Parent Module
|
||||||
|
|
||||||
|
**Issue:** https://github.com/microsoft/language-server-protocol/issues/1002
|
||||||
|
|
||||||
|
**Server Capability:** `{ "parentModule": boolean }`
|
||||||
|
|
||||||
|
This request is send from client to server to handle "Goto Parent Module" editor action.
|
||||||
|
|
||||||
|
**Method:** `experimental/parentModule`
|
||||||
|
|
||||||
|
**Request:** `TextDocumentPositionParams`
|
||||||
|
|
||||||
|
**Response:** `Location | Location[] | LocationLink[] | null`
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/main.rs
|
||||||
|
mod foo;
|
||||||
|
// src/foo.rs
|
||||||
|
|
||||||
|
/* cursor here*/
|
||||||
|
```
|
||||||
|
|
||||||
|
`experimental/parentModule` returns a single `Link` to the `mod foo;` declaration.
|
||||||
|
|
||||||
|
### Unresolved Question
|
||||||
|
|
||||||
|
* An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules.
|
||||||
|
This is the approach IntelliJ Rust is takeing.
|
||||||
|
However, experience shows that super module (which generally has a feeling of navigation between files) should be separate.
|
||||||
|
If you want super module, but the cursor happens to be inside an overriden function, the behavior with single "gotoSuper" request is surprising.
|
||||||
|
|
||||||
## Join Lines
|
## Join Lines
|
||||||
|
|
||||||
**Issue:** https://github.com/microsoft/language-server-protocol/issues/992
|
**Issue:** https://github.com/microsoft/language-server-protocol/issues/992
|
||||||
|
@ -108,11 +142,7 @@ interface JoinLinesParams {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response:**
|
**Response:** `TextEdit[]`
|
||||||
|
|
||||||
```typescript
|
|
||||||
TextEdit[]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
|
|
|
@ -138,10 +138,10 @@ export function parentModule(ctx: Ctx): Cmd {
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
const loc = response[0];
|
const loc = response[0];
|
||||||
if (loc == null) return;
|
if (!loc) return;
|
||||||
|
|
||||||
const uri = client.protocol2CodeConverter.asUri(loc.uri);
|
const uri = client.protocol2CodeConverter.asUri(loc.targetUri);
|
||||||
const range = client.protocol2CodeConverter.asRange(loc.range);
|
const range = client.protocol2CodeConverter.asRange(loc.targetRange);
|
||||||
|
|
||||||
const doc = await vscode.workspace.openTextDocument(uri);
|
const doc = await vscode.workspace.openTextDocument(uri);
|
||||||
const e = await vscode.window.showTextDocument(doc);
|
const e = await vscode.window.showTextDocument(doc);
|
||||||
|
|
|
@ -31,7 +31,7 @@ export interface MatchingBraceParams {
|
||||||
}
|
}
|
||||||
export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position[], void>("experimental/matchingBrace");
|
export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position[], void>("experimental/matchingBrace");
|
||||||
|
|
||||||
export const parentModule = new lc.RequestType<lc.TextDocumentPositionParams, lc.Location[], void>("rust-analyzer/parentModule");
|
export const parentModule = new lc.RequestType<lc.TextDocumentPositionParams, lc.LocationLink[], void>("experimental/parentModule");
|
||||||
|
|
||||||
export interface JoinLinesParams {
|
export interface JoinLinesParams {
|
||||||
textDocument: lc.TextDocumentIdentifier;
|
textDocument: lc.TextDocumentIdentifier;
|
||||||
|
|
Loading…
Reference in a new issue