Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-completion/src/lib.rs22
-rw-r--r--crates/ide-completion/src/tests/special.rs109
2 files changed, 131 insertions, 0 deletions
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 2eaa42040a..2fad293d16 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -169,6 +169,28 @@ pub fn completions(
return Some(completions.into());
}
+ // when the user types a bare `_` (that is it does not belong to an identifier)
+ // the user might just wanted to type a `_` for type inference or pattern discarding
+ // so try to suppress completions in those cases
+ if trigger_character == Some('_') && ctx.original_token.kind() == syntax::SyntaxKind::UNDERSCORE
+ {
+ if let CompletionAnalysis::NameRef(NameRefContext {
+ kind:
+ NameRefKind::Path(
+ path_ctx @ PathCompletionCtx {
+ kind: PathKind::Type { .. } | PathKind::Pat { .. },
+ ..
+ },
+ ),
+ ..
+ }) = analysis
+ {
+ if path_ctx.is_trivial_path() {
+ return None;
+ }
+ }
+ }
+
{
let acc = &mut completions;
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index 83888e08f1..d3dbd7cc22 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -1372,3 +1372,112 @@ fn main() {
expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"),
);
}
+
+#[test]
+fn skips_underscore() {
+ check_with_trigger_character(
+ r#"
+fn foo(_$0) { }
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo(_: _$0) { }
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo<T>() {
+ foo::<_$0>();
+}
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ // underscore expressions are fine, they are invalid so the user definitely meant to type an
+ // underscored name here
+ check_with_trigger_character(
+ r#"
+fn foo() {
+ _$0
+}
+"#,
+ Some('_'),
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+}
+
+#[test]
+fn no_skip_underscore_ident() {
+ check_with_trigger_character(
+ r#"
+fn foo(a_$0) { }
+"#,
+ Some('_'),
+ expect![[r#"
+ kw mut
+ kw ref
+ "#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo(_: a_$0) { }
+"#,
+ Some('_'),
+ expect![[r#"
+ bt u32
+ kw crate::
+ kw self::
+ "#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo<T>() {
+ foo::<a_$0>();
+}
+"#,
+ Some('_'),
+ expect![[r#"
+ tp T
+ bt u32
+ kw crate::
+ kw self::
+ "#]],
+ );
+}