Skip to content

fix: Typing underscore should not trigger completions in types or patterns #15692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions crates/ide-completion/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
109 changes: 109 additions & 0 deletions crates/ide-completion/src/tests/special.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::
"#]],
);
}