From 2136e75c0bce090d104bb5b5006e48e42fb22a0a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 21 Dec 2018 23:04:56 +0300 Subject: move path completion to a separate component --- crates/ra_analysis/src/completion/complete_path.rs | 95 ++++++++++++++++++++++ .../src/completion/reference_completion.rs | 33 +------- 2 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 crates/ra_analysis/src/completion/complete_path.rs (limited to 'crates/ra_analysis/src/completion') diff --git a/crates/ra_analysis/src/completion/complete_path.rs b/crates/ra_analysis/src/completion/complete_path.rs new file mode 100644 index 000000000..d04503e46 --- /dev/null +++ b/crates/ra_analysis/src/completion/complete_path.rs @@ -0,0 +1,95 @@ +use crate::{ + completion::{CompletionItem, Completions, CompletionKind::*, SyntaxContext}, + Cancelable, +}; + +pub(super) fn complete_path(acc: &mut Completions, ctx: &SyntaxContext) -> Cancelable<()> { + let (path, module) = match (&ctx.path_prefix, &ctx.module) { + (Some(path), Some(module)) => (path.clone(), module), + _ => return Ok(()), + }; + let def_id = match module.resolve_path(ctx.db, path)? { + None => return Ok(()), + Some(it) => it, + }; + let target_module = match def_id.resolve(ctx.db)? { + hir::Def::Module(it) => it, + _ => return Ok(()), + }; + let module_scope = target_module.scope(ctx.db)?; + module_scope.entries().for_each(|(name, _res)| { + CompletionItem::new(name.to_string()) + .kind(Reference) + .add_to(acc) + }); + Ok(()) +} + +#[cfg(test)] +mod tests { + use crate::completion::{CompletionKind, check_completion}; + + fn check_reference_completion(code: &str, expected_completions: &str) { + check_completion(code, expected_completions, CompletionKind::Reference); + } + + #[test] + fn completes_use_item_starting_with_self() { + check_reference_completion( + r" + use self::m::<|>; + + mod m { + struct Bar; + } + ", + "Bar", + ); + } + + #[test] + fn completes_use_item_starting_with_crate() { + check_reference_completion( + " + //- /lib.rs + mod foo; + struct Spam; + //- /foo.rs + use crate::Sp<|> + ", + "Spam;foo", + ); + } + + #[test] + fn completes_nested_use_tree() { + check_reference_completion( + " + //- /lib.rs + mod foo; + struct Spam; + //- /foo.rs + use crate::{Sp<|>}; + ", + "Spam;foo", + ); + } + + #[test] + fn completes_deeply_nested_use_tree() { + check_reference_completion( + " + //- /lib.rs + mod foo; + pub mod bar { + pub mod baz { + pub struct Spam; + } + } + //- /foo.rs + use crate::{bar::{baz::Sp<|>}}; + ", + "Spam", + ); + } +} diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index 46d381927..459ed8f6f 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs @@ -1,4 +1,4 @@ -use rustc_hash::{FxHashSet}; +use rustc_hash::FxHashSet; use ra_syntax::{ SourceFileNode, AstNode, ast, @@ -6,7 +6,7 @@ use ra_syntax::{ }; use hir::{ self, - FnScopes, Def, Path + FnScopes, Path }; use crate::{ @@ -53,7 +53,7 @@ pub(super) fn completions( .add_to(acc) }); } - NameRefKind::Path(path) => complete_path(acc, db, module, path)?, + NameRefKind::Path(_) => (), NameRefKind::BareIdentInMod => (), } Ok(()) @@ -121,33 +121,6 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Completions) } } -fn complete_path( - acc: &mut Completions, - db: &RootDatabase, - module: &hir::Module, - mut path: Path, -) -> Cancelable<()> { - if path.segments.is_empty() { - return Ok(()); - } - path.segments.pop(); - let def_id = match module.resolve_path(db, path)? { - None => return Ok(()), - Some(it) => it, - }; - let target_module = match def_id.resolve(db)? { - Def::Module(it) => it, - _ => return Ok(()), - }; - let module_scope = target_module.scope(db)?; - module_scope.entries().for_each(|(name, _res)| { - CompletionItem::new(name.to_string()) - .kind(Reference) - .add_to(acc) - }); - Ok(()) -} - #[cfg(test)] mod tests { use crate::completion::{CompletionKind, check_completion}; -- cgit v1.2.3