9896: internal: Only complete type annotations for patterns in function params r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-08-14 16:19:14 +00:00 committed by GitHub
commit d7374ab882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 19 deletions

View File

@ -6,14 +6,17 @@
match_ast, AstNode, match_ast, AstNode,
}; };
use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions}; use crate::{
context::ParamKind, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
Completions,
};
/// Complete repeated parameters, both name and type. For example, if all /// Complete repeated parameters, both name and type. For example, if all
/// functions in a file have a `spam: &mut Spam` parameter, a completion with /// functions in a file have a `spam: &mut Spam` parameter, a completion with
/// `spam: &mut Spam` insert text/label and `spam` lookup string will be /// `spam: &mut Spam` insert text/label and `spam` lookup string will be
/// suggested. /// suggested.
pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
if !ctx.is_param { if ctx.is_param != Some(ParamKind::Function) {
return None; return None;
} }

View File

@ -60,6 +60,12 @@ pub(crate) enum CallKind {
Mac, Mac,
Expr, Expr,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum ParamKind {
Function,
Closure,
}
/// `CompletionContext` is created early during completion to figure out, where /// `CompletionContext` is created early during completion to figure out, where
/// exactly is the cursor, syntax-wise. /// exactly is the cursor, syntax-wise.
#[derive(Debug)] #[derive(Debug)]
@ -91,7 +97,7 @@ pub(crate) struct CompletionContext<'a> {
// potentially set if we are completing a name // potentially set if we are completing a name
pub(super) is_pat_or_const: Option<PatternRefutability>, pub(super) is_pat_or_const: Option<PatternRefutability>,
pub(super) is_param: bool, pub(super) is_param: Option<ParamKind>,
pub(super) completion_location: Option<ImmediateLocation>, pub(super) completion_location: Option<ImmediateLocation>,
pub(super) prev_sibling: Option<ImmediatePrevSibling>, pub(super) prev_sibling: Option<ImmediatePrevSibling>,
@ -158,7 +164,7 @@ pub(super) fn new(
lifetime_allowed: false, lifetime_allowed: false,
is_label_ref: false, is_label_ref: false,
is_pat_or_const: None, is_pat_or_const: None,
is_param: false, is_param: None,
completion_location: None, completion_location: None,
prev_sibling: None, prev_sibling: None,
attribute_under_caret: None, attribute_under_caret: None,
@ -670,7 +676,17 @@ fn classify_name(&mut self, name: ast::Name) {
self.fill_impl_def(); self.fill_impl_def();
} }
self.is_param |= is_node::<ast::Param>(name.syntax()); if let Some(param) = name
.syntax()
.ancestors()
.find_map(ast::Param::cast)
.filter(|it| it.syntax().text_range() == name.syntax().text_range())
{
let is_closure_param =
param.syntax().ancestors().nth(2).and_then(ast::ClosureExpr::cast).is_some();
self.is_param =
Some(if is_closure_param { ParamKind::Closure } else { ParamKind::Function });
}
} }
fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameRef) { fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameRef) {
@ -774,13 +790,6 @@ fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Op
syntax.covering_element(range).ancestors().find_map(N::cast) syntax.covering_element(range).ancestors().find_map(N::cast)
} }
fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
match node.ancestors().find_map(N::cast) {
None => false,
Some(n) => n.syntax().text_range() == node.text_range(),
}
}
fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> { fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
if let Some(qual) = path.qualifier() { if let Some(qual) = path.qualifier() {
return Some((qual, false)); return Some((qual, false));

View File

@ -4,7 +4,10 @@
use ide_db::helpers::SnippetCap; use ide_db::helpers::SnippetCap;
use itertools::Itertools; use itertools::Itertools;
use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind}; use crate::{
context::ParamKind, item::CompletionKind, render::RenderContext, CompletionItem,
CompletionItemKind,
};
pub(crate) fn render_struct_pat( pub(crate) fn render_struct_pat(
ctx: RenderContext<'_>, ctx: RenderContext<'_>,
@ -83,7 +86,7 @@ fn render_pat(
_ => return None, _ => return None,
}; };
if ctx.completion.is_param { if ctx.completion.is_param == Some(ParamKind::Function) {
pat.push(':'); pat.push(':');
pat.push(' '); pat.push(' ');
pat.push_str(name); pat.push_str(name);

View File

@ -58,11 +58,6 @@ fn render_literal(
_ => return None, _ => return None,
}; };
if ctx.completion.is_param {
literal.push(':');
literal.push(' ');
literal.push_str(name);
}
if ctx.snippet_cap().is_some() { if ctx.snippet_cap().is_some() {
literal.push_str("$0"); literal.push_str("$0");
} }

View File

@ -309,3 +309,41 @@ fn outer(Foo { bar$0 }: Foo) {}
expect![[r#""#]], expect![[r#""#]],
) )
} }
#[test]
fn completes_in_fn_param() {
check_empty(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn foo($0) {}
"#,
expect![[r#"
kw mut
bn Foo Foo { bar$1 }: Foo$0
st Foo
bn Bar Bar($1): Bar$0
st Bar
"#]],
)
}
#[test]
fn completes_in_closure_param() {
check_empty(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn foo() {
|$0| {};
}
"#,
expect![[r#"
kw mut
bn Foo Foo { bar$1 }$0
st Foo
bn Bar Bar($1)$0
st Bar
"#]],
)
}