Fix invalid completion arg nr
Example
---
```rust
fn foo() { bar(, $0); }
fn bar(x: u32, y: i32) {}
```
**Before this PR**
```text
ty: u32, name: x
```
**After this PR**
```text
ty: i32, name: y
```
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index d6d3978..d5a1d21 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -657,7 +657,7 @@
cov_mark::hit!(expected_type_fn_param);
ActiveParameter::at_token(
sema,
- token.clone(),
+ token.clone(),
).map(|ap| {
let name = ap.ident().map(NameOrNameRef::Name);
(Some(ap.ty), name)
diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs
index 51d28bd..41f0db3 100644
--- a/crates/ide-completion/src/context/tests.rs
+++ b/crates/ide-completion/src/context/tests.rs
@@ -90,6 +90,20 @@
"#,
expect![[r#"ty: u32, name: x"#]],
);
+ check_expected_type_and_name(
+ r#"
+fn foo() { bar(, $0); }
+fn bar(x: u32, y: i32) {}
+"#,
+ expect![[r#"ty: i32, name: y"#]],
+ );
+ check_expected_type_and_name(
+ r#"
+fn foo() { bar(, c$0); }
+fn bar(x: u32, y: i32) {}
+"#,
+ expect![[r#"ty: i32, name: y"#]],
+ );
}
#[test]
diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs
index 4fb7d14..f5a5b76 100644
--- a/crates/ide-db/src/active_parameter.rs
+++ b/crates/ide-db/src/active_parameter.rs
@@ -5,7 +5,7 @@
use parser::T;
use span::TextSize;
use syntax::{
- AstNode, NodeOrToken, SyntaxToken,
+ AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
ast::{self, AstChildren, HasArgList, HasAttrs, HasName},
match_ast,
};
@@ -102,8 +102,7 @@
arg_list
.syntax()
.children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .filter(|t| t.kind() == T![,])
+ .filter_map(into_comma)
.take_while(|t| t.text_range().start() <= offset)
.count()
});
@@ -162,8 +161,7 @@
let active_param = generic_arg_list
.syntax()
.children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .filter(|t| t.kind() == T![,])
+ .filter_map(into_comma)
.take_while(|t| t.text_range().start() <= token.text_range().start())
.count();
@@ -174,3 +172,12 @@
Some((def, active_param, first_arg_is_non_lifetime, variant))
}
+
+fn into_comma(it: NodeOrToken<SyntaxNode, SyntaxToken>) -> Option<SyntaxToken> {
+ let token = match it {
+ NodeOrToken::Token(it) => it,
+ NodeOrToken::Node(node) if node.kind() == SyntaxKind::ERROR => node.first_token()?,
+ NodeOrToken::Node(_) => return None,
+ };
+ (token.kind() == T![,]).then_some(token)
+}