mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
internal: Allow OnTypeFormatting to send SnippetTextEdit
But continue to send TextEdit only.
This commit is contained in:
parent
3de03d4c61
commit
636d4880c4
5 changed files with 38 additions and 15 deletions
|
@ -34,6 +34,11 @@ pub(crate) use on_enter::on_enter;
|
||||||
// Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
|
// Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
|
||||||
pub(crate) const TRIGGER_CHARS: &str = ".=>{";
|
pub(crate) const TRIGGER_CHARS: &str = ".=>{";
|
||||||
|
|
||||||
|
struct ExtendedTextEdit {
|
||||||
|
edit: TextEdit,
|
||||||
|
is_snippet: bool,
|
||||||
|
}
|
||||||
|
|
||||||
// Feature: On Typing Assists
|
// Feature: On Typing Assists
|
||||||
//
|
//
|
||||||
// Some features trigger on typing certain characters:
|
// Some features trigger on typing certain characters:
|
||||||
|
@ -68,22 +73,27 @@ pub(crate) fn on_char_typed(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let edit = on_char_typed_inner(file, position.offset, char_typed)?;
|
let edit = on_char_typed_inner(file, position.offset, char_typed)?;
|
||||||
Some(SourceChange::from_text_edit(position.file_id, edit))
|
let mut sc = SourceChange::from_text_edit(position.file_id, edit.edit);
|
||||||
|
sc.is_snippet = edit.is_snippet;
|
||||||
|
Some(sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_char_typed_inner(
|
fn on_char_typed_inner(
|
||||||
file: &Parse<SourceFile>,
|
file: &Parse<SourceFile>,
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
char_typed: char,
|
char_typed: char,
|
||||||
) -> Option<TextEdit> {
|
) -> Option<ExtendedTextEdit> {
|
||||||
|
fn conv(text_edit: Option<TextEdit>) -> Option<ExtendedTextEdit> {
|
||||||
|
Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
|
||||||
|
}
|
||||||
if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
|
if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match char_typed {
|
match char_typed {
|
||||||
'.' => on_dot_typed(&file.tree(), offset),
|
'.' => conv(on_dot_typed(&file.tree(), offset)),
|
||||||
'=' => on_eq_typed(&file.tree(), offset),
|
'=' => conv(on_eq_typed(&file.tree(), offset)),
|
||||||
'>' => on_arrow_typed(&file.tree(), offset),
|
'>' => conv(on_arrow_typed(&file.tree(), offset)),
|
||||||
'{' => on_opening_brace_typed(file, offset),
|
'{' => conv(on_opening_brace_typed(file, offset)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ pub(crate) fn handle_on_enter(
|
||||||
pub(crate) fn handle_on_type_formatting(
|
pub(crate) fn handle_on_type_formatting(
|
||||||
snap: GlobalStateSnapshot,
|
snap: GlobalStateSnapshot,
|
||||||
params: lsp_types::DocumentOnTypeFormattingParams,
|
params: lsp_types::DocumentOnTypeFormattingParams,
|
||||||
) -> Result<Option<Vec<lsp_types::TextEdit>>> {
|
) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
|
||||||
let _p = profile::span("handle_on_type_formatting");
|
let _p = profile::span("handle_on_type_formatting");
|
||||||
let mut position = from_proto::file_position(&snap, params.text_document_position)?;
|
let mut position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||||
let line_index = snap.file_line_index(position.file_id)?;
|
let line_index = snap.file_line_index(position.file_id)?;
|
||||||
|
@ -306,9 +306,9 @@ pub(crate) fn handle_on_type_formatting(
|
||||||
};
|
};
|
||||||
|
|
||||||
// This should be a single-file edit
|
// This should be a single-file edit
|
||||||
let (_, edit) = edit.source_file_edits.into_iter().next().unwrap();
|
let (_, text_edit) = edit.source_file_edits.into_iter().next().unwrap();
|
||||||
|
|
||||||
let change = to_proto::text_edit_vec(&line_index, edit);
|
let change = to_proto::snippet_text_edit_vec(&line_index, edit.is_snippet, text_edit);
|
||||||
Ok(Some(change))
|
Ok(Some(change))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use lsp_types::request::Request;
|
use lsp_types::request::Request;
|
||||||
use lsp_types::{
|
use lsp_types::{
|
||||||
notification::Notification, CodeActionKind, PartialResultParams, Position, Range,
|
notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams,
|
||||||
TextDocumentIdentifier, WorkDoneProgressParams,
|
PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -512,6 +512,19 @@ pub enum WorkspaceSymbolSearchKind {
|
||||||
AllSymbols,
|
AllSymbols,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The document on type formatting request is sent from the client to
|
||||||
|
/// the server to format parts of the document during typing. This is
|
||||||
|
/// almost same as lsp_types::request::OnTypeFormatting, but the
|
||||||
|
/// result has SnippetTextEdit in it instead of TextEdit.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum OnTypeFormatting {}
|
||||||
|
|
||||||
|
impl Request for OnTypeFormatting {
|
||||||
|
type Params = DocumentOnTypeFormattingParams;
|
||||||
|
type Result = Option<Vec<SnippetTextEdit>>;
|
||||||
|
const METHOD: &'static str = "textDocument/onTypeFormatting";
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct CompletionResolveData {
|
pub struct CompletionResolveData {
|
||||||
pub position: lsp_types::TextDocumentPositionParams,
|
pub position: lsp_types::TextDocumentPositionParams,
|
||||||
|
|
|
@ -605,7 +605,7 @@ impl GlobalState {
|
||||||
.on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
|
.on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
|
||||||
.on::<lsp_ext::MoveItem>(handlers::handle_move_item)
|
.on::<lsp_ext::MoveItem>(handlers::handle_move_item)
|
||||||
.on::<lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol)
|
.on::<lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol)
|
||||||
.on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
|
.on::<lsp_ext::OnTypeFormatting>(handlers::handle_on_type_formatting)
|
||||||
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
|
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
|
||||||
.on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
|
.on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
|
||||||
.on::<lsp_types::request::GotoDeclaration>(handlers::handle_goto_declaration)
|
.on::<lsp_types::request::GotoDeclaration>(handlers::handle_goto_declaration)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!---
|
<!---
|
||||||
lsp_ext.rs hash: 44e8238e4fbd4128
|
lsp_ext.rs hash: 2a188defec26cc7c
|
||||||
|
|
||||||
If you need to change the above hash to make the test pass, please check if you
|
If you need to change the above hash to make the test pass, please check if you
|
||||||
need to adjust this doc as well and ping this issue:
|
need to adjust this doc as well and ping this issue:
|
||||||
|
@ -47,7 +47,7 @@ If a language client does not know about `rust-analyzer`'s configuration options
|
||||||
|
|
||||||
**Experimental Client Capability:** `{ "snippetTextEdit": boolean }`
|
**Experimental Client Capability:** `{ "snippetTextEdit": boolean }`
|
||||||
|
|
||||||
If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
|
If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests and `TextEdit`s returned from `textDocument/onTypeFormatting` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface SnippetTextEdit extends TextEdit {
|
interface SnippetTextEdit extends TextEdit {
|
||||||
|
@ -63,7 +63,7 @@ export interface TextDocumentEdit {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When applying such code action, the editor should insert snippet, with tab stops and placeholder.
|
When applying such code action or text edit, the editor should insert snippet, with tab stops and placeholder.
|
||||||
At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`.
|
At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
Loading…
Reference in a new issue