Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/postfix.rs')
-rw-r--r--crates/ide-completion/src/completions/postfix.rs96
1 files changed, 61 insertions, 35 deletions
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index 28e2853096..54be7d2fbc 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -5,24 +5,24 @@ mod format_like;
use base_db::SourceDatabase;
use hir::{ItemInNs, Semantics};
use ide_db::{
+ RootDatabase, SnippetCap,
documentation::{Documentation, HasDocs},
imports::insert_use::ImportScope,
text_edit::TextEdit,
ty_filter::TryEnum,
- RootDatabase, SnippetCap,
};
use stdx::never;
use syntax::{
- ast::{self, AstNode, AstToken},
SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR},
TextRange, TextSize,
+ ast::{self, AstNode, AstToken},
};
use crate::{
+ CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
completions::postfix::format_like::add_format_like_completions,
context::{BreakableKind, CompletionContext, DotAccess, DotAccessKind},
item::{Builder, CompletionRelevancePostfixMatch},
- CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
};
pub(crate) fn complete_postfix(
@@ -155,22 +155,29 @@ pub(crate) fn complete_postfix(
postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc, ctx.db);
postfix_snippet("deref", "*expr", &format!("*{receiver_text}")).add_to(acc, ctx.db);
- let mut unsafe_should_be_wrapped = true;
+ let mut block_should_be_wrapped = true;
if dot_receiver.syntax().kind() == BLOCK_EXPR {
- unsafe_should_be_wrapped = false;
+ block_should_be_wrapped = false;
if let Some(parent) = dot_receiver.syntax().parent() {
if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) {
- unsafe_should_be_wrapped = true;
+ block_should_be_wrapped = true;
}
}
};
- let unsafe_completion_string = if unsafe_should_be_wrapped {
+ let unsafe_completion_string = if block_should_be_wrapped {
format!("unsafe {{ {receiver_text} }}")
} else {
format!("unsafe {receiver_text}")
};
postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc, ctx.db);
+ let const_completion_string = if block_should_be_wrapped {
+ format!("const {{ {receiver_text} }}")
+ } else {
+ format!("const {receiver_text}")
+ };
+ postfix_snippet("const", "const {}", &const_completion_string).add_to(acc, ctx.db);
+
// The rest of the postfix completions create an expression that moves an argument,
// so it's better to consider references now to avoid breaking the compilation
@@ -276,8 +283,8 @@ fn get_receiver_text(
if receiver_is_ambiguous_float_literal {
range.range = TextRange::at(range.range.start(), range.range.len() - TextSize::of('.'))
}
- let file_text = sema.db.file_text(range.file_id.file_id());
- let mut text = file_text[range.range].to_owned();
+ let file_text = sema.db.file_text(range.file_id.file_id(sema.db));
+ let mut text = file_text.text(sema.db)[range.range].to_owned();
// The receiver texts should be interpreted as-is, as they are expected to be
// normal Rust expressions.
@@ -414,8 +421,8 @@ mod tests {
use expect_test::expect;
use crate::{
- tests::{check, check_edit, check_edit_with_config, TEST_CONFIG},
CompletionConfig, Snippet,
+ tests::{TEST_CONFIG, check, check_edit, check_edit_with_config},
};
#[test]
@@ -430,6 +437,7 @@ fn main() {
expect![[r#"
sn box Box::new(expr)
sn call function(expr)
+ sn const const {}
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn deref *expr
@@ -463,6 +471,7 @@ fn main() {
expect![[r#"
sn box Box::new(expr)
sn call function(expr)
+ sn const const {}
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn deref *expr
@@ -490,6 +499,7 @@ fn main() {
expect![[r#"
sn box Box::new(expr)
sn call function(expr)
+ sn const const {}
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn deref *expr
@@ -516,6 +526,7 @@ fn main() {
expect![[r#"
sn box Box::new(expr)
sn call function(expr)
+ sn const const {}
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn deref *expr
@@ -653,59 +664,74 @@ fn main() {
#[test]
fn postfix_completion_for_unsafe() {
- check_edit("unsafe", r#"fn main() { foo.$0 }"#, r#"fn main() { unsafe { foo } }"#);
- check_edit("unsafe", r#"fn main() { { foo }.$0 }"#, r#"fn main() { unsafe { foo } }"#);
+ postfix_completion_for_block("unsafe");
+ }
+
+ #[test]
+ fn postfix_completion_for_const() {
+ postfix_completion_for_block("const");
+ }
+
+ fn postfix_completion_for_block(kind: &str) {
+ check_edit(kind, r#"fn main() { foo.$0 }"#, &format!("fn main() {{ {kind} {{ foo }} }}"));
check_edit(
- "unsafe",
+ kind,
+ r#"fn main() { { foo }.$0 }"#,
+ &format!("fn main() {{ {kind} {{ foo }} }}"),
+ );
+ check_edit(
+ kind,
r#"fn main() { if x { foo }.$0 }"#,
- r#"fn main() { unsafe { if x { foo } } }"#,
+ &format!("fn main() {{ {kind} {{ if x {{ foo }} }} }}"),
);
check_edit(
- "unsafe",
+ kind,
r#"fn main() { loop { foo }.$0 }"#,
- r#"fn main() { unsafe { loop { foo } } }"#,
+ &format!("fn main() {{ {kind} {{ loop {{ foo }} }} }}"),
);
check_edit(
- "unsafe",
+ kind,
r#"fn main() { if true {}.$0 }"#,
- r#"fn main() { unsafe { if true {} } }"#,
+ &format!("fn main() {{ {kind} {{ if true {{}} }} }}"),
);
check_edit(
- "unsafe",
+ kind,
r#"fn main() { while true {}.$0 }"#,
- r#"fn main() { unsafe { while true {} } }"#,
+ &format!("fn main() {{ {kind} {{ while true {{}} }} }}"),
);
check_edit(
- "unsafe",
+ kind,
r#"fn main() { for i in 0..10 {}.$0 }"#,
- r#"fn main() { unsafe { for i in 0..10 {} } }"#,
+ &format!("fn main() {{ {kind} {{ for i in 0..10 {{}} }} }}"),
);
check_edit(
- "unsafe",
+ kind,
r#"fn main() { let x = if true {1} else {2}.$0 }"#,
- r#"fn main() { let x = unsafe { if true {1} else {2} } }"#,
+ &format!("fn main() {{ let x = {kind} {{ if true {{1}} else {{2}} }} }}"),
);
// completion will not be triggered
check_edit(
- "unsafe",
+ kind,
r#"fn main() { let x = true else {panic!()}.$0}"#,
- r#"fn main() { let x = true else {panic!()}.unsafe $0}"#,
+ &format!("fn main() {{ let x = true else {{panic!()}}.{kind} $0}}"),
);
}
#[test]
fn custom_postfix_completion() {
let config = CompletionConfig {
- snippets: vec![Snippet::new(
- &[],
- &["break".into()],
- &["ControlFlow::Break(${receiver})".into()],
- "",
- &["core::ops::ControlFlow".into()],
- crate::SnippetScope::Expr,
- )
- .unwrap()],
+ snippets: vec![
+ Snippet::new(
+ &[],
+ &["break".into()],
+ &["ControlFlow::Break(${receiver})".into()],
+ "",
+ &["core::ops::ControlFlow".into()],
+ crate::SnippetScope::Expr,
+ )
+ .unwrap(),
+ ],
..TEST_CONFIG
};