From 52fd2c8e4858c548195edceb83c02437d2d28ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 6 Apr 2020 17:21:33 +0300 Subject: Fix unnecessary braces warnings --- crates/ra_ide/src/call_info.rs | 14 ++++---- crates/ra_ide/src/completion/complete_fn_param.rs | 4 +-- crates/ra_ide/src/completion/complete_keyword.rs | 6 ++-- crates/ra_ide/src/display/navigation_target.rs | 42 +++++++++++------------ crates/ra_ide/src/display/structure.rs | 16 ++++----- crates/ra_ide/src/goto_type_definition.rs | 6 ++-- crates/ra_ide/src/runnables.rs | 4 +-- 7 files changed, 46 insertions(+), 46 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 39d09a07f..ca57eceff 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -109,7 +109,7 @@ impl FnCallNode { syntax.ancestors().find_map(|node| { match_ast! { match node { - ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, + ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), ast::MethodCallExpr(it) => { let arg_list = it.arg_list()?; if !syntax.text_range().is_subrange(&arg_list.syntax().text_range()) { @@ -117,8 +117,8 @@ impl FnCallNode { } Some(FnCallNode::MethodCallExpr(it)) }, - ast::MacroCall(it) => { Some(FnCallNode::MacroCallExpr(it)) }, - _ => { None }, + ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), + _ => None, } } }) @@ -127,10 +127,10 @@ impl FnCallNode { pub(crate) fn with_node_exact(node: &SyntaxNode) -> Option { match_ast! { match node { - ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, - ast::MethodCallExpr(it) => { Some(FnCallNode::MethodCallExpr(it)) }, - ast::MacroCall(it) => { Some(FnCallNode::MacroCallExpr(it)) }, - _ => { None }, + ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), + ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), + ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), + _ => None, } } } diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs index 9226ac055..62ae5ccb4 100644 --- a/crates/ra_ide/src/completion/complete_fn_param.rs +++ b/crates/ra_ide/src/completion/complete_fn_param.rs @@ -18,8 +18,8 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) for node in ctx.token.parent().ancestors() { match_ast! { match node { - ast::SourceFile(it) => { process(it, &mut params) }, - ast::ItemList(it) => { process(it, &mut params) }, + ast::SourceFile(it) => process(it, &mut params), + ast::ItemList(it) => process(it, &mut params), _ => (), } } diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 1e053ea4a..38f9c34e7 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -86,9 +86,9 @@ fn is_in_loop_body(leaf: &SyntaxToken) -> bool { } let loop_body = match_ast! { match node { - ast::ForExpr(it) => { it.loop_body() }, - ast::WhileExpr(it) => { it.loop_body() }, - ast::LoopExpr(it) => { it.loop_body() }, + ast::ForExpr(it) => it.loop_body(), + ast::WhileExpr(it) => it.loop_body(), + ast::LoopExpr(it) => it.loop_body(), _ => None, } }; diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index d57451cc8..e61846995 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -399,17 +399,17 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option match_ast! { match node { - ast::FnDef(it) => { it.doc_comment_text() }, - ast::StructDef(it) => { it.doc_comment_text() }, - ast::EnumDef(it) => { it.doc_comment_text() }, - ast::TraitDef(it) => { it.doc_comment_text() }, - ast::Module(it) => { it.doc_comment_text() }, - ast::TypeAliasDef(it) => { it.doc_comment_text() }, - ast::ConstDef(it) => { it.doc_comment_text() }, - ast::StaticDef(it) => { it.doc_comment_text() }, - ast::RecordFieldDef(it) => { it.doc_comment_text() }, - ast::EnumVariant(it) => { it.doc_comment_text() }, - ast::MacroCall(it) => { it.doc_comment_text() }, + ast::FnDef(it) => it.doc_comment_text(), + ast::StructDef(it) => it.doc_comment_text(), + ast::EnumDef(it) => it.doc_comment_text(), + ast::TraitDef(it) => it.doc_comment_text(), + ast::Module(it) => it.doc_comment_text(), + ast::TypeAliasDef(it) => it.doc_comment_text(), + ast::ConstDef(it) => it.doc_comment_text(), + ast::StaticDef(it) => it.doc_comment_text(), + ast::RecordFieldDef(it) => it.doc_comment_text(), + ast::EnumVariant(it) => it.doc_comment_text(), + ast::MacroCall(it) => it.doc_comment_text(), _ => None, } } @@ -424,16 +424,16 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> match_ast! { match node { - ast::FnDef(it) => { it.short_label() }, - ast::StructDef(it) => { it.short_label() }, - ast::EnumDef(it) => { it.short_label() }, - ast::TraitDef(it) => { it.short_label() }, - ast::Module(it) => { it.short_label() }, - ast::TypeAliasDef(it) => { it.short_label() }, - ast::ConstDef(it) => { it.short_label() }, - ast::StaticDef(it) => { it.short_label() }, - ast::RecordFieldDef(it) => { it.short_label() }, - ast::EnumVariant(it) => { it.short_label() }, + ast::FnDef(it) => it.short_label(), + ast::StructDef(it) => it.short_label(), + ast::EnumDef(it) => it.short_label(), + ast::TraitDef(it) => it.short_label(), + ast::Module(it) => it.short_label(), + ast::TypeAliasDef(it) => it.short_label(), + ast::ConstDef(it) => it.short_label(), + ast::StaticDef(it) => it.short_label(), + ast::RecordFieldDef(it) => it.short_label(), + ast::EnumVariant(it) => it.short_label(), _ => None, } } diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs index 5774e9a8b..7a774785c 100644 --- a/crates/ra_ide/src/display/structure.rs +++ b/crates/ra_ide/src/display/structure.rs @@ -117,18 +117,18 @@ fn structure_node(node: &SyntaxNode) -> Option { decl_with_detail(it, Some(detail)) }, - ast::StructDef(it) => { decl(it) }, - ast::EnumDef(it) => { decl(it) }, - ast::EnumVariant(it) => { decl(it) }, - ast::TraitDef(it) => { decl(it) }, - ast::Module(it) => { decl(it) }, + ast::StructDef(it) => decl(it), + ast::EnumDef(it) => decl(it), + ast::EnumVariant(it) => decl(it), + ast::TraitDef(it) => decl(it), + ast::Module(it) => decl(it), ast::TypeAliasDef(it) => { let ty = it.type_ref(); decl_with_type_ref(it, ty) }, - ast::RecordFieldDef(it) => { decl_with_ascription(it) }, - ast::ConstDef(it) => { decl_with_ascription(it) }, - ast::StaticDef(it) => { decl_with_ascription(it) }, + ast::RecordFieldDef(it) => decl_with_ascription(it), + ast::ConstDef(it) => decl_with_ascription(it), + ast::StaticDef(it) => decl_with_ascription(it), ast::ImplDef(it) => { let target_type = it.target_type()?; let target_trait = it.target_trait(); diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 869a4708b..bd2688df1 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -18,9 +18,9 @@ pub(crate) fn goto_type_definition( let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { let ty = match_ast! { match node { - ast::Expr(expr) => { sema.type_of_expr(&expr)? }, - ast::Pat(pat) => { sema.type_of_pat(&pat)? }, - _ => { return None }, + ast::Expr(expr) => sema.type_of_expr(&expr)?, + ast::Pat(pat) => sema.type_of_pat(&pat)?, + _ => return None, } }; diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 74877e90f..9433f3a24 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs @@ -49,8 +49,8 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { fn runnable(sema: &Semantics, item: SyntaxNode) -> Option { match_ast! { match item { - ast::FnDef(it) => { runnable_fn(sema, it) }, - ast::Module(it) => { runnable_mod(sema, it) }, + ast::FnDef(it) => runnable_fn(sema, it), + ast::Module(it) => runnable_mod(sema, it), _ => None, } } -- cgit v1.2.3 From bf569f8b29d05782597d40ec98ee33bc2574763e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 6 Apr 2020 16:58:16 +0200 Subject: Check for eprintln on CI --- crates/ra_ide/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 285381086..5599f143f 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -10,6 +10,11 @@ // For proving that RootDatabase is RefUnwindSafe. #![recursion_limit = "128"] +#[allow(unused)] +macro_rules! eprintln { + ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; +} + pub mod mock_analysis; mod source_change; -- cgit v1.2.3 From a5ffe53c9d185d790388760dfe09f265e352b6bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Apr 2020 13:19:57 +0200 Subject: Better naming for path completion --- crates/ra_ide/src/completion.rs | 8 +- crates/ra_ide/src/completion/complete_path.rs | 1046 ------------------- .../src/completion/complete_qualified_path.rs | 1046 +++++++++++++++++++ crates/ra_ide/src/completion/complete_scope.rs | 1067 -------------------- .../src/completion/complete_unqualified_path.rs | 1067 ++++++++++++++++++++ 5 files changed, 2117 insertions(+), 2117 deletions(-) delete mode 100644 crates/ra_ide/src/completion/complete_path.rs create mode 100644 crates/ra_ide/src/completion/complete_qualified_path.rs delete mode 100644 crates/ra_ide/src/completion/complete_scope.rs create mode 100644 crates/ra_ide/src/completion/complete_unqualified_path.rs (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 93157bbba..c9ba1d4ee 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -10,8 +10,8 @@ mod complete_pattern; mod complete_fn_param; mod complete_keyword; mod complete_snippet; -mod complete_path; -mod complete_scope; +mod complete_qualified_path; +mod complete_unqualified_path; mod complete_postfix; mod complete_macro_in_item_position; mod complete_trait_impl; @@ -85,8 +85,8 @@ pub(crate) fn completions( complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); complete_snippet::complete_expr_snippet(&mut acc, &ctx); complete_snippet::complete_item_snippet(&mut acc, &ctx); - complete_path::complete_path(&mut acc, &ctx); - complete_scope::complete_scope(&mut acc, &ctx); + complete_qualified_path::complete_path(&mut acc, &ctx); + complete_unqualified_path::complete_scope(&mut acc, &ctx); complete_dot::complete_dot(&mut acc, &ctx); complete_record::complete_record(&mut acc, &ctx); complete_pattern::complete_pattern(&mut acc, &ctx); diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs deleted file mode 100644 index 3ed2ae2b6..000000000 --- a/crates/ra_ide/src/completion/complete_path.rs +++ /dev/null @@ -1,1046 +0,0 @@ -//! Completion of paths, i.e. `some::prefix::<|>`. - -use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; -use ra_syntax::AstNode; -use test_utils::tested_by; - -use crate::completion::{CompletionContext, Completions}; - -pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { - let path = match &ctx.path_prefix { - Some(path) => path.clone(), - _ => return, - }; - let def = match ctx.scope().resolve_hir_path(&path) { - Some(PathResolution::Def(def)) => def, - _ => return, - }; - let context_module = ctx.scope().module(); - match def { - hir::ModuleDef::Module(module) => { - let module_scope = module.scope(ctx.db, context_module); - for (name, def) in module_scope { - if ctx.use_item_syntax.is_some() { - if let ScopeDef::Unknown = def { - if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { - if name_ref.syntax().text() == name.to_string().as_str() { - // for `use self::foo<|>`, don't suggest `foo` as a completion - tested_by!(dont_complete_current_use); - continue; - } - } - } - } - - acc.add_resolution(ctx, name.to_string(), &def); - } - } - hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { - if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { - for variant in e.variants(ctx.db) { - acc.add_enum_variant(ctx, variant, None); - } - } - let ty = match def { - hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), - hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), - _ => unreachable!(), - }; - // Iterate assoc types separately - // FIXME: complete T::AssocType - let krate = ctx.krate; - if let Some(krate) = krate { - let traits_in_scope = ctx.scope().traits_in_scope(); - ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { - if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { - return None; - } - match item { - hir::AssocItem::Function(func) => { - if !func.has_self_param(ctx.db) { - acc.add_function(ctx, func, None); - } - } - hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), - hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), - } - None::<()> - }); - - ty.iterate_impl_items(ctx.db, krate, |item| { - if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { - return None; - } - match item { - hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} - hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), - } - None::<()> - }); - } - } - hir::ModuleDef::Trait(t) => { - for item in t.items(ctx.db) { - if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { - continue; - } - match item { - hir::AssocItem::Function(func) => { - if !func.has_self_param(ctx.db) { - acc.add_function(ctx, func, None); - } - } - hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), - hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), - } - } - } - _ => {} - }; -} - -#[cfg(test)] -mod tests { - use test_utils::covers; - - use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; - use insta::assert_debug_snapshot; - - fn do_reference_completion(code: &str) -> Vec { - do_completion(code, CompletionKind::Reference) - } - - #[test] - fn dont_complete_current_use() { - covers!(dont_complete_current_use); - let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference); - assert!(completions.is_empty()); - } - - #[test] - fn dont_complete_current_use_in_braces_with_glob() { - let completions = do_completion( - r" - mod foo { pub struct S; } - use self::{foo::*, bar<|>}; - ", - CompletionKind::Reference, - ); - assert_eq!(completions.len(), 2); - } - - #[test] - fn dont_complete_primitive_in_use() { - let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType); - assert!(completions.is_empty()); - } - - #[test] - fn dont_complete_primitive_in_module_scope() { - let completions = do_completion(r"fn foo() { self::<|> }", CompletionKind::BuiltinType); - assert!(completions.is_empty()); - } - - #[test] - fn completes_primitives() { - let completions = - do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType); - assert_eq!(completions.len(), 17); - } - - #[test] - fn completes_mod_with_docs() { - assert_debug_snapshot!( - do_reference_completion( - r" - use self::my<|>; - - /// Some simple - /// docs describing `mod my`. - mod my { - struct Bar; - } - " - ), - @r###" - [ - CompletionItem { - label: "my", - source_range: [27; 29), - delete: [27; 29), - insert: "my", - kind: Module, - documentation: Documentation( - "Some simple\ndocs describing `mod my`.", - ), - }, - ] - "### - ); - } - - #[test] - fn path_visibility() { - assert_debug_snapshot!( - do_reference_completion( - r" - use self::my::<|>; - - mod my { - struct Bar; - pub struct Foo; - pub use Bar as PublicBar; - } - " - ), - @r###" - [ - CompletionItem { - label: "Foo", - source_range: [31; 31), - delete: [31; 31), - insert: "Foo", - kind: Struct, - }, - CompletionItem { - label: "PublicBar", - source_range: [31; 31), - delete: [31; 31), - insert: "PublicBar", - kind: Struct, - }, - ] - "### - ); - } - - #[test] - fn completes_use_item_starting_with_self() { - assert_debug_snapshot!( - do_reference_completion( - r" - use self::m::<|>; - - mod m { - pub struct Bar; - } - " - ), - @r###" - [ - CompletionItem { - label: "Bar", - source_range: [30; 30), - delete: [30; 30), - insert: "Bar", - kind: Struct, - }, - ] - "### - ); - } - - #[test] - fn completes_use_item_starting_with_crate() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - mod foo; - struct Spam; - //- /foo.rs - use crate::Sp<|> - " - ), - @r###" - [ - CompletionItem { - label: "Spam", - source_range: [11; 13), - delete: [11; 13), - insert: "Spam", - kind: Struct, - }, - CompletionItem { - label: "foo", - source_range: [11; 13), - delete: [11; 13), - insert: "foo", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_nested_use_tree() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - mod foo; - struct Spam; - //- /foo.rs - use crate::{Sp<|>}; - " - ), - @r###" - [ - CompletionItem { - label: "Spam", - source_range: [12; 14), - delete: [12; 14), - insert: "Spam", - kind: Struct, - }, - CompletionItem { - label: "foo", - source_range: [12; 14), - delete: [12; 14), - insert: "foo", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_deeply_nested_use_tree() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - mod foo; - pub mod bar { - pub mod baz { - pub struct Spam; - } - } - //- /foo.rs - use crate::{bar::{baz::Sp<|>}}; - " - ), - @r###" - [ - CompletionItem { - label: "Spam", - source_range: [23; 25), - delete: [23; 25), - insert: "Spam", - kind: Struct, - }, - ] - "### - ); - } - - #[test] - fn completes_enum_variant() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// An enum - enum E { - /// Foo Variant - Foo, - /// Bar Variant with i32 - Bar(i32) - } - fn foo() { let _ = E::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "Bar(…)", - source_range: [116; 116), - delete: [116; 116), - insert: "Bar($0)", - kind: EnumVariant, - lookup: "Bar", - detail: "(i32)", - documentation: Documentation( - "Bar Variant with i32", - ), - trigger_call_info: true, - }, - CompletionItem { - label: "Foo", - source_range: [116; 116), - delete: [116; 116), - insert: "Foo", - kind: EnumVariant, - detail: "()", - documentation: Documentation( - "Foo Variant", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_enum_variant_with_details() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - struct S { field: u32 } - /// An enum - enum E { - /// Foo Variant (empty) - Foo, - /// Bar Variant with i32 and u32 - Bar(i32, u32), - /// - S(S), - } - fn foo() { let _ = E::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "Bar(…)", - source_range: [180; 180), - delete: [180; 180), - insert: "Bar($0)", - kind: EnumVariant, - lookup: "Bar", - detail: "(i32, u32)", - documentation: Documentation( - "Bar Variant with i32 and u32", - ), - trigger_call_info: true, - }, - CompletionItem { - label: "Foo", - source_range: [180; 180), - delete: [180; 180), - insert: "Foo", - kind: EnumVariant, - detail: "()", - documentation: Documentation( - "Foo Variant (empty)", - ), - }, - CompletionItem { - label: "S(…)", - source_range: [180; 180), - delete: [180; 180), - insert: "S($0)", - kind: EnumVariant, - lookup: "S", - detail: "(S)", - documentation: Documentation( - "", - ), - trigger_call_info: true, - }, - ] - "### - ); - } - - #[test] - fn completes_struct_associated_method() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// A Struct - struct S; - - impl S { - /// An associated method - fn m() { } - } - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [100; 100), - delete: [100; 100), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "An associated method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_struct_associated_const() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// A Struct - struct S; - - impl S { - /// An associated const - const C: i32 = 42; - } - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "C", - source_range: [107; 107), - delete: [107; 107), - insert: "C", - kind: Const, - detail: "const C: i32 = 42;", - documentation: Documentation( - "An associated const", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_struct_associated_type() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// A Struct - struct S; - - impl S { - /// An associated type - type T = i32; - } - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "T", - source_range: [101; 101), - delete: [101; 101), - insert: "T", - kind: TypeAlias, - detail: "type T = i32;", - documentation: Documentation( - "An associated type", - ), - }, - ] - "### - ); - } - - #[test] - fn associated_item_visibility() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - struct S; - - mod m { - impl super::S { - pub(super) fn public_method() { } - fn private_method() { } - pub(super) type PublicType = u32; - type PrivateType = u32; - pub(super) const PUBLIC_CONST: u32 = 1; - const PRIVATE_CONST: u32 = 1; - } - } - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "PUBLIC_CONST", - source_range: [302; 302), - delete: [302; 302), - insert: "PUBLIC_CONST", - kind: Const, - detail: "pub(super) const PUBLIC_CONST: u32 = 1;", - }, - CompletionItem { - label: "PublicType", - source_range: [302; 302), - delete: [302; 302), - insert: "PublicType", - kind: TypeAlias, - detail: "pub(super) type PublicType = u32;", - }, - CompletionItem { - label: "public_method()", - source_range: [302; 302), - delete: [302; 302), - insert: "public_method()$0", - kind: Function, - lookup: "public_method", - detail: "pub(super) fn public_method()", - }, - ] - "### - ); - } - - #[test] - fn completes_enum_associated_method() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// An enum - enum S {}; - - impl S { - /// An associated method - fn m() { } - } - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [100; 100), - delete: [100; 100), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "An associated method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_union_associated_method() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - /// A union - union U {}; - - impl U { - /// An associated method - fn m() { } - } - - fn foo() { let _ = U::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [101; 101), - delete: [101; 101), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "An associated method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_use_paths_across_crates() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - use foo::<|>; - - //- /foo/lib.rs - pub mod bar { - pub struct S; - } - " - ), - @r###" - [ - CompletionItem { - label: "bar", - source_range: [9; 9), - delete: [9; 9), - insert: "bar", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_trait_associated_method_1() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - trait Trait { - /// A trait method - fn m(); - } - - fn foo() { let _ = Trait::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [73; 73), - delete: [73; 73), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "A trait method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_trait_associated_method_2() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - trait Trait { - /// A trait method - fn m(); - } - - struct S; - impl Trait for S {} - - fn foo() { let _ = S::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [99; 99), - delete: [99; 99), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "A trait method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_trait_associated_method_3() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /lib.rs - trait Trait { - /// A trait method - fn m(); - } - - struct S; - impl Trait for S {} - - fn foo() { let _ = ::<|> } - " - ), - @r###" - [ - CompletionItem { - label: "m()", - source_range: [110; 110), - delete: [110; 110), - insert: "m()$0", - kind: Function, - lookup: "m", - detail: "fn m()", - documentation: Documentation( - "A trait method", - ), - }, - ] - "### - ); - } - - #[test] - fn completes_type_alias() { - assert_debug_snapshot!( - do_reference_completion( - " - struct S; - impl S { fn foo() {} } - type T = S; - impl T { fn bar() {} } - - fn main() { - T::<|>; - } - " - ), - @r###" - [ - CompletionItem { - label: "bar()", - source_range: [185; 185), - delete: [185; 185), - insert: "bar()$0", - kind: Function, - lookup: "bar", - detail: "fn bar()", - }, - CompletionItem { - label: "foo()", - source_range: [185; 185), - delete: [185; 185), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - ] - "### - ); - } - - #[test] - fn completes_qualified_macros() { - assert_debug_snapshot!( - do_reference_completion( - " - #[macro_export] - macro_rules! foo { - () => {} - } - - fn main() { - let _ = crate::<|> - } - " - ), - @r###" - [ - CompletionItem { - label: "foo!", - source_range: [179; 179), - delete: [179; 179), - insert: "foo!($0)", - kind: Macro, - detail: "#[macro_export]\nmacro_rules! foo", - }, - CompletionItem { - label: "main()", - source_range: [179; 179), - delete: [179; 179), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ); - } - - #[test] - fn completes_reexported_items_under_correct_name() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn foo() { - self::m::<|> - } - - mod m { - pub use super::p::wrong_fn as right_fn; - pub use super::p::WRONG_CONST as RIGHT_CONST; - pub use super::p::WrongType as RightType; - } - mod p { - fn wrong_fn() {} - const WRONG_CONST: u32 = 1; - struct WrongType {}; - } - " - ), - @r###" - [ - CompletionItem { - label: "RIGHT_CONST", - source_range: [57; 57), - delete: [57; 57), - insert: "RIGHT_CONST", - kind: Const, - }, - CompletionItem { - label: "RightType", - source_range: [57; 57), - delete: [57; 57), - insert: "RightType", - kind: Struct, - }, - CompletionItem { - label: "right_fn()", - source_range: [57; 57), - delete: [57; 57), - insert: "right_fn()$0", - kind: Function, - lookup: "right_fn", - detail: "fn wrong_fn()", - }, - ] - "### - ); - } - - #[test] - fn completes_in_simple_macro_call() { - let completions = do_reference_completion( - r#" - macro_rules! m { ($e:expr) => { $e } } - fn main() { m!(self::f<|>); } - fn foo() {} - "#, - ); - assert_debug_snapshot!(completions, @r###" - [ - CompletionItem { - label: "foo()", - source_range: [93; 94), - delete: [93; 94), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - CompletionItem { - label: "main()", - source_range: [93; 94), - delete: [93; 94), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "###); - } - - #[test] - fn function_mod_share_name() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn foo() { - self::m::<|> - } - - mod m { - pub mod z {} - pub fn z() {} - } - ", - ), - @r###" - [ - CompletionItem { - label: "z", - source_range: [57; 57), - delete: [57; 57), - insert: "z", - kind: Module, - }, - CompletionItem { - label: "z()", - source_range: [57; 57), - delete: [57; 57), - insert: "z()$0", - kind: Function, - lookup: "z", - detail: "pub fn z()", - }, - ] - "### - ); - } - - #[test] - fn completes_hashmap_new() { - assert_debug_snapshot!( - do_reference_completion( - r" - struct RandomState; - struct HashMap {} - - impl HashMap { - pub fn new() -> HashMap { } - } - fn foo() { - HashMap::<|> - } - " - ), - @r###" - [ - CompletionItem { - label: "new()", - source_range: [292; 292), - delete: [292; 292), - insert: "new()$0", - kind: Function, - lookup: "new", - detail: "pub fn new() -> HashMap", - }, - ] - "### - ); - } -} diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs new file mode 100644 index 000000000..3ed2ae2b6 --- /dev/null +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs @@ -0,0 +1,1046 @@ +//! Completion of paths, i.e. `some::prefix::<|>`. + +use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; +use ra_syntax::AstNode; +use test_utils::tested_by; + +use crate::completion::{CompletionContext, Completions}; + +pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { + let path = match &ctx.path_prefix { + Some(path) => path.clone(), + _ => return, + }; + let def = match ctx.scope().resolve_hir_path(&path) { + Some(PathResolution::Def(def)) => def, + _ => return, + }; + let context_module = ctx.scope().module(); + match def { + hir::ModuleDef::Module(module) => { + let module_scope = module.scope(ctx.db, context_module); + for (name, def) in module_scope { + if ctx.use_item_syntax.is_some() { + if let ScopeDef::Unknown = def { + if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { + if name_ref.syntax().text() == name.to_string().as_str() { + // for `use self::foo<|>`, don't suggest `foo` as a completion + tested_by!(dont_complete_current_use); + continue; + } + } + } + } + + acc.add_resolution(ctx, name.to_string(), &def); + } + } + hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { + if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { + for variant in e.variants(ctx.db) { + acc.add_enum_variant(ctx, variant, None); + } + } + let ty = match def { + hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), + hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), + _ => unreachable!(), + }; + // Iterate assoc types separately + // FIXME: complete T::AssocType + let krate = ctx.krate; + if let Some(krate) = krate { + let traits_in_scope = ctx.scope().traits_in_scope(); + ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { + if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { + return None; + } + match item { + hir::AssocItem::Function(func) => { + if !func.has_self_param(ctx.db) { + acc.add_function(ctx, func, None); + } + } + hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + None::<()> + }); + + ty.iterate_impl_items(ctx.db, krate, |item| { + if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { + return None; + } + match item { + hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + None::<()> + }); + } + } + hir::ModuleDef::Trait(t) => { + for item in t.items(ctx.db) { + if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { + continue; + } + match item { + hir::AssocItem::Function(func) => { + if !func.has_self_param(ctx.db) { + acc.add_function(ctx, func, None); + } + } + hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + } + } + _ => {} + }; +} + +#[cfg(test)] +mod tests { + use test_utils::covers; + + use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; + use insta::assert_debug_snapshot; + + fn do_reference_completion(code: &str) -> Vec { + do_completion(code, CompletionKind::Reference) + } + + #[test] + fn dont_complete_current_use() { + covers!(dont_complete_current_use); + let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference); + assert!(completions.is_empty()); + } + + #[test] + fn dont_complete_current_use_in_braces_with_glob() { + let completions = do_completion( + r" + mod foo { pub struct S; } + use self::{foo::*, bar<|>}; + ", + CompletionKind::Reference, + ); + assert_eq!(completions.len(), 2); + } + + #[test] + fn dont_complete_primitive_in_use() { + let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType); + assert!(completions.is_empty()); + } + + #[test] + fn dont_complete_primitive_in_module_scope() { + let completions = do_completion(r"fn foo() { self::<|> }", CompletionKind::BuiltinType); + assert!(completions.is_empty()); + } + + #[test] + fn completes_primitives() { + let completions = + do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType); + assert_eq!(completions.len(), 17); + } + + #[test] + fn completes_mod_with_docs() { + assert_debug_snapshot!( + do_reference_completion( + r" + use self::my<|>; + + /// Some simple + /// docs describing `mod my`. + mod my { + struct Bar; + } + " + ), + @r###" + [ + CompletionItem { + label: "my", + source_range: [27; 29), + delete: [27; 29), + insert: "my", + kind: Module, + documentation: Documentation( + "Some simple\ndocs describing `mod my`.", + ), + }, + ] + "### + ); + } + + #[test] + fn path_visibility() { + assert_debug_snapshot!( + do_reference_completion( + r" + use self::my::<|>; + + mod my { + struct Bar; + pub struct Foo; + pub use Bar as PublicBar; + } + " + ), + @r###" + [ + CompletionItem { + label: "Foo", + source_range: [31; 31), + delete: [31; 31), + insert: "Foo", + kind: Struct, + }, + CompletionItem { + label: "PublicBar", + source_range: [31; 31), + delete: [31; 31), + insert: "PublicBar", + kind: Struct, + }, + ] + "### + ); + } + + #[test] + fn completes_use_item_starting_with_self() { + assert_debug_snapshot!( + do_reference_completion( + r" + use self::m::<|>; + + mod m { + pub struct Bar; + } + " + ), + @r###" + [ + CompletionItem { + label: "Bar", + source_range: [30; 30), + delete: [30; 30), + insert: "Bar", + kind: Struct, + }, + ] + "### + ); + } + + #[test] + fn completes_use_item_starting_with_crate() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + mod foo; + struct Spam; + //- /foo.rs + use crate::Sp<|> + " + ), + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [11; 13), + delete: [11; 13), + insert: "Spam", + kind: Struct, + }, + CompletionItem { + label: "foo", + source_range: [11; 13), + delete: [11; 13), + insert: "foo", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_nested_use_tree() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + mod foo; + struct Spam; + //- /foo.rs + use crate::{Sp<|>}; + " + ), + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [12; 14), + delete: [12; 14), + insert: "Spam", + kind: Struct, + }, + CompletionItem { + label: "foo", + source_range: [12; 14), + delete: [12; 14), + insert: "foo", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_deeply_nested_use_tree() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + mod foo; + pub mod bar { + pub mod baz { + pub struct Spam; + } + } + //- /foo.rs + use crate::{bar::{baz::Sp<|>}}; + " + ), + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [23; 25), + delete: [23; 25), + insert: "Spam", + kind: Struct, + }, + ] + "### + ); + } + + #[test] + fn completes_enum_variant() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// An enum + enum E { + /// Foo Variant + Foo, + /// Bar Variant with i32 + Bar(i32) + } + fn foo() { let _ = E::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "Bar(…)", + source_range: [116; 116), + delete: [116; 116), + insert: "Bar($0)", + kind: EnumVariant, + lookup: "Bar", + detail: "(i32)", + documentation: Documentation( + "Bar Variant with i32", + ), + trigger_call_info: true, + }, + CompletionItem { + label: "Foo", + source_range: [116; 116), + delete: [116; 116), + insert: "Foo", + kind: EnumVariant, + detail: "()", + documentation: Documentation( + "Foo Variant", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_enum_variant_with_details() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + struct S { field: u32 } + /// An enum + enum E { + /// Foo Variant (empty) + Foo, + /// Bar Variant with i32 and u32 + Bar(i32, u32), + /// + S(S), + } + fn foo() { let _ = E::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "Bar(…)", + source_range: [180; 180), + delete: [180; 180), + insert: "Bar($0)", + kind: EnumVariant, + lookup: "Bar", + detail: "(i32, u32)", + documentation: Documentation( + "Bar Variant with i32 and u32", + ), + trigger_call_info: true, + }, + CompletionItem { + label: "Foo", + source_range: [180; 180), + delete: [180; 180), + insert: "Foo", + kind: EnumVariant, + detail: "()", + documentation: Documentation( + "Foo Variant (empty)", + ), + }, + CompletionItem { + label: "S(…)", + source_range: [180; 180), + delete: [180; 180), + insert: "S($0)", + kind: EnumVariant, + lookup: "S", + detail: "(S)", + documentation: Documentation( + "", + ), + trigger_call_info: true, + }, + ] + "### + ); + } + + #[test] + fn completes_struct_associated_method() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// A Struct + struct S; + + impl S { + /// An associated method + fn m() { } + } + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [100; 100), + delete: [100; 100), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "An associated method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_struct_associated_const() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// A Struct + struct S; + + impl S { + /// An associated const + const C: i32 = 42; + } + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "C", + source_range: [107; 107), + delete: [107; 107), + insert: "C", + kind: Const, + detail: "const C: i32 = 42;", + documentation: Documentation( + "An associated const", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_struct_associated_type() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// A Struct + struct S; + + impl S { + /// An associated type + type T = i32; + } + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "T", + source_range: [101; 101), + delete: [101; 101), + insert: "T", + kind: TypeAlias, + detail: "type T = i32;", + documentation: Documentation( + "An associated type", + ), + }, + ] + "### + ); + } + + #[test] + fn associated_item_visibility() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + struct S; + + mod m { + impl super::S { + pub(super) fn public_method() { } + fn private_method() { } + pub(super) type PublicType = u32; + type PrivateType = u32; + pub(super) const PUBLIC_CONST: u32 = 1; + const PRIVATE_CONST: u32 = 1; + } + } + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "PUBLIC_CONST", + source_range: [302; 302), + delete: [302; 302), + insert: "PUBLIC_CONST", + kind: Const, + detail: "pub(super) const PUBLIC_CONST: u32 = 1;", + }, + CompletionItem { + label: "PublicType", + source_range: [302; 302), + delete: [302; 302), + insert: "PublicType", + kind: TypeAlias, + detail: "pub(super) type PublicType = u32;", + }, + CompletionItem { + label: "public_method()", + source_range: [302; 302), + delete: [302; 302), + insert: "public_method()$0", + kind: Function, + lookup: "public_method", + detail: "pub(super) fn public_method()", + }, + ] + "### + ); + } + + #[test] + fn completes_enum_associated_method() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// An enum + enum S {}; + + impl S { + /// An associated method + fn m() { } + } + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [100; 100), + delete: [100; 100), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "An associated method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_union_associated_method() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + /// A union + union U {}; + + impl U { + /// An associated method + fn m() { } + } + + fn foo() { let _ = U::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [101; 101), + delete: [101; 101), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "An associated method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_use_paths_across_crates() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + use foo::<|>; + + //- /foo/lib.rs + pub mod bar { + pub struct S; + } + " + ), + @r###" + [ + CompletionItem { + label: "bar", + source_range: [9; 9), + delete: [9; 9), + insert: "bar", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_trait_associated_method_1() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + fn foo() { let _ = Trait::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [73; 73), + delete: [73; 73), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_trait_associated_method_2() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + struct S; + impl Trait for S {} + + fn foo() { let _ = S::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [99; 99), + delete: [99; 99), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_trait_associated_method_3() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + struct S; + impl Trait for S {} + + fn foo() { let _ = ::<|> } + " + ), + @r###" + [ + CompletionItem { + label: "m()", + source_range: [110; 110), + delete: [110; 110), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### + ); + } + + #[test] + fn completes_type_alias() { + assert_debug_snapshot!( + do_reference_completion( + " + struct S; + impl S { fn foo() {} } + type T = S; + impl T { fn bar() {} } + + fn main() { + T::<|>; + } + " + ), + @r###" + [ + CompletionItem { + label: "bar()", + source_range: [185; 185), + delete: [185; 185), + insert: "bar()$0", + kind: Function, + lookup: "bar", + detail: "fn bar()", + }, + CompletionItem { + label: "foo()", + source_range: [185; 185), + delete: [185; 185), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + ] + "### + ); + } + + #[test] + fn completes_qualified_macros() { + assert_debug_snapshot!( + do_reference_completion( + " + #[macro_export] + macro_rules! foo { + () => {} + } + + fn main() { + let _ = crate::<|> + } + " + ), + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [179; 179), + delete: [179; 179), + insert: "foo!($0)", + kind: Macro, + detail: "#[macro_export]\nmacro_rules! foo", + }, + CompletionItem { + label: "main()", + source_range: [179; 179), + delete: [179; 179), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); + } + + #[test] + fn completes_reexported_items_under_correct_name() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn foo() { + self::m::<|> + } + + mod m { + pub use super::p::wrong_fn as right_fn; + pub use super::p::WRONG_CONST as RIGHT_CONST; + pub use super::p::WrongType as RightType; + } + mod p { + fn wrong_fn() {} + const WRONG_CONST: u32 = 1; + struct WrongType {}; + } + " + ), + @r###" + [ + CompletionItem { + label: "RIGHT_CONST", + source_range: [57; 57), + delete: [57; 57), + insert: "RIGHT_CONST", + kind: Const, + }, + CompletionItem { + label: "RightType", + source_range: [57; 57), + delete: [57; 57), + insert: "RightType", + kind: Struct, + }, + CompletionItem { + label: "right_fn()", + source_range: [57; 57), + delete: [57; 57), + insert: "right_fn()$0", + kind: Function, + lookup: "right_fn", + detail: "fn wrong_fn()", + }, + ] + "### + ); + } + + #[test] + fn completes_in_simple_macro_call() { + let completions = do_reference_completion( + r#" + macro_rules! m { ($e:expr) => { $e } } + fn main() { m!(self::f<|>); } + fn foo() {} + "#, + ); + assert_debug_snapshot!(completions, @r###" + [ + CompletionItem { + label: "foo()", + source_range: [93; 94), + delete: [93; 94), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + CompletionItem { + label: "main()", + source_range: [93; 94), + delete: [93; 94), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "###); + } + + #[test] + fn function_mod_share_name() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn foo() { + self::m::<|> + } + + mod m { + pub mod z {} + pub fn z() {} + } + ", + ), + @r###" + [ + CompletionItem { + label: "z", + source_range: [57; 57), + delete: [57; 57), + insert: "z", + kind: Module, + }, + CompletionItem { + label: "z()", + source_range: [57; 57), + delete: [57; 57), + insert: "z()$0", + kind: Function, + lookup: "z", + detail: "pub fn z()", + }, + ] + "### + ); + } + + #[test] + fn completes_hashmap_new() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct RandomState; + struct HashMap {} + + impl HashMap { + pub fn new() -> HashMap { } + } + fn foo() { + HashMap::<|> + } + " + ), + @r###" + [ + CompletionItem { + label: "new()", + source_range: [292; 292), + delete: [292; 292), + insert: "new()$0", + kind: Function, + lookup: "new", + detail: "pub fn new() -> HashMap", + }, + ] + "### + ); + } +} diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs deleted file mode 100644 index 665597e4c..000000000 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ /dev/null @@ -1,1067 +0,0 @@ -//! Completion of names from the current scope, e.g. locals and imported items. - -use crate::completion::{CompletionContext, Completions}; - -pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { - if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) { - return; - } - - ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res)); -} - -#[cfg(test)] -mod tests { - use insta::assert_debug_snapshot; - - use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; - - fn do_reference_completion(ra_fixture: &str) -> Vec { - do_completion(ra_fixture, CompletionKind::Reference) - } - - #[test] - fn bind_pat_and_path_ignore_at() { - assert_debug_snapshot!( - do_reference_completion( - r" - enum Enum { - A, - B, - } - fn quux(x: Option) { - match x { - None => (), - Some(en<|> @ Enum::A) => (), - } - } - " - ), - @r###"[]"### - ); - } - - #[test] - fn bind_pat_and_path_ignore_ref() { - assert_debug_snapshot!( - do_reference_completion( - r" - enum Enum { - A, - B, - } - fn quux(x: Option) { - match x { - None => (), - Some(ref en<|>) => (), - } - } - " - ), - @r###"[]"### - ); - } - - #[test] - fn bind_pat_and_path() { - assert_debug_snapshot!( - do_reference_completion( - r" - enum Enum { - A, - B, - } - fn quux(x: Option) { - match x { - None => (), - Some(En<|>) => (), - } - } - " - ), - @r###" - [ - CompletionItem { - label: "Enum", - source_range: [231; 233), - delete: [231; 233), - insert: "Enum", - kind: Enum, - }, - ] - "### - ); - } - - #[test] - fn completes_bindings_from_let() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn quux(x: i32) { - let y = 92; - 1 + <|>; - let z = (); - } - " - ), - @r###" - [ - CompletionItem { - label: "quux(…)", - source_range: [91; 91), - delete: [91; 91), - insert: "quux(${1:x})$0", - kind: Function, - lookup: "quux", - detail: "fn quux(x: i32)", - trigger_call_info: true, - }, - CompletionItem { - label: "x", - source_range: [91; 91), - delete: [91; 91), - insert: "x", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "y", - source_range: [91; 91), - delete: [91; 91), - insert: "y", - kind: Binding, - detail: "i32", - }, - ] - "### - ); - } - - #[test] - fn completes_bindings_from_if_let() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn quux() { - if let Some(x) = foo() { - let y = 92; - }; - if let Some(a) = bar() { - let b = 62; - 1 + <|> - } - } - " - ), - @r###" - [ - CompletionItem { - label: "a", - source_range: [242; 242), - delete: [242; 242), - insert: "a", - kind: Binding, - }, - CompletionItem { - label: "b", - source_range: [242; 242), - delete: [242; 242), - insert: "b", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "quux()", - source_range: [242; 242), - delete: [242; 242), - insert: "quux()$0", - kind: Function, - lookup: "quux", - detail: "fn quux()", - }, - ] - "### - ); - } - - #[test] - fn completes_bindings_from_for() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn quux() { - for x in &[1, 2, 3] { - <|> - } - } - " - ), - @r###" - [ - CompletionItem { - label: "quux()", - source_range: [95; 95), - delete: [95; 95), - insert: "quux()$0", - kind: Function, - lookup: "quux", - detail: "fn quux()", - }, - CompletionItem { - label: "x", - source_range: [95; 95), - delete: [95; 95), - insert: "x", - kind: Binding, - }, - ] - "### - ); - } - - #[test] - fn completes_generic_params() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn quux() { - <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "T", - source_range: [52; 52), - delete: [52; 52), - insert: "T", - kind: TypeParam, - }, - CompletionItem { - label: "quux()", - source_range: [52; 52), - delete: [52; 52), - insert: "quux()$0", - kind: Function, - lookup: "quux", - detail: "fn quux()", - }, - ] - "### - ); - } - - #[test] - fn completes_generic_params_in_struct() { - assert_debug_snapshot!( - do_reference_completion( - r" - struct X { - x: <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "Self", - source_range: [54; 54), - delete: [54; 54), - insert: "Self", - kind: TypeParam, - }, - CompletionItem { - label: "T", - source_range: [54; 54), - delete: [54; 54), - insert: "T", - kind: TypeParam, - }, - CompletionItem { - label: "X<…>", - source_range: [54; 54), - delete: [54; 54), - insert: "X<$0>", - kind: Struct, - lookup: "X", - }, - ] - "### - ); - } - - #[test] - fn completes_self_in_enum() { - assert_debug_snapshot!( - do_reference_completion( - r" - enum X { - Y(<|>) - } - " - ), - @r###" - [ - CompletionItem { - label: "Self", - source_range: [48; 48), - delete: [48; 48), - insert: "Self", - kind: TypeParam, - }, - CompletionItem { - label: "X", - source_range: [48; 48), - delete: [48; 48), - insert: "X", - kind: Enum, - }, - ] - "### - ); - } - - #[test] - fn completes_module_items() { - assert_debug_snapshot!( - do_reference_completion( - r" - struct Foo; - enum Baz {} - fn quux() { - <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "Baz", - source_range: [105; 105), - delete: [105; 105), - insert: "Baz", - kind: Enum, - }, - CompletionItem { - label: "Foo", - source_range: [105; 105), - delete: [105; 105), - insert: "Foo", - kind: Struct, - }, - CompletionItem { - label: "quux()", - source_range: [105; 105), - delete: [105; 105), - insert: "quux()$0", - kind: Function, - lookup: "quux", - detail: "fn quux()", - }, - ] - "### - ); - } - - #[test] - fn completes_extern_prelude() { - assert_debug_snapshot!( - do_reference_completion( - r" - //- /lib.rs - use <|>; - - //- /other_crate/lib.rs - // nothing here - " - ), - @r###" - [ - CompletionItem { - label: "other_crate", - source_range: [4; 4), - delete: [4; 4), - insert: "other_crate", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_module_items_in_nested_modules() { - assert_debug_snapshot!( - do_reference_completion( - r" - struct Foo; - mod m { - struct Bar; - fn quux() { <|> } - } - " - ), - @r###" - [ - CompletionItem { - label: "Bar", - source_range: [117; 117), - delete: [117; 117), - insert: "Bar", - kind: Struct, - }, - CompletionItem { - label: "quux()", - source_range: [117; 117), - delete: [117; 117), - insert: "quux()$0", - kind: Function, - lookup: "quux", - detail: "fn quux()", - }, - ] - "### - ); - } - - #[test] - fn completes_return_type() { - assert_debug_snapshot!( - do_reference_completion( - r" - struct Foo; - fn x() -> <|> - " - ), - @r###" - [ - CompletionItem { - label: "Foo", - source_range: [55; 55), - delete: [55; 55), - insert: "Foo", - kind: Struct, - }, - CompletionItem { - label: "x()", - source_range: [55; 55), - delete: [55; 55), - insert: "x()$0", - kind: Function, - lookup: "x", - detail: "fn x()", - }, - ] - "### - ); - } - - #[test] - fn dont_show_both_completions_for_shadowing() { - assert_debug_snapshot!( - do_reference_completion( - r" - fn foo() { - let bar = 92; - { - let bar = 62; - <|> - } - } - " - ), - @r###" - [ - CompletionItem { - label: "bar", - source_range: [146; 146), - delete: [146; 146), - insert: "bar", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "foo()", - source_range: [146; 146), - delete: [146; 146), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - ] - "### - ); - } - - #[test] - fn completes_self_in_methods() { - assert_debug_snapshot!( - do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), - @r###" - [ - CompletionItem { - label: "Self", - source_range: [25; 25), - delete: [25; 25), - insert: "Self", - kind: TypeParam, - }, - CompletionItem { - label: "self", - source_range: [25; 25), - delete: [25; 25), - insert: "self", - kind: Binding, - detail: "&{unknown}", - }, - ] - "### - ); - } - - #[test] - fn completes_prelude() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - fn foo() { let x: <|> } - - //- /std/lib.rs - #[prelude_import] - use prelude::*; - - mod prelude { - struct Option; - } - " - ), - @r###" - [ - CompletionItem { - label: "Option", - source_range: [18; 18), - delete: [18; 18), - insert: "Option", - kind: Struct, - }, - CompletionItem { - label: "foo()", - source_range: [18; 18), - delete: [18; 18), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - CompletionItem { - label: "std", - source_range: [18; 18), - delete: [18; 18), - insert: "std", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_std_prelude_if_core_is_defined() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - fn foo() { let x: <|> } - - //- /core/lib.rs - #[prelude_import] - use prelude::*; - - mod prelude { - struct Option; - } - - //- /std/lib.rs - #[prelude_import] - use prelude::*; - - mod prelude { - struct String; - } - " - ), - @r###" - [ - CompletionItem { - label: "String", - source_range: [18; 18), - delete: [18; 18), - insert: "String", - kind: Struct, - }, - CompletionItem { - label: "core", - source_range: [18; 18), - delete: [18; 18), - insert: "core", - kind: Module, - }, - CompletionItem { - label: "foo()", - source_range: [18; 18), - delete: [18; 18), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - CompletionItem { - label: "std", - source_range: [18; 18), - delete: [18; 18), - insert: "std", - kind: Module, - }, - ] - "### - ); - } - - #[test] - fn completes_macros_as_value() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - macro_rules! foo { - () => {} - } - - #[macro_use] - mod m1 { - macro_rules! bar { - () => {} - } - } - - mod m2 { - macro_rules! nope { - () => {} - } - - #[macro_export] - macro_rules! baz { - () => {} - } - } - - fn main() { - let v = <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "bar!", - source_range: [252; 252), - delete: [252; 252), - insert: "bar!($0)", - kind: Macro, - detail: "macro_rules! bar", - }, - CompletionItem { - label: "baz!", - source_range: [252; 252), - delete: [252; 252), - insert: "baz!($0)", - kind: Macro, - detail: "#[macro_export]\nmacro_rules! baz", - }, - CompletionItem { - label: "foo!", - source_range: [252; 252), - delete: [252; 252), - insert: "foo!($0)", - kind: Macro, - detail: "macro_rules! foo", - }, - CompletionItem { - label: "m1", - source_range: [252; 252), - delete: [252; 252), - insert: "m1", - kind: Module, - }, - CompletionItem { - label: "m2", - source_range: [252; 252), - delete: [252; 252), - insert: "m2", - kind: Module, - }, - CompletionItem { - label: "main()", - source_range: [252; 252), - delete: [252; 252), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ); - } - - #[test] - fn completes_both_macro_and_value() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - macro_rules! foo { - () => {} - } - - fn foo() { - <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "foo!", - source_range: [49; 49), - delete: [49; 49), - insert: "foo!($0)", - kind: Macro, - detail: "macro_rules! foo", - }, - CompletionItem { - label: "foo()", - source_range: [49; 49), - delete: [49; 49), - insert: "foo()$0", - kind: Function, - lookup: "foo", - detail: "fn foo()", - }, - ] - "### - ); - } - - #[test] - fn completes_macros_as_type() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - macro_rules! foo { - () => {} - } - - fn main() { - let x: <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "foo!", - source_range: [57; 57), - delete: [57; 57), - insert: "foo!($0)", - kind: Macro, - detail: "macro_rules! foo", - }, - CompletionItem { - label: "main()", - source_range: [57; 57), - delete: [57; 57), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ); - } - - #[test] - fn completes_macros_as_stmt() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - macro_rules! foo { - () => {} - } - - fn main() { - <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "foo!", - source_range: [50; 50), - delete: [50; 50), - insert: "foo!($0)", - kind: Macro, - detail: "macro_rules! foo", - }, - CompletionItem { - label: "main()", - source_range: [50; 50), - delete: [50; 50), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ); - } - - #[test] - fn completes_local_item() { - assert_debug_snapshot!( - do_reference_completion( - " - //- /main.rs - fn main() { - return f<|>; - fn frobnicate() {} - } - " - ), - @r###" - [ - CompletionItem { - label: "frobnicate()", - source_range: [23; 24), - delete: [23; 24), - insert: "frobnicate()$0", - kind: Function, - lookup: "frobnicate", - detail: "fn frobnicate()", - }, - CompletionItem { - label: "main()", - source_range: [23; 24), - delete: [23; 24), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ) - } - - #[test] - fn completes_in_simple_macro_1() { - assert_debug_snapshot!( - do_reference_completion( - r" - macro_rules! m { ($e:expr) => { $e } } - fn quux(x: i32) { - let y = 92; - m!(<|>); - } - " - ), - @r###" - [ - CompletionItem { - label: "m!", - source_range: [145; 145), - delete: [145; 145), - insert: "m!($0)", - kind: Macro, - detail: "macro_rules! m", - }, - CompletionItem { - label: "quux(…)", - source_range: [145; 145), - delete: [145; 145), - insert: "quux(${1:x})$0", - kind: Function, - lookup: "quux", - detail: "fn quux(x: i32)", - trigger_call_info: true, - }, - CompletionItem { - label: "x", - source_range: [145; 145), - delete: [145; 145), - insert: "x", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "y", - source_range: [145; 145), - delete: [145; 145), - insert: "y", - kind: Binding, - detail: "i32", - }, - ] - "### - ); - } - - #[test] - fn completes_in_simple_macro_2() { - assert_debug_snapshot!( - do_reference_completion( - r" - macro_rules! m { ($e:expr) => { $e } } - fn quux(x: i32) { - let y = 92; - m!(x<|>); - } - " - ), - @r###" - [ - CompletionItem { - label: "m!", - source_range: [145; 146), - delete: [145; 146), - insert: "m!($0)", - kind: Macro, - detail: "macro_rules! m", - }, - CompletionItem { - label: "quux(…)", - source_range: [145; 146), - delete: [145; 146), - insert: "quux(${1:x})$0", - kind: Function, - lookup: "quux", - detail: "fn quux(x: i32)", - trigger_call_info: true, - }, - CompletionItem { - label: "x", - source_range: [145; 146), - delete: [145; 146), - insert: "x", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "y", - source_range: [145; 146), - delete: [145; 146), - insert: "y", - kind: Binding, - detail: "i32", - }, - ] - "### - ); - } - - #[test] - fn completes_in_simple_macro_without_closing_parens() { - assert_debug_snapshot!( - do_reference_completion( - r" - macro_rules! m { ($e:expr) => { $e } } - fn quux(x: i32) { - let y = 92; - m!(x<|> - } - " - ), - @r###" - [ - CompletionItem { - label: "m!", - source_range: [145; 146), - delete: [145; 146), - insert: "m!($0)", - kind: Macro, - detail: "macro_rules! m", - }, - CompletionItem { - label: "quux(…)", - source_range: [145; 146), - delete: [145; 146), - insert: "quux(${1:x})$0", - kind: Function, - lookup: "quux", - detail: "fn quux(x: i32)", - trigger_call_info: true, - }, - CompletionItem { - label: "x", - source_range: [145; 146), - delete: [145; 146), - insert: "x", - kind: Binding, - detail: "i32", - }, - CompletionItem { - label: "y", - source_range: [145; 146), - delete: [145; 146), - insert: "y", - kind: Binding, - detail: "i32", - }, - ] - "### - ); - } - - #[test] - fn completes_unresolved_uses() { - assert_debug_snapshot!( - do_reference_completion( - r" - use spam::Quux; - - fn main() { - <|> - } - " - ), - @r###" - [ - CompletionItem { - label: "Quux", - source_range: [82; 82), - delete: [82; 82), - insert: "Quux", - }, - CompletionItem { - label: "main()", - source_range: [82; 82), - delete: [82; 82), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - ] - "### - ); - } -} diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs new file mode 100644 index 000000000..665597e4c --- /dev/null +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs @@ -0,0 +1,1067 @@ +//! Completion of names from the current scope, e.g. locals and imported items. + +use crate::completion::{CompletionContext, Completions}; + +pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { + if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) { + return; + } + + ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res)); +} + +#[cfg(test)] +mod tests { + use insta::assert_debug_snapshot; + + use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; + + fn do_reference_completion(ra_fixture: &str) -> Vec { + do_completion(ra_fixture, CompletionKind::Reference) + } + + #[test] + fn bind_pat_and_path_ignore_at() { + assert_debug_snapshot!( + do_reference_completion( + r" + enum Enum { + A, + B, + } + fn quux(x: Option) { + match x { + None => (), + Some(en<|> @ Enum::A) => (), + } + } + " + ), + @r###"[]"### + ); + } + + #[test] + fn bind_pat_and_path_ignore_ref() { + assert_debug_snapshot!( + do_reference_completion( + r" + enum Enum { + A, + B, + } + fn quux(x: Option) { + match x { + None => (), + Some(ref en<|>) => (), + } + } + " + ), + @r###"[]"### + ); + } + + #[test] + fn bind_pat_and_path() { + assert_debug_snapshot!( + do_reference_completion( + r" + enum Enum { + A, + B, + } + fn quux(x: Option) { + match x { + None => (), + Some(En<|>) => (), + } + } + " + ), + @r###" + [ + CompletionItem { + label: "Enum", + source_range: [231; 233), + delete: [231; 233), + insert: "Enum", + kind: Enum, + }, + ] + "### + ); + } + + #[test] + fn completes_bindings_from_let() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn quux(x: i32) { + let y = 92; + 1 + <|>; + let z = (); + } + " + ), + @r###" + [ + CompletionItem { + label: "quux(…)", + source_range: [91; 91), + delete: [91; 91), + insert: "quux(${1:x})$0", + kind: Function, + lookup: "quux", + detail: "fn quux(x: i32)", + trigger_call_info: true, + }, + CompletionItem { + label: "x", + source_range: [91; 91), + delete: [91; 91), + insert: "x", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "y", + source_range: [91; 91), + delete: [91; 91), + insert: "y", + kind: Binding, + detail: "i32", + }, + ] + "### + ); + } + + #[test] + fn completes_bindings_from_if_let() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn quux() { + if let Some(x) = foo() { + let y = 92; + }; + if let Some(a) = bar() { + let b = 62; + 1 + <|> + } + } + " + ), + @r###" + [ + CompletionItem { + label: "a", + source_range: [242; 242), + delete: [242; 242), + insert: "a", + kind: Binding, + }, + CompletionItem { + label: "b", + source_range: [242; 242), + delete: [242; 242), + insert: "b", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "quux()", + source_range: [242; 242), + delete: [242; 242), + insert: "quux()$0", + kind: Function, + lookup: "quux", + detail: "fn quux()", + }, + ] + "### + ); + } + + #[test] + fn completes_bindings_from_for() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn quux() { + for x in &[1, 2, 3] { + <|> + } + } + " + ), + @r###" + [ + CompletionItem { + label: "quux()", + source_range: [95; 95), + delete: [95; 95), + insert: "quux()$0", + kind: Function, + lookup: "quux", + detail: "fn quux()", + }, + CompletionItem { + label: "x", + source_range: [95; 95), + delete: [95; 95), + insert: "x", + kind: Binding, + }, + ] + "### + ); + } + + #[test] + fn completes_generic_params() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn quux() { + <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "T", + source_range: [52; 52), + delete: [52; 52), + insert: "T", + kind: TypeParam, + }, + CompletionItem { + label: "quux()", + source_range: [52; 52), + delete: [52; 52), + insert: "quux()$0", + kind: Function, + lookup: "quux", + detail: "fn quux()", + }, + ] + "### + ); + } + + #[test] + fn completes_generic_params_in_struct() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct X { + x: <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "Self", + source_range: [54; 54), + delete: [54; 54), + insert: "Self", + kind: TypeParam, + }, + CompletionItem { + label: "T", + source_range: [54; 54), + delete: [54; 54), + insert: "T", + kind: TypeParam, + }, + CompletionItem { + label: "X<…>", + source_range: [54; 54), + delete: [54; 54), + insert: "X<$0>", + kind: Struct, + lookup: "X", + }, + ] + "### + ); + } + + #[test] + fn completes_self_in_enum() { + assert_debug_snapshot!( + do_reference_completion( + r" + enum X { + Y(<|>) + } + " + ), + @r###" + [ + CompletionItem { + label: "Self", + source_range: [48; 48), + delete: [48; 48), + insert: "Self", + kind: TypeParam, + }, + CompletionItem { + label: "X", + source_range: [48; 48), + delete: [48; 48), + insert: "X", + kind: Enum, + }, + ] + "### + ); + } + + #[test] + fn completes_module_items() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct Foo; + enum Baz {} + fn quux() { + <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "Baz", + source_range: [105; 105), + delete: [105; 105), + insert: "Baz", + kind: Enum, + }, + CompletionItem { + label: "Foo", + source_range: [105; 105), + delete: [105; 105), + insert: "Foo", + kind: Struct, + }, + CompletionItem { + label: "quux()", + source_range: [105; 105), + delete: [105; 105), + insert: "quux()$0", + kind: Function, + lookup: "quux", + detail: "fn quux()", + }, + ] + "### + ); + } + + #[test] + fn completes_extern_prelude() { + assert_debug_snapshot!( + do_reference_completion( + r" + //- /lib.rs + use <|>; + + //- /other_crate/lib.rs + // nothing here + " + ), + @r###" + [ + CompletionItem { + label: "other_crate", + source_range: [4; 4), + delete: [4; 4), + insert: "other_crate", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_module_items_in_nested_modules() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct Foo; + mod m { + struct Bar; + fn quux() { <|> } + } + " + ), + @r###" + [ + CompletionItem { + label: "Bar", + source_range: [117; 117), + delete: [117; 117), + insert: "Bar", + kind: Struct, + }, + CompletionItem { + label: "quux()", + source_range: [117; 117), + delete: [117; 117), + insert: "quux()$0", + kind: Function, + lookup: "quux", + detail: "fn quux()", + }, + ] + "### + ); + } + + #[test] + fn completes_return_type() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct Foo; + fn x() -> <|> + " + ), + @r###" + [ + CompletionItem { + label: "Foo", + source_range: [55; 55), + delete: [55; 55), + insert: "Foo", + kind: Struct, + }, + CompletionItem { + label: "x()", + source_range: [55; 55), + delete: [55; 55), + insert: "x()$0", + kind: Function, + lookup: "x", + detail: "fn x()", + }, + ] + "### + ); + } + + #[test] + fn dont_show_both_completions_for_shadowing() { + assert_debug_snapshot!( + do_reference_completion( + r" + fn foo() { + let bar = 92; + { + let bar = 62; + <|> + } + } + " + ), + @r###" + [ + CompletionItem { + label: "bar", + source_range: [146; 146), + delete: [146; 146), + insert: "bar", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "foo()", + source_range: [146; 146), + delete: [146; 146), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + ] + "### + ); + } + + #[test] + fn completes_self_in_methods() { + assert_debug_snapshot!( + do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), + @r###" + [ + CompletionItem { + label: "Self", + source_range: [25; 25), + delete: [25; 25), + insert: "Self", + kind: TypeParam, + }, + CompletionItem { + label: "self", + source_range: [25; 25), + delete: [25; 25), + insert: "self", + kind: Binding, + detail: "&{unknown}", + }, + ] + "### + ); + } + + #[test] + fn completes_prelude() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + fn foo() { let x: <|> } + + //- /std/lib.rs + #[prelude_import] + use prelude::*; + + mod prelude { + struct Option; + } + " + ), + @r###" + [ + CompletionItem { + label: "Option", + source_range: [18; 18), + delete: [18; 18), + insert: "Option", + kind: Struct, + }, + CompletionItem { + label: "foo()", + source_range: [18; 18), + delete: [18; 18), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + CompletionItem { + label: "std", + source_range: [18; 18), + delete: [18; 18), + insert: "std", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_std_prelude_if_core_is_defined() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + fn foo() { let x: <|> } + + //- /core/lib.rs + #[prelude_import] + use prelude::*; + + mod prelude { + struct Option; + } + + //- /std/lib.rs + #[prelude_import] + use prelude::*; + + mod prelude { + struct String; + } + " + ), + @r###" + [ + CompletionItem { + label: "String", + source_range: [18; 18), + delete: [18; 18), + insert: "String", + kind: Struct, + }, + CompletionItem { + label: "core", + source_range: [18; 18), + delete: [18; 18), + insert: "core", + kind: Module, + }, + CompletionItem { + label: "foo()", + source_range: [18; 18), + delete: [18; 18), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + CompletionItem { + label: "std", + source_range: [18; 18), + delete: [18; 18), + insert: "std", + kind: Module, + }, + ] + "### + ); + } + + #[test] + fn completes_macros_as_value() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + macro_rules! foo { + () => {} + } + + #[macro_use] + mod m1 { + macro_rules! bar { + () => {} + } + } + + mod m2 { + macro_rules! nope { + () => {} + } + + #[macro_export] + macro_rules! baz { + () => {} + } + } + + fn main() { + let v = <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "bar!", + source_range: [252; 252), + delete: [252; 252), + insert: "bar!($0)", + kind: Macro, + detail: "macro_rules! bar", + }, + CompletionItem { + label: "baz!", + source_range: [252; 252), + delete: [252; 252), + insert: "baz!($0)", + kind: Macro, + detail: "#[macro_export]\nmacro_rules! baz", + }, + CompletionItem { + label: "foo!", + source_range: [252; 252), + delete: [252; 252), + insert: "foo!($0)", + kind: Macro, + detail: "macro_rules! foo", + }, + CompletionItem { + label: "m1", + source_range: [252; 252), + delete: [252; 252), + insert: "m1", + kind: Module, + }, + CompletionItem { + label: "m2", + source_range: [252; 252), + delete: [252; 252), + insert: "m2", + kind: Module, + }, + CompletionItem { + label: "main()", + source_range: [252; 252), + delete: [252; 252), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); + } + + #[test] + fn completes_both_macro_and_value() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + macro_rules! foo { + () => {} + } + + fn foo() { + <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [49; 49), + delete: [49; 49), + insert: "foo!($0)", + kind: Macro, + detail: "macro_rules! foo", + }, + CompletionItem { + label: "foo()", + source_range: [49; 49), + delete: [49; 49), + insert: "foo()$0", + kind: Function, + lookup: "foo", + detail: "fn foo()", + }, + ] + "### + ); + } + + #[test] + fn completes_macros_as_type() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + macro_rules! foo { + () => {} + } + + fn main() { + let x: <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [57; 57), + delete: [57; 57), + insert: "foo!($0)", + kind: Macro, + detail: "macro_rules! foo", + }, + CompletionItem { + label: "main()", + source_range: [57; 57), + delete: [57; 57), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); + } + + #[test] + fn completes_macros_as_stmt() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + macro_rules! foo { + () => {} + } + + fn main() { + <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [50; 50), + delete: [50; 50), + insert: "foo!($0)", + kind: Macro, + detail: "macro_rules! foo", + }, + CompletionItem { + label: "main()", + source_range: [50; 50), + delete: [50; 50), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); + } + + #[test] + fn completes_local_item() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + fn main() { + return f<|>; + fn frobnicate() {} + } + " + ), + @r###" + [ + CompletionItem { + label: "frobnicate()", + source_range: [23; 24), + delete: [23; 24), + insert: "frobnicate()$0", + kind: Function, + lookup: "frobnicate", + detail: "fn frobnicate()", + }, + CompletionItem { + label: "main()", + source_range: [23; 24), + delete: [23; 24), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ) + } + + #[test] + fn completes_in_simple_macro_1() { + assert_debug_snapshot!( + do_reference_completion( + r" + macro_rules! m { ($e:expr) => { $e } } + fn quux(x: i32) { + let y = 92; + m!(<|>); + } + " + ), + @r###" + [ + CompletionItem { + label: "m!", + source_range: [145; 145), + delete: [145; 145), + insert: "m!($0)", + kind: Macro, + detail: "macro_rules! m", + }, + CompletionItem { + label: "quux(…)", + source_range: [145; 145), + delete: [145; 145), + insert: "quux(${1:x})$0", + kind: Function, + lookup: "quux", + detail: "fn quux(x: i32)", + trigger_call_info: true, + }, + CompletionItem { + label: "x", + source_range: [145; 145), + delete: [145; 145), + insert: "x", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "y", + source_range: [145; 145), + delete: [145; 145), + insert: "y", + kind: Binding, + detail: "i32", + }, + ] + "### + ); + } + + #[test] + fn completes_in_simple_macro_2() { + assert_debug_snapshot!( + do_reference_completion( + r" + macro_rules! m { ($e:expr) => { $e } } + fn quux(x: i32) { + let y = 92; + m!(x<|>); + } + " + ), + @r###" + [ + CompletionItem { + label: "m!", + source_range: [145; 146), + delete: [145; 146), + insert: "m!($0)", + kind: Macro, + detail: "macro_rules! m", + }, + CompletionItem { + label: "quux(…)", + source_range: [145; 146), + delete: [145; 146), + insert: "quux(${1:x})$0", + kind: Function, + lookup: "quux", + detail: "fn quux(x: i32)", + trigger_call_info: true, + }, + CompletionItem { + label: "x", + source_range: [145; 146), + delete: [145; 146), + insert: "x", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "y", + source_range: [145; 146), + delete: [145; 146), + insert: "y", + kind: Binding, + detail: "i32", + }, + ] + "### + ); + } + + #[test] + fn completes_in_simple_macro_without_closing_parens() { + assert_debug_snapshot!( + do_reference_completion( + r" + macro_rules! m { ($e:expr) => { $e } } + fn quux(x: i32) { + let y = 92; + m!(x<|> + } + " + ), + @r###" + [ + CompletionItem { + label: "m!", + source_range: [145; 146), + delete: [145; 146), + insert: "m!($0)", + kind: Macro, + detail: "macro_rules! m", + }, + CompletionItem { + label: "quux(…)", + source_range: [145; 146), + delete: [145; 146), + insert: "quux(${1:x})$0", + kind: Function, + lookup: "quux", + detail: "fn quux(x: i32)", + trigger_call_info: true, + }, + CompletionItem { + label: "x", + source_range: [145; 146), + delete: [145; 146), + insert: "x", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "y", + source_range: [145; 146), + delete: [145; 146), + insert: "y", + kind: Binding, + detail: "i32", + }, + ] + "### + ); + } + + #[test] + fn completes_unresolved_uses() { + assert_debug_snapshot!( + do_reference_completion( + r" + use spam::Quux; + + fn main() { + <|> + } + " + ), + @r###" + [ + CompletionItem { + label: "Quux", + source_range: [82; 82), + delete: [82; 82), + insert: "Quux", + }, + CompletionItem { + label: "main()", + source_range: [82; 82), + delete: [82; 82), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); + } +} -- cgit v1.2.3 From 021556043425d7b11800532bc06e5d49514c1347 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Apr 2020 13:20:41 +0200 Subject: Better naming for scope completion --- crates/ra_ide/src/completion.rs | 4 ++-- crates/ra_ide/src/completion/complete_qualified_path.rs | 2 +- crates/ra_ide/src/completion/complete_unqualified_path.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index c9ba1d4ee..4a1a2a04a 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -85,8 +85,8 @@ pub(crate) fn completions( complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); complete_snippet::complete_expr_snippet(&mut acc, &ctx); complete_snippet::complete_item_snippet(&mut acc, &ctx); - complete_qualified_path::complete_path(&mut acc, &ctx); - complete_unqualified_path::complete_scope(&mut acc, &ctx); + complete_qualified_path::complete_qualified_path(&mut acc, &ctx); + complete_unqualified_path::complete_unqualified_path(&mut acc, &ctx); complete_dot::complete_dot(&mut acc, &ctx); complete_record::complete_record(&mut acc, &ctx); complete_pattern::complete_pattern(&mut acc, &ctx); diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs index 3ed2ae2b6..d98523406 100644 --- a/crates/ra_ide/src/completion/complete_qualified_path.rs +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs @@ -6,7 +6,7 @@ use test_utils::tested_by; use crate::completion::{CompletionContext, Completions}; -pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { +pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { let path = match &ctx.path_prefix { Some(path) => path.clone(), _ => return, diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs index 665597e4c..efde9bf73 100644 --- a/crates/ra_ide/src/completion/complete_unqualified_path.rs +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs @@ -2,7 +2,7 @@ use crate::completion::{CompletionContext, Completions}; -pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { +pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) { return; } -- cgit v1.2.3 From 8c378af72117e92bc894fd4a79e978ef0d1c0cc7 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 24 Mar 2020 04:40:58 -0700 Subject: missing match arms diagnostic --- crates/ra_ide/src/diagnostics.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index c1d7ddaf2..901ad104c 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -101,6 +101,14 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec fix, }) }) + .on::(|d| { + res.borrow_mut().push(Diagnostic { + range: d.highlight_range(), + message: d.message(), + severity: Severity::Error, + fix: None, + }) + }) .on::(|d| { let node = d.ast(db); let replacement = format!("Ok({})", node.syntax()); @@ -291,7 +299,7 @@ mod tests { fn check_no_diagnostic(content: &str) { let (analysis, file_id) = single_file(content); let diagnostics = analysis.diagnostics(file_id).unwrap(); - assert_eq!(diagnostics.len(), 0); + assert_eq!(diagnostics.len(), 0, "expected no diagnostic, found one"); } #[test] -- cgit v1.2.3 From 73ccf7f495f328e10dca38e0f069de89ab52b9d3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Apr 2020 15:07:18 +0200 Subject: Reorder imports --- crates/ra_ide/src/completion/complete_record.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs index 01dd8c6db..780a98aea 100644 --- a/crates/ra_ide/src/completion/complete_record.rs +++ b/crates/ra_ide/src/completion/complete_record.rs @@ -1,7 +1,8 @@ //! Complete fields in record literals and patterns. -use crate::completion::{CompletionContext, Completions}; use ra_syntax::{ast, ast::NameOwner, SmolStr}; +use crate::completion::{CompletionContext, Completions}; + pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { let (ty, variant, already_present_fields) = match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) { @@ -59,9 +60,10 @@ fn pattern_ascribed_fields(record_pat: &ast::RecordPat) -> Vec { #[cfg(test)] mod tests { mod record_lit_tests { - use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; use insta::assert_debug_snapshot; + use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; + fn complete(code: &str) -> Vec { do_completion(code, CompletionKind::Reference) } @@ -204,9 +206,10 @@ mod tests { } mod record_pat_tests { - use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; use insta::assert_debug_snapshot; + use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; + fn complete(code: &str) -> Vec { do_completion(code, CompletionKind::Reference) } -- cgit v1.2.3 From 5540193fc87a33a6c141956a63f9f56fe6207ee8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Apr 2020 16:37:33 +0200 Subject: Don't insert !() if there's already some --- crates/ra_ide/src/completion/completion_context.rs | 4 ++ crates/ra_ide/src/completion/presentation.rs | 43 ++++++++++++++++++++-- crates/ra_ide/src/marks.rs | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index b8213d62f..f833d2a9a 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -50,6 +50,8 @@ pub(crate) struct CompletionContext<'a> { pub(super) dot_receiver_is_ambiguous_float_literal: bool, /// If this is a call (method or function) in particular, i.e. the () are already there. pub(super) is_call: bool, + /// If this is a macro call, i.e. the () are already there. + pub(super) is_macro_call: bool, pub(super) is_path_type: bool, pub(super) has_type_args: bool, } @@ -102,6 +104,7 @@ impl<'a> CompletionContext<'a> { is_new_item: false, dot_receiver: None, is_call: false, + is_macro_call: false, is_path_type: false, has_type_args: false, dot_receiver_is_ambiguous_float_literal: false, @@ -269,6 +272,7 @@ impl<'a> CompletionContext<'a> { .and_then(ast::PathExpr::cast) .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) .is_some(); + self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); self.has_type_args = segment.type_arg_list().is_some(); diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index cdfd7bc32..55f75b15a 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -174,7 +174,8 @@ impl Completions { .set_deprecated(is_deprecated(macro_, ctx.db)) .detail(detail); - builder = if ctx.use_item_syntax.is_some() { + builder = if ctx.use_item_syntax.is_some() || ctx.is_macro_call { + tested_by!(dont_insert_macro_call_parens_unncessary); builder.insert_text(name) } else { let macro_braces_to_insert = @@ -960,7 +961,8 @@ mod tests { } #[test] - fn dont_insert_macro_call_braces_in_use() { + fn dont_insert_macro_call_parens_unncessary() { + covers!(dont_insert_macro_call_parens_unncessary); assert_debug_snapshot!( do_reference_completion( r" @@ -986,6 +988,41 @@ mod tests { }, ] "### - ) + ); + + assert_debug_snapshot!( + do_reference_completion( + r" + //- /main.rs + macro_rules frobnicate { + () => () + } + fn main() { + frob<|>!(); + } + " + ), + @r###" + [ + CompletionItem { + label: "frobnicate!", + source_range: [56; 60), + delete: [56; 60), + insert: "frobnicate", + kind: Macro, + detail: "macro_rules! frobnicate", + }, + CompletionItem { + label: "main()", + source_range: [56; 60), + delete: [56; 60), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ); } } diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs index 1236cb773..5e1f135c5 100644 --- a/crates/ra_ide/src/marks.rs +++ b/crates/ra_ide/src/marks.rs @@ -7,4 +7,5 @@ test_utils::marks!( dont_complete_current_use test_resolve_parent_module_on_module_decl search_filters_by_range + dont_insert_macro_call_parens_unncessary ); -- cgit v1.2.3 From 3bde2b742388f3ec3bb08841f93a06a62be04e4d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Apr 2020 16:40:39 +0200 Subject: A more precise panic macro --- crates/ra_ide/src/completion/complete_record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs index 780a98aea..79f5c8c8f 100644 --- a/crates/ra_ide/src/completion/complete_record.rs +++ b/crates/ra_ide/src/completion/complete_record.rs @@ -7,7 +7,7 @@ pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> let (ty, variant, already_present_fields) = match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) { (None, None) => return None, - (Some(_), Some(_)) => panic!("A record cannot be both a literal and a pattern"), + (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"), (Some(record_pat), _) => ( ctx.sema.type_of_pat(&record_pat.clone().into())?, ctx.sema.resolve_record_pattern(record_pat)?, -- cgit v1.2.3