From 33ff7b56ff353410e7bcb7aed27004d4f0a57d8e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 27 Jan 2019 20:50:57 +0100 Subject: Use the new Resolver API in completion --- crates/ra_ide_api/src/completion/complete_path.rs | 12 ++--- crates/ra_ide_api/src/completion/complete_scope.rs | 63 ++++++---------------- .../src/completion/completion_context.rs | 5 +- .../ra_ide_api/src/completion/completion_item.rs | 44 ++++++++++----- .../completion_item__self_in_methods.snap | 18 ++++++- 5 files changed, 74 insertions(+), 68 deletions(-) (limited to 'crates/ra_ide_api/src/completion') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index b33ddcde5..9e61c0212 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -7,13 +7,13 @@ use crate::{ use hir::Docs; pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { - let (path, module) = match (&ctx.path_prefix, &ctx.module) { - (Some(path), Some(module)) => (path.clone(), module), + let path = match &ctx.path_prefix { + Some(path) => path.clone(), _ => return, }; - let def_id = match module.resolve_path(ctx.db, &path).take_types() { - Some(it) => it, - None => return, + let def = match ctx.resolver.resolve_path(ctx.db, &path).take_types() { + Some(Resolution::Def { def }) => def, + _ => return, }; match def_id { hir::ModuleDef::Module(module) => { @@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { ctx.source_range(), name.to_string(), ) - .from_resolution(ctx, res) + .from_resolution(ctx, &res.def.map(|def| hir::Resolution::Def { def })) .add_to(acc); } } diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index f837bb1db..3488d6480 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs @@ -1,61 +1,32 @@ -use rustc_hash::FxHashSet; -use ra_syntax::ast::AstNode; -use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; +use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext}; pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { if !ctx.is_trivial_path { return; } - let module = match &ctx.module { - Some(it) => it, - None => return, - }; - if let Some(function) = &ctx.function { - let scopes = function.scopes(ctx.db); - complete_fn(acc, &scopes, ctx); - } + let names = ctx.resolver.all_names(); - let module_scope = module.scope(ctx.db); - module_scope - .entries() - .filter(|(_name, res)| { - // For cases like `use self::foo<|>` don't suggest foo itself. - match res.import { - None => true, - Some(import) => { - let source = module.import_source(ctx.db, import); - !source.syntax().range().is_subrange(&ctx.leaf.range()) - } - } - }) + // let module_scope = module.scope(ctx.db); + names + .into_iter() + // FIXME check tests + // .filter(|(_name, res)| { + // // For cases like `use self::foo<|>` don't suggest foo itself. + // match res.import { + // None => true, + // Some(import) => { + // let source = module.import_source(ctx.db, import); + // !source.syntax().range().is_subrange(&ctx.leaf.range()) + // } + // } + // }) .for_each(|(name, res)| { CompletionItem::new( CompletionKind::Reference, ctx.source_range(), name.to_string(), ) - .from_resolution(ctx, res) - .add_to(acc) - }); -} - -fn complete_fn( - acc: &mut Completions, - scopes: &hir::ScopesWithSyntaxMapping, - ctx: &CompletionContext, -) { - let mut shadowed = FxHashSet::default(); - scopes - .scope_chain_for_offset(ctx.offset) - .flat_map(|scope| scopes.scopes.entries(scope).iter()) - .filter(|entry| shadowed.insert(entry.name())) - .for_each(|entry| { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - entry.name().to_string(), - ) - .kind(CompletionItemKind::Binding) + .from_resolution(ctx, &res) .add_to(acc) }); } diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 578af6e5b..aea32fce3 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs @@ -5,7 +5,7 @@ use ra_syntax::{ algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset}, SyntaxKind::*, }; -use hir::source_binder; +use hir::{source_binder, Resolver}; use crate::{db, FilePosition}; @@ -16,6 +16,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) db: &'a db::RootDatabase, pub(super) offset: TextUnit, pub(super) leaf: &'a SyntaxNode, + pub(super) resolver: Resolver<'static>, pub(super) module: Option, pub(super) function: Option, pub(super) function_syntax: Option<&'a ast::FnDef>, @@ -42,12 +43,14 @@ impl<'a> CompletionContext<'a> { original_file: &'a SourceFile, position: FilePosition, ) -> Option> { + let resolver = source_binder::resolver_for_position(db, position); let module = source_binder::module_from_position(db, position); let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?; let mut ctx = CompletionContext { db, leaf, offset: position.offset, + resolver, module, function: None, function_syntax: None, diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index d3bc14894..4101ce88a 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -1,5 +1,7 @@ -use hir::{Docs, Documentation}; -use ra_syntax::TextRange; +use hir::{Docs, Documentation, PerNs, Resolution}; +use ra_syntax::{ + TextRange, +}; use ra_text_edit::TextEdit; use test_utils::tested_by; @@ -48,6 +50,7 @@ pub enum CompletionItemKind { Trait, TypeAlias, Method, + TypeParam, } #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -207,23 +210,38 @@ impl Builder { pub(super) fn from_resolution( mut self, ctx: &CompletionContext, - resolution: &hir::Resolution, + resolution: &PerNs, ) -> Builder { - let def = resolution.def.take_types().or(resolution.def.take_values()); + use hir::ModuleDef::*; + + let def = resolution + .as_ref() + .take_types() + .or(resolution.as_ref().take_values()); let def = match def { None => return self, Some(it) => it, }; let (kind, docs) = match def { - hir::ModuleDef::Module(it) => (CompletionItemKind::Module, it.docs(ctx.db)), - hir::ModuleDef::Function(func) => return self.from_function(ctx, func), - hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), - hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), - hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), - hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), - hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), - hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), - hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + Resolution::Def { def: Module(it) } => (CompletionItemKind::Module, it.docs(ctx.db)), + Resolution::Def { + def: Function(func), + } => return self.from_function(ctx, *func), + Resolution::Def { def: Struct(it) } => (CompletionItemKind::Struct, it.docs(ctx.db)), + Resolution::Def { def: Enum(it) } => (CompletionItemKind::Enum, it.docs(ctx.db)), + Resolution::Def { + def: EnumVariant(it), + } => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), + Resolution::Def { def: Const(it) } => (CompletionItemKind::Const, it.docs(ctx.db)), + Resolution::Def { def: Static(it) } => (CompletionItemKind::Static, it.docs(ctx.db)), + Resolution::Def { def: Trait(it) } => (CompletionItemKind::Trait, it.docs(ctx.db)), + Resolution::Def { def: Type(it) } => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + Resolution::GenericParam { .. } => (CompletionItemKind::TypeParam, None), + Resolution::LocalBinding { .. } => (CompletionItemKind::Binding, None), + Resolution::SelfType { .. } => ( + CompletionItemKind::TypeParam, // (does this need its own kind?) + None, + ), }; self.kind = Some(kind); self.documentation = docs; diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap index 6a49e325c..ba1d4abbd 100644 --- a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap @@ -1,10 +1,24 @@ --- -created: "2019-01-23T05:27:32.422259+00:00" -creator: insta@0.4.0 +created: "2019-01-27T20:17:10.051725945+00:00" +creator: insta@0.5.2 expression: kind_completions source: crates/ra_ide_api/src/completion/completion_item.rs --- [ + CompletionItem { + completion_kind: Reference, + label: "Self", + kind: Some( + TypeParam + ), + detail: None, + documentation: None, + lookup: None, + insert_text: None, + insert_text_format: PlainText, + source_range: [25; 25), + text_edit: None + }, CompletionItem { completion_kind: Reference, label: "self", -- cgit v1.2.3 From d3df80dfe41e4e3ab7644ae576119a264ba0e7f1 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 27 Jan 2019 17:23:49 +0100 Subject: Cleanup --- crates/ra_ide_api/src/completion/complete_path.rs | 6 +++--- crates/ra_ide_api/src/completion/completion_context.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide_api/src/completion') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 9e61c0212..5b89c64ad 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -1,11 +1,11 @@ use join_to_string::join; +use hir::{Docs, Resolution}; + use crate::{ completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, }; -use hir::Docs; - pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { let path = match &ctx.path_prefix { Some(path) => path.clone(), @@ -15,7 +15,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { Some(Resolution::Def { def }) => def, _ => return, }; - match def_id { + match def { hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); for (name, res) in module_scope.entries() { diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index aea32fce3..5d1851da6 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs @@ -16,7 +16,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) db: &'a db::RootDatabase, pub(super) offset: TextUnit, pub(super) leaf: &'a SyntaxNode, - pub(super) resolver: Resolver<'static>, + pub(super) resolver: Resolver, pub(super) module: Option, pub(super) function: Option, pub(super) function_syntax: Option<&'a ast::FnDef>, -- cgit v1.2.3 From d571d26955148befd6986008a5112fff3a901c43 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 30 Jan 2019 22:41:44 +0100 Subject: Make the Resolution variants tuple variants --- crates/ra_ide_api/src/completion/complete_path.rs | 4 ++-- .../ra_ide_api/src/completion/completion_item.rs | 28 ++++++++++------------ 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'crates/ra_ide_api/src/completion') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 5b89c64ad..8e0f6a79e 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -12,7 +12,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { _ => return, }; let def = match ctx.resolver.resolve_path(ctx.db, &path).take_types() { - Some(Resolution::Def { def }) => def, + Some(Resolution::Def(def)) => def, _ => return, }; match def { @@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { ctx.source_range(), name.to_string(), ) - .from_resolution(ctx, &res.def.map(|def| hir::Resolution::Def { def })) + .from_resolution(ctx, &res.def.map(hir::Resolution::Def)) .add_to(acc); } } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 4101ce88a..bada6a33b 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -223,22 +223,18 @@ impl Builder { Some(it) => it, }; let (kind, docs) = match def { - Resolution::Def { def: Module(it) } => (CompletionItemKind::Module, it.docs(ctx.db)), - Resolution::Def { - def: Function(func), - } => return self.from_function(ctx, *func), - Resolution::Def { def: Struct(it) } => (CompletionItemKind::Struct, it.docs(ctx.db)), - Resolution::Def { def: Enum(it) } => (CompletionItemKind::Enum, it.docs(ctx.db)), - Resolution::Def { - def: EnumVariant(it), - } => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), - Resolution::Def { def: Const(it) } => (CompletionItemKind::Const, it.docs(ctx.db)), - Resolution::Def { def: Static(it) } => (CompletionItemKind::Static, it.docs(ctx.db)), - Resolution::Def { def: Trait(it) } => (CompletionItemKind::Trait, it.docs(ctx.db)), - Resolution::Def { def: Type(it) } => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), - Resolution::GenericParam { .. } => (CompletionItemKind::TypeParam, None), - Resolution::LocalBinding { .. } => (CompletionItemKind::Binding, None), - Resolution::SelfType { .. } => ( + Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)), + Resolution::Def(Function(func)) => return self.from_function(ctx, *func), + Resolution::Def(Struct(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)), + Resolution::Def(Enum(it)) => (CompletionItemKind::Enum, it.docs(ctx.db)), + Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), + Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)), + Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)), + Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)), + Resolution::Def(Type(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None), + Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None), + Resolution::SelfType(..) => ( CompletionItemKind::TypeParam, // (does this need its own kind?) None, ), -- cgit v1.2.3 From c5852f422ff45adaa21815c1a15e03b067a56a82 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 1 Feb 2019 23:06:57 +0100 Subject: Some cleanup and additional tests --- crates/ra_ide_api/src/completion/complete_path.rs | 11 +++++ crates/ra_ide_api/src/completion/complete_scope.rs | 57 +++++++++++++--------- .../snapshots/completion_item__generic_params.snap | 40 +++++++++++++++ .../completion_item__generic_params_in_struct.snap | 36 ++++++++++++++ 4 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap create mode 100644 crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap (limited to 'crates/ra_ide_api/src/completion') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 8e0f6a79e..0b9948d4b 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -65,6 +65,17 @@ mod tests { check_completion(code, expected_completions, CompletionKind::Reference); } + #[test] + #[ignore] // should not complete foo, which currently doesn't work + fn dont_complete_current_use() { + check_reference_completion( + "dont_complete_current_use", + r" + use self::foo<|>; + ", + ); + } + #[test] fn completes_mod_with_docs() { check_reference_completion( diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 3488d6480..44514ab2b 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs @@ -6,29 +6,15 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { } let names = ctx.resolver.all_names(); - // let module_scope = module.scope(ctx.db); - names - .into_iter() - // FIXME check tests - // .filter(|(_name, res)| { - // // For cases like `use self::foo<|>` don't suggest foo itself. - // match res.import { - // None => true, - // Some(import) => { - // let source = module.import_source(ctx.db, import); - // !source.syntax().range().is_subrange(&ctx.leaf.range()) - // } - // } - // }) - .for_each(|(name, res)| { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - name.to_string(), - ) - .from_resolution(ctx, &res) - .add_to(acc) - }); + names.into_iter().for_each(|(name, res)| { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + name.to_string(), + ) + .from_resolution(ctx, &res) + .add_to(acc) + }); } #[cfg(test)] @@ -86,6 +72,30 @@ mod tests { ); } + #[test] + fn completes_generic_params() { + check_reference_completion( + "generic_params", + r" + fn quux() { + <|> + } + ", + ); + } + + #[test] + fn completes_generic_params_in_struct() { + check_reference_completion( + "generic_params_in_struct", + r" + struct X { + x: <|> + } + ", + ); + } + #[test] fn completes_module_items() { check_reference_completion( @@ -145,5 +155,4 @@ mod tests { fn completes_self_in_methods() { check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") } - } diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap new file mode 100644 index 000000000..71cb55a5b --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap @@ -0,0 +1,40 @@ +--- +created: "2019-02-01T22:20:40.580128393+00:00" +creator: insta@0.5.3 +expression: kind_completions +source: crates/ra_ide_api/src/completion/completion_item.rs +--- +[ + CompletionItem { + completion_kind: Reference, + label: "T", + kind: Some( + TypeParam + ), + detail: None, + documentation: None, + lookup: None, + insert_text: None, + insert_text_format: PlainText, + source_range: [44; 44), + text_edit: None + }, + CompletionItem { + completion_kind: Reference, + label: "quux", + kind: Some( + Function + ), + detail: Some( + "fn quux()" + ), + documentation: None, + lookup: None, + insert_text: Some( + "quux()$0" + ), + insert_text_format: Snippet, + source_range: [44; 44), + text_edit: None + } +] diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap new file mode 100644 index 000000000..a35c0cd13 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap @@ -0,0 +1,36 @@ +--- +created: "2019-02-01T22:23:21.508620224+00:00" +creator: insta@0.5.3 +expression: kind_completions +source: crates/ra_ide_api/src/completion/completion_item.rs +--- +[ + CompletionItem { + completion_kind: Reference, + label: "T", + kind: Some( + TypeParam + ), + detail: None, + documentation: None, + lookup: None, + insert_text: None, + insert_text_format: PlainText, + source_range: [46; 46), + text_edit: None + }, + CompletionItem { + completion_kind: Reference, + label: "X", + kind: Some( + Struct + ), + detail: None, + documentation: None, + lookup: None, + insert_text: None, + insert_text_format: PlainText, + source_range: [46; 46), + text_edit: None + } +] -- cgit v1.2.3