mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Autoclose blocks when typing {
This commit is contained in:
parent
8e900cb4a1
commit
36cd724b7b
3 changed files with 47 additions and 3 deletions
|
@ -33,7 +33,8 @@ use crate::SourceChange;
|
||||||
|
|
||||||
pub(crate) use on_enter::on_enter;
|
pub(crate) use on_enter::on_enter;
|
||||||
|
|
||||||
pub(crate) const TRIGGER_CHARS: &str = ".=>";
|
// Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
|
||||||
|
pub(crate) const TRIGGER_CHARS: &str = ".=>{";
|
||||||
|
|
||||||
// Feature: On Typing Assists
|
// Feature: On Typing Assists
|
||||||
//
|
//
|
||||||
|
@ -70,10 +71,47 @@ fn on_char_typed_inner(file: &SourceFile, offset: TextSize, char_typed: char) ->
|
||||||
'.' => on_dot_typed(file, offset),
|
'.' => on_dot_typed(file, offset),
|
||||||
'=' => on_eq_typed(file, offset),
|
'=' => on_eq_typed(file, offset),
|
||||||
'>' => on_arrow_typed(file, offset),
|
'>' => on_arrow_typed(file, offset),
|
||||||
|
'{' => on_opening_brace_typed(file, offset),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a closing `}` when the user types an opening `{`, wrapping an existing expression in a
|
||||||
|
/// block.
|
||||||
|
fn on_opening_brace_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
|
assert_eq!(file.syntax().text().char_at(offset), Some('{'));
|
||||||
|
let brace_token = file.syntax().token_at_offset(offset).right_biased()?;
|
||||||
|
let block = ast::BlockExpr::cast(brace_token.parent()?)?;
|
||||||
|
|
||||||
|
// We expect a block expression enclosing exactly 1 preexisting expression. It can be parsed as
|
||||||
|
// either the trailing expr or an ExprStmt.
|
||||||
|
let offset = {
|
||||||
|
match block.tail_expr() {
|
||||||
|
Some(expr) => {
|
||||||
|
if block.statements().next().is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
expr.syntax().text_range().end()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if block.statements().count() != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match block.statements().next()? {
|
||||||
|
ast::Stmt::ExprStmt(it) => {
|
||||||
|
// Use the expression span to place `}` before the `;`
|
||||||
|
it.expr()?.syntax().text_range().end()
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(TextEdit::insert(offset, "}".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an edit which should be applied after `=` was typed. Primarily,
|
/// Returns an edit which should be applied after `=` was typed. Primarily,
|
||||||
/// this works when adding `let =`.
|
/// this works when adding `let =`.
|
||||||
// FIXME: use a snippet completion instead of this hack here.
|
// FIXME: use a snippet completion instead of this hack here.
|
||||||
|
@ -373,4 +411,11 @@ fn main() {
|
||||||
fn adds_space_after_return_type() {
|
fn adds_space_after_return_type() {
|
||||||
type_char('>', "fn foo() -$0{ 92 }", "fn foo() -> { 92 }")
|
type_char('>', "fn foo() -$0{ 92 }", "fn foo() -> { 92 }")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn adds_closing_brace() {
|
||||||
|
type_char('{', r"fn f() { match () { _ => $0() } }", r"fn f() { match () { _ => {()} } }");
|
||||||
|
type_char('{', r"fn f() { $0(); }", r"fn f() { {()}; }");
|
||||||
|
type_char('{', r"fn f() { let x = $0(); }", r"fn f() { let x = {()}; }");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
|
||||||
document_range_formatting_provider: None,
|
document_range_formatting_provider: None,
|
||||||
document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
|
document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
|
||||||
first_trigger_character: "=".to_string(),
|
first_trigger_character: "=".to_string(),
|
||||||
more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
|
more_trigger_character: Some(vec![".".to_string(), ">".to_string(), "{".to_string()]),
|
||||||
}),
|
}),
|
||||||
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
|
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
|
||||||
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
|
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
|
||||||
|
|
|
@ -231,7 +231,6 @@ pub(crate) fn handle_on_enter(
|
||||||
Ok(Some(edit))
|
Ok(Some(edit))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`.
|
|
||||||
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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue