From e14f5cfff04942f45a4af3b45152df9672b3458a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Jun 2021 13:13:12 +0200 Subject: [PATCH 1/3] Move out and rewrite UseTree completion tests --- .../ide_completion/src/completions/keyword.rs | 35 --- .../src/completions/qualified_path.rs | 157 ----------- .../src/completions/unqualified_path.rs | 32 --- crates/ide_completion/src/tests.rs | 1 + crates/ide_completion/src/tests/use_tree.rs | 261 ++++++++++++++++++ 5 files changed, 262 insertions(+), 224 deletions(-) create mode 100644 crates/ide_completion/src/tests/use_tree.rs diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 73bbc43458e..b6f06a44fb6 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs @@ -199,41 +199,6 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } - #[test] - fn test_keywords_in_use_stmt() { - check( - r"use $0", - expect![[r#" - kw crate:: - kw self - kw super:: - "#]], - ); - - // FIXME: `self` shouldn't be shown here and the check below - check( - r"use a::$0", - expect![[r#" - kw self - "#]], - ); - - check( - r"use super::$0", - expect![[r#" - kw self - kw super:: - "#]], - ); - - check( - r"use a::{b, $0}", - expect![[r#" - kw self - "#]], - ); - } - #[test] fn test_keywords_in_function() { check( diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 9432caa22e4..5b49868e4e0 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -212,12 +212,6 @@ fn check_builtin(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual); } - #[test] - fn dont_complete_current_use() { - cov_mark::check!(dont_complete_current_use); - check(r#"use self::foo$0;"#, expect![[""]]); - } - #[test] fn dont_complete_values_in_type_pos() { check( @@ -248,20 +242,6 @@ fn foo() { ); } - #[test] - fn dont_complete_current_use_in_braces_with_glob() { - check( - r#" -mod foo { pub struct S; } -use self::{foo::*, bar$0}; -"#, - expect![[r#" - st S - md foo - "#]], - ); - } - #[test] fn dont_complete_primitive_in_use() { check_builtin(r#"use self::$0;"#, expect![[""]]); @@ -298,108 +278,6 @@ fn completes_primitives() { ); } - #[test] - fn completes_mod_with_same_name_as_function() { - check( - r#" -use self::my::$0; - -mod my { pub struct Bar; } -fn my() {} -"#, - expect![[r#" - st Bar - "#]], - ); - } - - #[test] - fn filters_visibility() { - check( - r#" -use self::my::$0; - -mod my { - struct Bar; - pub struct Foo; - pub use Bar as PublicBar; -} -"#, - expect![[r#" - st Foo - st PublicBar - "#]], - ); - } - - #[test] - fn completes_use_item_starting_with_self() { - check( - r#" -use self::m::$0; - -mod m { pub struct Bar; } -"#, - expect![[r#" - st Bar - "#]], - ); - } - - #[test] - fn completes_use_item_starting_with_crate() { - check( - r#" -//- /lib.rs -mod foo; -struct Spam; -//- /foo.rs -use crate::Sp$0 -"#, - expect![[r#" - md foo - st Spam - "#]], - ); - } - - #[test] - fn completes_nested_use_tree() { - check( - r#" -//- /lib.rs -mod foo; -struct Spam; -//- /foo.rs -use crate::{Sp$0}; -"#, - expect![[r#" - md foo - st Spam - "#]], - ); - } - - #[test] - fn completes_deeply_nested_use_tree() { - check( - r#" -//- /lib.rs -mod foo; -pub mod bar { - pub mod baz { - pub struct Spam; - } -} -//- /foo.rs -use crate::{bar::{baz::Sp$0}}; -"#, - expect![[r#" - st Spam - "#]], - ); - } - #[test] fn completes_enum_variant() { check( @@ -496,22 +374,6 @@ fn m() fn() ); } - #[test] - fn completes_use_paths_across_crates() { - check( - r#" -//- /main.rs crate:main deps:foo -use foo::$0; - -//- /foo/lib.rs crate:foo -pub mod bar { pub struct S; } -"#, - expect![[r#" - md bar - "#]], - ); - } - #[test] fn completes_trait_associated_method_1() { check( @@ -713,25 +575,6 @@ impl MyStruct { ); } - #[test] - fn test_super_super_completion() { - check( - r#" -mod a { - const A: usize = 0; - mod b { - const B: usize = 0; - mod c { use super::super::$0 } - } -} -"#, - expect![[r#" - md b - ct A - "#]], - ); - } - #[test] fn completes_reexported_items_under_correct_name() { check( diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 2868d9b1813..83b9148b31d 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -129,22 +129,6 @@ fn foo() { ); } - #[test] - fn only_completes_modules_in_import() { - cov_mark::check!(only_completes_modules_in_import); - check( - r#" -use f$0 - -struct Foo; -mod foo {} -"#, - expect![[r#" - md foo - "#]], - ); - } - #[test] fn bind_pat_and_path_ignore_at() { check( @@ -358,22 +342,6 @@ fn _alpha() {} ) } - #[test] - fn completes_extern_prelude() { - check( - r#" -//- /lib.rs crate:main deps:other_crate -use $0; - -//- /other_crate/lib.rs crate:other_crate -// nothing here -"#, - expect![[r#" - md other_crate - "#]], - ); - } - #[test] fn completes_module_items_in_nested_modules() { check( diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs index 1495924ea36..89c7fb524ec 100644 --- a/crates/ide_completion/src/tests.rs +++ b/crates/ide_completion/src/tests.rs @@ -1,4 +1,5 @@ mod item_list; +mod use_tree; use hir::{PrefixKind, Semantics}; use ide_db::{ diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs new file mode 100644 index 00000000000..156ca244dc6 --- /dev/null +++ b/crates/ide_completion/src/tests/use_tree.rs @@ -0,0 +1,261 @@ +use expect_test::{expect, Expect}; + +use crate::tests::completion_list; + +fn check(ra_fixture: &str, expect: Expect) { + let actual = completion_list(ra_fixture); + expect.assert_eq(&actual) +} + +#[test] +fn use_tree_start() { + cov_mark::check!(only_completes_modules_in_import); + check( + r#" +//- /lib.rs crate:main deps:other_crate +use f$0 + +struct Foo; +mod foo {} +//- /other_crate/lib.rs crate:other_crate +// nothing here +"#, + // FIXME: self in this case should also get the colons + expect![[r#" + kw crate:: + kw self + kw super:: + md foo + md other_crate + "#]], + ); +} + +#[test] +fn dont_complete_current_use() { + cov_mark::check!(dont_complete_current_use); + // FIXME: self shouldn't be here + check( + r#"use self::foo$0;"#, + expect![[r#" + kw self + "#]], + ); + check( + r#" +mod foo { pub struct S; } +use self::{foo::*, bar$0}; +"#, + expect![[r#" + kw self + st S + md foo + "#]], + ); +} + +#[test] +fn nested_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +mod foo { + pub mod bar { + pub struct FooBar; + } +} +use foo::{bar::$0} +"#, + expect![[r#" + kw self + st FooBar + "#]], + ); + check( + r#" +mod foo { + pub mod bar { + pub struct FooBar; + } +} +use foo::{$0} +"#, + expect![[r#" + kw self + md bar + "#]], + ); +} + +#[test] +fn deeply_nested_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +mod foo { + pub mod bar { + pub mod baz { + pub struct FooBarBaz; + } + } +} +use foo::{bar::{baz::$0}} +"#, + expect![[r#" + kw self + st FooBarBaz + "#]], + ); + check( + r#" +mod foo { + pub mod bar { + pub mod baz { + pub struct FooBarBaz; + } + } +} +use foo::{bar::{$0}} +"#, + expect![[r#" + kw self + md baz + "#]], + ); +} + +#[test] +fn plain_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +use foo::$0 + +mod foo { + struct Private; + pub struct Foo; +} +struct Bar; +"#, + expect![[r#" + kw self + st Foo + "#]], + ); +} + +#[test] +fn self_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +use self::$0 + +mod foo {} +struct Bar; +"#, + expect![[r#" + kw self + md foo + st Bar + "#]], + ); +} + +#[test] +fn super_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +mod bar { + use super::$0 +} + +mod foo {} +struct Bar; +"#, + expect![[r#" + kw self + kw super:: + st Bar + md bar + md foo + "#]], + ); +} + +#[test] +fn super_super_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +mod a { + const A: usize = 0; + mod b { + const B: usize = 0; + mod c { use super::super::$0 } + } +} +"#, + expect![[r#" + kw self + kw super:: + md b + ct A + "#]], + ); +} + +#[test] +fn crate_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +use crate::$0 + +mod foo {} +struct Bar; +"#, + expect![[r#" + kw self + md foo + st Bar + "#]], + ); +} + +#[test] +fn extern_crate_qualified_use_tree() { + // FIXME: self shouldn't be here + check( + r#" +//- /lib.rs crate:main deps:other_crate +use other_crate::$0 +//- /other_crate/lib.rs crate:other_crate +pub struct Foo; +pub mod foo {} +"#, + expect![[r#" + kw self + st Foo + md foo + "#]], + ); +} + +#[test] +fn pub_use_tree() { + check( + r#" +pub struct X; +pub mod bar {} +pub use $0; +"#, + expect![[r#" + kw crate:: + kw self + kw super:: + md bar + "#]], + ); +} From 2225db2eb48bd8c8fdf399c50652d3f95c851ace Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Jun 2021 13:56:55 +0200 Subject: [PATCH 2/3] Refine `self`, `super` and `crate` completion in use paths --- .../src/completions/flyimport.rs | 2 +- .../ide_completion/src/completions/keyword.rs | 29 ++++++++++++------- .../src/completions/qualified_path.rs | 2 +- .../src/completions/unqualified_path.rs | 2 +- crates/ide_completion/src/context.rs | 26 ++++++++++------- crates/ide_completion/src/patterns.rs | 7 +++-- .../ide_completion/src/render/builder_ext.rs | 2 +- crates/ide_completion/src/render/macro_.rs | 2 +- crates/ide_completion/src/tests/use_tree.rs | 29 ++----------------- 9 files changed, 47 insertions(+), 54 deletions(-) diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 4604feb5dc7..814c1565362 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs @@ -109,7 +109,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) if !ctx.config.enable_imports_on_the_fly { return None; } - if ctx.use_item_syntax.is_some() + if ctx.in_use_tree() || ctx.is_path_disallowed() || ctx.expects_item() || ctx.expects_assoc_item() diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index b6f06a44fb6..9754122a0e4 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs @@ -18,17 +18,24 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC item }; - if ctx.use_item_syntax.is_some() { - let qual = ctx.path_qual(); - if qual.is_none() { - kw_completion("crate::").add_to(acc); - } - kw_completion("self").add_to(acc); - if iter::successors(qual.cloned(), |p| p.qualifier()) - .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) - { - kw_completion("super::").add_to(acc); - } + if ctx.in_use_tree() { + match &ctx.path_context { + Some(PathCompletionContext { qualifier: Some(qual), use_tree_parent, .. }) => { + if iter::successors(Some(qual.clone()), |p| p.qualifier()) + .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) + { + kw_completion("super::").add_to(acc); + } + if *use_tree_parent { + kw_completion("self").add_to(acc); + } + } + _ => { + kw_completion("crate::").add_to(acc); + kw_completion("self::").add_to(acc); + kw_completion("super::").add_to(acc); + } + }; } // Suggest .await syntax for types that implement Future trait diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 5b49868e4e0..0597879ac61 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -49,7 +49,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon hir::PathResolution::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 ctx.in_use_tree() { if let hir::ScopeDef::Unknown = def { if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { if name_ref.syntax().text() == name.to_string().as_str() { diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 83b9148b31d..4bafc1bf8e1 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -25,7 +25,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC return; } - if ctx.expects_use_tree() { + if ctx.expects_new_use_tree() { // only show modules in a fresh UseTree cov_mark::hit!(only_completes_modules_in_import); ctx.scope.process_all_names(&mut |name, res| { diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 121909857bd..c3076f608d6 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -43,6 +43,8 @@ pub(crate) struct PathCompletionContext { pub(super) is_trivial_path: bool, /// If not a trivial path, the prefix (qualifier). pub(super) qualifier: Option, + /// Whether the qualifier comes from a use tree parent or not + pub(super) use_tree_parent: bool, pub(super) kind: Option, /// Whether the path segment has type args or not. pub(super) has_type_args: bool, @@ -79,7 +81,6 @@ pub(crate) struct CompletionContext<'a> { /// The parent impl of the cursor position if it exists. pub(super) impl_def: Option, pub(super) name_ref_syntax: Option, - pub(super) use_item_syntax: Option, // potentially set if we are completing a lifetime pub(super) lifetime_syntax: Option, @@ -151,7 +152,6 @@ pub(super) fn new( function_def: None, impl_def: None, name_ref_syntax: None, - use_item_syntax: None, lifetime_syntax: None, lifetime_param_syntax: None, lifetime_allowed: false, @@ -264,7 +264,7 @@ pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { } } - pub(crate) fn expects_use_tree(&self) -> bool { + pub(crate) fn expects_new_use_tree(&self) -> bool { matches!(self.completion_location, Some(ImmediateLocation::Use)) } @@ -295,6 +295,13 @@ pub(crate) fn expect_record_field(&self) -> bool { matches!(self.completion_location, Some(ImmediateLocation::RecordField)) } + pub(crate) fn in_use_tree(&self) -> bool { + matches!( + self.completion_location, + Some(ImmediateLocation::Use) | Some(ImmediateLocation::UseTree) + ) + } + pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool { matches!( self.prev_sibling, @@ -578,9 +585,6 @@ fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameR self.name_ref_syntax = find_node_at_offset(original_file, name_ref.syntax().text_range().start()); - self.use_item_syntax = - self.sema.token_ancestors_with_macros(self.token.clone()).find_map(ast::Use::cast); - self.function_def = self .sema .token_ancestors_with_macros(self.token.clone()) @@ -600,6 +604,7 @@ fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameR has_type_args: false, can_be_stmt: false, in_loop_body: false, + use_tree_parent: false, kind: None, }); path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax()); @@ -627,7 +632,8 @@ fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameR } path_ctx.has_type_args = segment.generic_arg_list().is_some(); - if let Some(path) = path_or_use_tree_qualifier(&path) { + if let Some((path, use_tree_parent)) = path_or_use_tree_qualifier(&path) { + path_ctx.use_tree_parent = use_tree_parent; path_ctx.qualifier = path .segment() .and_then(|it| { @@ -681,13 +687,13 @@ fn is_node(node: &SyntaxNode) -> bool { } } -fn path_or_use_tree_qualifier(path: &ast::Path) -> Option { +fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> { if let Some(qual) = path.qualifier() { - return Some(qual); + return Some((qual, false)); } let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?; let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast)?; - use_tree.path() + use_tree.path().zip(Some(true)) } #[cfg(test)] diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 62e4334decd..271409c38ad 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs @@ -27,6 +27,7 @@ pub(crate) enum ImmediatePrevSibling { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum ImmediateLocation { Use, + UseTree, Impl, Trait, RecordField, @@ -180,6 +181,8 @@ pub(crate) fn determine_location( match parent { ast::IdentPat(_it) => ImmediateLocation::IdentPat, ast::Use(_it) => ImmediateLocation::Use, + ast::UseTree(_it) => ImmediateLocation::UseTree, + ast::UseTreeList(_it) => ImmediateLocation::UseTree, ast::BlockExpr(_it) => ImmediateLocation::BlockExpr, ast::SourceFile(_it) => ImmediateLocation::ItemList, ast::ItemList(_it) => ImmediateLocation::ItemList, @@ -373,8 +376,8 @@ fn test_impl_loc() { fn test_use_loc() { check_location(r"use f$0", ImmediateLocation::Use); check_location(r"use f$0;", ImmediateLocation::Use); - check_location(r"use f::{f$0}", None); - check_location(r"use {f$0}", None); + check_location(r"use f::{f$0}", ImmediateLocation::UseTree); + check_location(r"use {f$0}", ImmediateLocation::UseTree); } #[test] diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs index c54752d30b4..749dfc665a0 100644 --- a/crates/ide_completion/src/render/builder_ext.rs +++ b/crates/ide_completion/src/render/builder_ext.rs @@ -28,7 +28,7 @@ fn should_add_parens(&self, ctx: &CompletionContext) -> bool { if !ctx.config.add_call_parenthesis { return false; } - if ctx.use_item_syntax.is_some() { + if ctx.in_use_tree() { cov_mark::hit!(no_parens_in_use_item); return false; } diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs index d5a1f45d3e6..4d5179c4f95 100644 --- a/crates/ide_completion/src/render/macro_.rs +++ b/crates/ide_completion/src/render/macro_.rs @@ -69,7 +69,7 @@ fn render(&self, import_to_add: Option) -> Option { } fn needs_bang(&self) -> bool { - self.ctx.completion.use_item_syntax.is_none() + !self.ctx.completion.in_use_tree() && !matches!(self.ctx.completion.path_call_kind(), Some(CallKind::Mac)) } diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs index 156ca244dc6..878bc42bf52 100644 --- a/crates/ide_completion/src/tests/use_tree.rs +++ b/crates/ide_completion/src/tests/use_tree.rs @@ -20,10 +20,9 @@ mod foo {} //- /other_crate/lib.rs crate:other_crate // nothing here "#, - // FIXME: self in this case should also get the colons expect![[r#" kw crate:: - kw self + kw self:: kw super:: md foo md other_crate @@ -34,13 +33,7 @@ mod foo {} #[test] fn dont_complete_current_use() { cov_mark::check!(dont_complete_current_use); - // FIXME: self shouldn't be here - check( - r#"use self::foo$0;"#, - expect![[r#" - kw self - "#]], - ); + check(r#"use self::foo$0;"#, expect![[r#""#]]); check( r#" mod foo { pub struct S; } @@ -56,7 +49,6 @@ fn dont_complete_current_use() { #[test] fn nested_use_tree() { - // FIXME: self shouldn't be here check( r#" mod foo { @@ -67,7 +59,6 @@ pub mod bar { use foo::{bar::$0} "#, expect![[r#" - kw self st FooBar "#]], ); @@ -89,7 +80,6 @@ pub mod bar { #[test] fn deeply_nested_use_tree() { - // FIXME: self shouldn't be here check( r#" mod foo { @@ -102,7 +92,6 @@ pub mod baz { use foo::{bar::{baz::$0}} "#, expect![[r#" - kw self st FooBarBaz "#]], ); @@ -126,7 +115,6 @@ pub mod baz { #[test] fn plain_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" use foo::$0 @@ -138,7 +126,6 @@ mod foo { struct Bar; "#, expect![[r#" - kw self st Foo "#]], ); @@ -146,7 +133,6 @@ mod foo { #[test] fn self_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" use self::$0 @@ -155,7 +141,6 @@ mod foo {} struct Bar; "#, expect![[r#" - kw self md foo st Bar "#]], @@ -164,7 +149,6 @@ mod foo {} #[test] fn super_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" mod bar { @@ -175,7 +159,6 @@ mod foo {} struct Bar; "#, expect![[r#" - kw self kw super:: st Bar md bar @@ -186,7 +169,6 @@ mod foo {} #[test] fn super_super_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" mod a { @@ -198,7 +180,6 @@ mod c { use super::super::$0 } } "#, expect![[r#" - kw self kw super:: md b ct A @@ -208,7 +189,6 @@ mod c { use super::super::$0 } #[test] fn crate_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" use crate::$0 @@ -217,7 +197,6 @@ mod foo {} struct Bar; "#, expect![[r#" - kw self md foo st Bar "#]], @@ -226,7 +205,6 @@ mod foo {} #[test] fn extern_crate_qualified_use_tree() { - // FIXME: self shouldn't be here check( r#" //- /lib.rs crate:main deps:other_crate @@ -236,7 +214,6 @@ fn extern_crate_qualified_use_tree() { pub mod foo {} "#, expect![[r#" - kw self st Foo md foo "#]], @@ -253,7 +230,7 @@ pub mod bar {} "#, expect![[r#" kw crate:: - kw self + kw self:: kw super:: md bar "#]], From 9353f36516e5b4026ce3a181d578c3a63876a18f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Jun 2021 13:59:31 +0200 Subject: [PATCH 3/3] Fix incorrect completions in empty braced use statement --- .../src/completions/unqualified_path.rs | 2 +- crates/ide_completion/src/context.rs | 4 ---- crates/ide_completion/src/tests/use_tree.rs | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 4bafc1bf8e1..6f96eceb9c1 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -25,7 +25,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC return; } - if ctx.expects_new_use_tree() { + if ctx.in_use_tree() { // only show modules in a fresh UseTree cov_mark::hit!(only_completes_modules_in_import); ctx.scope.process_all_names(&mut |name, res| { diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index c3076f608d6..240cac1de09 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -264,10 +264,6 @@ pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { } } - pub(crate) fn expects_new_use_tree(&self) -> bool { - matches!(self.completion_location, Some(ImmediateLocation::Use)) - } - pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { matches!(self.completion_location, Some(ImmediateLocation::Impl)) } diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs index 878bc42bf52..7e6748cccd2 100644 --- a/crates/ide_completion/src/tests/use_tree.rs +++ b/crates/ide_completion/src/tests/use_tree.rs @@ -236,3 +236,20 @@ pub mod bar {} "#]], ); } + +#[test] +fn use_tree_braces_at_start() { + check( + r#" +struct X; +mod bar {} +use {$0}; +"#, + expect![[r#" + kw crate:: + kw self:: + kw super:: + md bar + "#]], + ); +}