Document matchingBrace LSP request

This commit is contained in:
Aleksey Kladov 2020-05-24 16:18:46 +02:00
parent 7e862626cc
commit 9342273616
6 changed files with 63 additions and 19 deletions

View file

@ -60,19 +60,19 @@ pub struct ExpandMacroParams {
pub position: Option<Position>, pub position: Option<Position>,
} }
pub enum FindMatchingBrace {} pub enum MatchingBrace {}
impl Request for FindMatchingBrace { impl Request for MatchingBrace {
type Params = FindMatchingBraceParams; type Params = MatchingBraceParams;
type Result = Vec<Position>; type Result = Vec<Position>;
const METHOD: &'static str = "rust-analyzer/findMatchingBrace"; const METHOD: &'static str = "experimental/matchingBrace";
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct FindMatchingBraceParams { pub struct MatchingBraceParams {
pub text_document: TextDocumentIdentifier, pub text_document: TextDocumentIdentifier,
pub offsets: Vec<Position>, pub positions: Vec<Position>,
} }
pub enum ParentModule {} pub enum ParentModule {}

View file

@ -509,8 +509,8 @@ fn on_request(
.on_sync::<lsp_types::request::SelectionRangeRequest>(|s, p| { .on_sync::<lsp_types::request::SelectionRangeRequest>(|s, p| {
handlers::handle_selection_range(s.snapshot(), p) handlers::handle_selection_range(s.snapshot(), p)
})? })?
.on_sync::<lsp_ext::FindMatchingBrace>(|s, p| { .on_sync::<lsp_ext::MatchingBrace>(|s, p| {
handlers::handle_find_matching_brace(s.snapshot(), p) handlers::handle_matching_brace(s.snapshot(), p)
})? })?
.on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)? .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)?
.on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)? .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)?

View file

@ -126,15 +126,15 @@ pub fn handle_selection_range(
Ok(Some(res?)) Ok(Some(res?))
} }
pub fn handle_find_matching_brace( pub fn handle_matching_brace(
world: WorldSnapshot, world: WorldSnapshot,
params: lsp_ext::FindMatchingBraceParams, params: lsp_ext::MatchingBraceParams,
) -> Result<Vec<Position>> { ) -> Result<Vec<Position>> {
let _p = profile("handle_find_matching_brace"); let _p = profile("handle_matching_brace");
let file_id = from_proto::file_id(&world, &params.text_document.uri)?; let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
let line_index = world.analysis().file_line_index(file_id)?; let line_index = world.analysis().file_line_index(file_id)?;
let res = params let res = params
.offsets .positions
.into_iter() .into_iter()
.map(|position| { .map(|position| {
let offset = from_proto::offset(&line_index, position); let offset = from_proto::offset(&line_index, position);

View file

@ -95,7 +95,7 @@ Invoking code action at this position will yield two code actions for importing
This request is send from client to server to handle "Join Lines" editor action. This request is send from client to server to handle "Join Lines" editor action.
**Method:** `experimental/JoinLines` **Method:** `experimental/joinLines`
**Request:** **Request:**
@ -172,3 +172,48 @@ SSR with query `foo($a:expr, $b:expr) ==>> ($a).foo($b)` will transform, eg `foo
* Probably needs search without replace mode * Probably needs search without replace mode
* Needs a way to limit the scope to certain files. * Needs a way to limit the scope to certain files.
## Matching Brace
**Issue:** https://github.com/microsoft/language-server-protocol/issues/999
**Server Capability:** `{ "matchingBrace": boolean }`
This request is send from client to server to handle "Matching Brace" editor action.
**Method:** `experimental/matchingBrace`
**Request:**
```typescript
interface MatchingBraceParams {
textDocument: TextDocumentIdentifier,
/// Position for each cursor
positions: Position[],
}
```
**Response:**
```typescript
Position[]
```
### Example
```rust
fn main() {
let x: Vec<()>/*cursor here*/ = vec![]
}
```
`experimental/matchingBrace` yields the position of `<`.
In many cases, matching braces can be handled by the editor.
However, some cases (like disambiguating between generics and comparison operations) need a real parser.
Moreover, it would be cool if editors didn't need to implement even basic language parsing
### Unresolved Question
* Should we return a a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair?
This is how `SelectionRange` request works.
* Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs?

View file

@ -9,9 +9,9 @@ export function matchingBrace(ctx: Ctx): Cmd {
const client = ctx.client; const client = ctx.client;
if (!editor || !client) return; if (!editor || !client) return;
const response = await client.sendRequest(ra.findMatchingBrace, { const response = await client.sendRequest(ra.matchingBrace, {
textDocument: { uri: editor.document.uri.toString() }, textDocument: { uri: editor.document.uri.toString() },
offsets: editor.selections.map(s => positions: editor.selections.map(s =>
client.code2ProtocolConverter.asPosition(s.active), client.code2ProtocolConverter.asPosition(s.active),
), ),
}); });

View file

@ -40,12 +40,11 @@ export interface ExpandedMacro {
export const expandMacro = request<ExpandMacroParams, Option<ExpandedMacro>>("expandMacro"); export const expandMacro = request<ExpandMacroParams, Option<ExpandedMacro>>("expandMacro");
export interface FindMatchingBraceParams { export interface MatchingBraceParams {
textDocument: lc.TextDocumentIdentifier; textDocument: lc.TextDocumentIdentifier;
offsets: Vec<lc.Position>; positions: lc.Position[];
} }
export const findMatchingBrace = request<FindMatchingBraceParams, Vec<lc.Position>>("findMatchingBrace"); export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position[], unknown>('experimental/matchingBrace');
export interface PublishDecorationsParams { export interface PublishDecorationsParams {
uri: string; uri: string;