mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
Add typing handler for param list pipe
This commit is contained in:
parent
5dc5107e9c
commit
54dbf1b446
6 changed files with 69 additions and 29 deletions
|
@ -402,6 +402,8 @@ impl Analysis {
|
||||||
self.with_db(|db| typing::on_enter(db, position))
|
self.with_db(|db| typing::on_enter(db, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const SUPPORTED_TRIGGER_CHARS: &'static str = typing::TRIGGER_CHARS;
|
||||||
|
|
||||||
/// Returns an edit which should be applied after a character was typed.
|
/// Returns an edit which should be applied after a character was typed.
|
||||||
///
|
///
|
||||||
/// This is useful for some on-the-fly fixups, like adding `;` to `let =`
|
/// This is useful for some on-the-fly fixups, like adding `;` to `let =`
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::SourceChange;
|
||||||
pub(crate) use on_enter::on_enter;
|
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 {
|
struct ExtendedTextEdit {
|
||||||
edit: TextEdit,
|
edit: TextEdit,
|
||||||
|
@ -99,6 +99,7 @@ fn on_char_typed_(
|
||||||
'=' => on_eq_typed(&file.tree(), offset),
|
'=' => on_eq_typed(&file.tree(), offset),
|
||||||
'>' => on_right_angle_typed(&file.tree(), offset),
|
'>' => on_right_angle_typed(&file.tree(), offset),
|
||||||
'{' | '(' | '<' => on_opening_delimiter_typed(file, offset, char_typed, edition),
|
'{' | '(' | '<' => on_opening_delimiter_typed(file, offset, char_typed, edition),
|
||||||
|
'|' => on_pipe_typed(&file.tree(), offset),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.map(conv)
|
.map(conv)
|
||||||
|
@ -212,10 +213,6 @@ fn on_delimited_node_typed(
|
||||||
// FIXME: use a snippet completion instead of this hack here.
|
// FIXME: use a snippet completion instead of this hack here.
|
||||||
fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
let text = file.syntax().text();
|
let text = file.syntax().text();
|
||||||
if !stdx::always!(text.char_at(offset) == Some('=')) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let has_newline = iter::successors(Some(offset), |&offset| Some(offset + TextSize::new(1)))
|
let has_newline = iter::successors(Some(offset), |&offset| Some(offset + TextSize::new(1)))
|
||||||
.filter_map(|offset| text.char_at(offset))
|
.filter_map(|offset| text.char_at(offset))
|
||||||
.find(|&c| !c.is_whitespace() || c == '\n')
|
.find(|&c| !c.is_whitespace() || c == '\n')
|
||||||
|
@ -308,9 +305,6 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
|
|
||||||
/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
|
/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
|
||||||
fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
if !stdx::always!(file.syntax().text().char_at(offset) == Some('.')) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let whitespace =
|
let whitespace =
|
||||||
file.syntax().token_at_offset(offset).left_biased().and_then(ast::Whitespace::cast)?;
|
file.syntax().token_at_offset(offset).left_biased().and_then(ast::Whitespace::cast)?;
|
||||||
|
|
||||||
|
@ -380,7 +374,9 @@ fn on_left_angle_typed(
|
||||||
if ancestors_at_offset(file.syntax(), offset)
|
if ancestors_at_offset(file.syntax(), offset)
|
||||||
.take_while(|n| !ast::Item::can_cast(n.kind()))
|
.take_while(|n| !ast::Item::can_cast(n.kind()))
|
||||||
.any(|n| {
|
.any(|n| {
|
||||||
ast::GenericParamList::can_cast(n.kind()) || ast::GenericArgList::can_cast(n.kind())
|
ast::GenericParamList::can_cast(n.kind())
|
||||||
|
|| ast::GenericArgList::can_cast(n.kind())
|
||||||
|
|| ast::UseBoundGenericArgs::can_cast(n.kind())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
// Insert the closing bracket right after
|
// Insert the closing bracket right after
|
||||||
|
@ -390,12 +386,21 @@ fn on_left_angle_typed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_pipe_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
|
let pipe_token = file.syntax().token_at_offset(offset).right_biased()?;
|
||||||
|
if pipe_token.kind() != SyntaxKind::PIPE {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if pipe_token.parent().and_then(ast::ParamList::cast)?.r_paren_token().is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let after_lpipe = offset + TextSize::of('|');
|
||||||
|
Some(TextEdit::insert(after_lpipe, "|".to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }`
|
/// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }`
|
||||||
fn on_right_angle_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
fn on_right_angle_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
|
||||||
let file_text = file.syntax().text();
|
let file_text = file.syntax().text();
|
||||||
if !stdx::always!(file_text.char_at(offset) == Some('>')) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let after_arrow = offset + TextSize::of('>');
|
let after_arrow = offset + TextSize::of('>');
|
||||||
if file_text.char_at(after_arrow) != Some('{') {
|
if file_text.char_at(after_arrow) != Some('{') {
|
||||||
return None;
|
return None;
|
||||||
|
@ -1527,6 +1532,44 @@ fn foo() {
|
||||||
)
|
)
|
||||||
$0
|
$0
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_pipe_param_list() {
|
||||||
|
type_char(
|
||||||
|
'|',
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
||
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
type_char(
|
||||||
|
'|',
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
$0 a
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
|| a
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
type_char_noop(
|
||||||
|
'|',
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
let $0
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,8 +308,8 @@ config_data! {
|
||||||
/// Show documentation.
|
/// Show documentation.
|
||||||
signatureInfo_documentation_enable: bool = true,
|
signatureInfo_documentation_enable: bool = true,
|
||||||
|
|
||||||
/// Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. Setting this to a string will disable typing assists for the specified characters.
|
/// Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.
|
||||||
typing_excludeChars: Option<String> = None,
|
typing_excludeChars: Option<String> = Some('<'.to_string()),
|
||||||
|
|
||||||
|
|
||||||
/// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].
|
/// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].
|
||||||
|
|
|
@ -72,9 +72,12 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
|
||||||
RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)),
|
RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)),
|
||||||
_ => Some(OneOf::Left(false)),
|
_ => Some(OneOf::Left(false)),
|
||||||
},
|
},
|
||||||
document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
|
document_on_type_formatting_provider: Some({
|
||||||
first_trigger_character: "=".to_owned(),
|
let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.chars();
|
||||||
more_trigger_character: Some(more_trigger_character(config)),
|
DocumentOnTypeFormattingOptions {
|
||||||
|
first_trigger_character: chars.next().unwrap().to_string(),
|
||||||
|
more_trigger_character: Some(chars.map(|c| c.to_string()).collect()),
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
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)),
|
||||||
|
@ -528,11 +531,3 @@ impl ClientCapabilities {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn more_trigger_character(config: &Config) -> Vec<String> {
|
|
||||||
let mut res = vec![".".to_owned(), ">".to_owned(), "{".to_owned(), "(".to_owned()];
|
|
||||||
if config.snippet_cap().is_some() {
|
|
||||||
res.push("<".to_owned());
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
|
@ -992,10 +992,10 @@ Show full signature of the callable. Only shows parameters if disabled.
|
||||||
--
|
--
|
||||||
Show documentation.
|
Show documentation.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.typing.excludeChars]]rust-analyzer.typing.excludeChars (default: `null`)::
|
[[rust-analyzer.typing.excludeChars]]rust-analyzer.typing.excludeChars (default: `"<"`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. Setting this to a string will disable typing assists for the specified characters.
|
Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.workspace.discoverConfig]]rust-analyzer.workspace.discoverConfig (default: `null`)::
|
[[rust-analyzer.workspace.discoverConfig]]rust-analyzer.workspace.discoverConfig (default: `null`)::
|
||||||
+
|
+
|
||||||
|
|
|
@ -2606,8 +2606,8 @@
|
||||||
"title": "typing",
|
"title": "typing",
|
||||||
"properties": {
|
"properties": {
|
||||||
"rust-analyzer.typing.excludeChars": {
|
"rust-analyzer.typing.excludeChars": {
|
||||||
"markdownDescription": "Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. Setting this to a string will disable typing assists for the specified characters.",
|
"markdownDescription": "Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.",
|
||||||
"default": null,
|
"default": "<",
|
||||||
"type": [
|
"type": [
|
||||||
"null",
|
"null",
|
||||||
"string"
|
"string"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue