-//! See `complete_fn_param`.
+//! See [`complete_fn_param`].
use rustc_hash::FxHashMap;
use syntax::{
- ast::{self, ModuleItemOwner},
+ ast::{self, HasModuleItem},
match_ast, AstNode,
};
-use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
+use crate::{
+ context::{ParamKind, PatternContext},
+ CompletionContext, CompletionItem, CompletionItemKind, 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) {
- if !ctx.is_param {
- return;
+pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
+ if !matches!(ctx.pattern_ctx, Some(PatternContext { is_param: Some(ParamKind::Function), .. }))
+ {
+ return None;
}
let mut params = FxHashMap::default();
}
func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
if let Some(pat) = param.pat() {
+ // FIXME: We should be able to turn these into SmolStr without having to allocate a String
let text = param.syntax().text().to_string();
let lookup = pat.syntax().text().to_string();
params.entry(text).or_insert(lookup);
};
}
- params.into_iter().for_each(|(label, lookup)| {
- let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
- item.kind(CompletionItemKind::Binding).lookup_by(lookup);
- item.add_to(acc)
- });
-}
-
-#[cfg(test)]
-mod tests {
- use expect_test::{expect, Expect};
-
- use crate::{test_utils::completion_list, CompletionKind};
-
- fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(ra_fixture, CompletionKind::Magic);
- expect.assert_eq(&actual);
- }
-
- #[test]
- fn test_param_completion_last_param() {
- check(
- r#"
-fn foo(file_id: FileId) {}
-fn bar(file_id: FileId) {}
-fn baz(file$0) {}
-"#,
- expect![[r#"
- bn file_id: FileId
- "#]],
- );
+ let self_completion_items = ["self", "&self", "mut self", "&mut self"];
+ if ctx.impl_def.is_some() && me?.param_list()?.params().next().is_none() {
+ self_completion_items.into_iter().for_each(|self_item| {
+ add_new_item_to_acc(ctx, acc, self_item.to_string(), self_item.to_string())
+ });
}
- #[test]
- fn test_param_completion_nth_param() {
- check(
- r#"
-fn foo(file_id: FileId) {}
-fn baz(file$0, x: i32) {}
-"#,
- expect![[r#"
- bn file_id: FileId
- "#]],
- );
- }
+ params.into_iter().for_each(|(label, lookup)| add_new_item_to_acc(ctx, acc, label, lookup));
- #[test]
- fn test_param_completion_trait_param() {
- check(
- r#"
-pub(crate) trait SourceRoot {
- pub fn contains(&self, file_id: FileId) -> bool;
- pub fn module_map(&self) -> &ModuleMap;
- pub fn lines(&self, file_id: FileId) -> &LineIndex;
- pub fn syntax(&self, file$0)
+ Some(())
}
-"#,
- expect![[r#"
- bn file_id: FileId
- "#]],
- );
- }
- #[test]
- fn completes_param_in_inner_function() {
- check(
- r#"
-fn outer(text: String) {
- fn inner($0)
-}
-"#,
- expect![[r#"
- bn text: String
- "#]],
- )
- }
+fn add_new_item_to_acc(
+ ctx: &CompletionContext,
+ acc: &mut Completions,
+ label: String,
+ lookup: String,
+) {
+ let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
+ item.lookup_by(lookup);
+ item.add_to(acc)
}