Merge #9896
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:
commit
d7374ab882
@ -6,14 +6,17 @@
|
||||
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
|
||||
/// 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
|
||||
/// suggested.
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,12 @@ pub(crate) enum CallKind {
|
||||
Mac,
|
||||
Expr,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum ParamKind {
|
||||
Function,
|
||||
Closure,
|
||||
}
|
||||
/// `CompletionContext` is created early during completion to figure out, where
|
||||
/// exactly is the cursor, syntax-wise.
|
||||
#[derive(Debug)]
|
||||
@ -91,7 +97,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||
|
||||
// potentially set if we are completing a name
|
||||
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) prev_sibling: Option<ImmediatePrevSibling>,
|
||||
@ -158,7 +164,7 @@ pub(super) fn new(
|
||||
lifetime_allowed: false,
|
||||
is_label_ref: false,
|
||||
is_pat_or_const: None,
|
||||
is_param: false,
|
||||
is_param: None,
|
||||
completion_location: None,
|
||||
prev_sibling: None,
|
||||
attribute_under_caret: None,
|
||||
@ -670,7 +676,17 @@ fn classify_name(&mut self, name: ast::Name) {
|
||||
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) {
|
||||
@ -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)
|
||||
}
|
||||
|
||||
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)> {
|
||||
if let Some(qual) = path.qualifier() {
|
||||
return Some((qual, false));
|
||||
|
@ -4,7 +4,10 @@
|
||||
use ide_db::helpers::SnippetCap;
|
||||
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(
|
||||
ctx: RenderContext<'_>,
|
||||
@ -83,7 +86,7 @@ fn render_pat(
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if ctx.completion.is_param {
|
||||
if ctx.completion.is_param == Some(ParamKind::Function) {
|
||||
pat.push(':');
|
||||
pat.push(' ');
|
||||
pat.push_str(name);
|
||||
|
@ -58,11 +58,6 @@ fn render_literal(
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if ctx.completion.is_param {
|
||||
literal.push(':');
|
||||
literal.push(' ');
|
||||
literal.push_str(name);
|
||||
}
|
||||
if ctx.snippet_cap().is_some() {
|
||||
literal.push_str("$0");
|
||||
}
|
||||
|
@ -309,3 +309,41 @@ fn outer(Foo { bar$0 }: Foo) {}
|
||||
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
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user