From 5b573deb20b15451788dd2861e9fc6e69ed0472e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 8 Jan 2019 22:33:36 +0300 Subject: fix usages after rename --- .../ra_ide_api/src/completion/complete_fn_param.rs | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 crates/ra_ide_api/src/completion/complete_fn_param.rs (limited to 'crates/ra_ide_api/src/completion/complete_fn_param.rs') diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs new file mode 100644 index 000000000..c1739e47e --- /dev/null +++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs @@ -0,0 +1,102 @@ +use ra_syntax::{ + algo::visit::{visitor_ctx, VisitorCtx}, + ast, + AstNode, +}; +use rustc_hash::FxHashMap; + +use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem}; + +/// Complete repeated parametes, 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(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) { + if !ctx.is_param { + return; + } + + let mut params = FxHashMap::default(); + for node in ctx.leaf.ancestors() { + let _ = visitor_ctx(&mut params) + .visit::(process) + .visit::(process) + .accept(node); + } + params + .into_iter() + .filter_map(|(label, (count, param))| { + let lookup = param.pat()?.syntax().text().to_string(); + if count < 2 { + None + } else { + Some((label, lookup)) + } + }) + .for_each(|(label, lookup)| { + CompletionItem::new(CompletionKind::Magic, label) + .lookup_by(lookup) + .add_to(acc) + }); + + fn process<'a, N: ast::FnDefOwner>( + node: &'a N, + params: &mut FxHashMap, + ) { + node.functions() + .filter_map(|it| it.param_list()) + .flat_map(|it| it.params()) + .for_each(|param| { + let text = param.syntax().text().to_string(); + params.entry(text).or_insert((0, param)).0 += 1; + }) + } +} + +#[cfg(test)] +mod tests { + use crate::completion::*; + + fn check_magic_completion(code: &str, expected_completions: &str) { + check_completion(code, expected_completions, CompletionKind::Magic); + } + + #[test] + fn test_param_completion_last_param() { + check_magic_completion( + r" + fn foo(file_id: FileId) {} + fn bar(file_id: FileId) {} + fn baz(file<|>) {} + ", + r#"file_id "file_id: FileId""#, + ); + } + + #[test] + fn test_param_completion_nth_param() { + check_magic_completion( + r" + fn foo(file_id: FileId) {} + fn bar(file_id: FileId) {} + fn baz(file<|>, x: i32) {} + ", + r#"file_id "file_id: FileId""#, + ); + } + + #[test] + fn test_param_completion_trait_param() { + check_magic_completion( + 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<|>) + } + ", + r#"file_id "file_id: FileId""#, + ); + } +} -- cgit v1.2.3