From 722489e3ff4c16dc179d30e729847314c918511f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 27 Oct 2021 16:24:42 +0200 Subject: [PATCH] Remove filtered completion list usage in completion tests --- crates/ide_completion/src/completions/dot.rs | 371 +++++- .../src/completions/flyimport.rs | 1015 ----------------- .../ide_completion/src/completions/keyword.rs | 295 +---- crates/ide_completion/src/completions/mod_.rs | 3 +- .../ide_completion/src/completions/postfix.rs | 6 +- .../src/completions/qualified_path.rs | 7 +- .../src/completions/trait_impl.rs | 79 +- .../src/completions/unqualified_path.rs | 17 +- crates/ide_completion/src/context.rs | 1 - crates/ide_completion/src/tests.rs | 63 +- crates/ide_completion/src/tests/expression.rs | 219 +++- crates/ide_completion/src/tests/flyimport.rs | 1014 ++++++++++++++++ crates/ide_completion/src/tests/record.rs | 1 + crates/rust-analyzer/tests/slow-tests/tidy.rs | 1 + 14 files changed, 1746 insertions(+), 1346 deletions(-) create mode 100644 crates/ide_completion/src/tests/flyimport.rs diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 213cb70170..9649667bd7 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs @@ -99,13 +99,10 @@ fn complete_methods( mod tests { use expect_test::{expect, Expect}; - use crate::{ - tests::{check_edit, filtered_completion_list}, - CompletionKind, - }; + use crate::tests::{check_edit, completion_list_no_kw}; fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); + let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual); } @@ -122,6 +119,18 @@ fn foo(s: S) { s.$0 } expect![[r#" fd foo u32 me bar() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -138,6 +147,18 @@ impl S { expect![[r#" fd the_field (u32,) me foo() fn(self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } @@ -154,6 +175,18 @@ impl A { expect![[r#" fd the_field (u32, i32) me foo() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } @@ -166,7 +199,18 @@ impl A { struct A { the_field: u32 } fn foo(a: A) { a.$0() } "#, - expect![[""]], + expect![[r#" + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + "#]], ); } @@ -191,6 +235,18 @@ fn foo(a: lib::m::A) { a.$0 } fd pub_field u32 fd crate_field u32 fd super_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); @@ -210,6 +266,18 @@ fn foo(a: lib::m::A) { a.$0 } "#, expect![[r#" fd pub_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); @@ -226,7 +294,19 @@ pub mod m { fn foo(a: lib::m::A) { a.$0 } "#, expect![[r#" - fd 1 f64 + fd 1 f64 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); @@ -248,6 +328,18 @@ fn foo(a: lib::A) { a.$0 } me private_method() fn(&self) me crate_method() fn(&self) me pub_method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); check( @@ -266,6 +358,18 @@ fn foo(a: lib::A) { a.$0 } "#, expect![[r#" me pub_method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -293,6 +397,18 @@ impl A { expect![[r#" fd pub_field u32 me pub_method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } @@ -307,6 +423,18 @@ fn foo(u: U) { u.$0 } expect![[r#" fd field u8 fd other u16 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -326,6 +454,18 @@ fn foo(a: A) { a.$0 } "#, expect![[r#" me the_method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } @@ -341,6 +481,18 @@ fn foo(a: A) { a.$0 } "#, expect![[r#" me the_method() (as Trait) fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); check_edit( @@ -371,6 +523,18 @@ fn foo(a: &A) { a.$0 } ", expect![[r#" me the_method() (as Trait) fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -389,6 +553,18 @@ fn foo(a: A) { a.$0 } ", expect![[r#" me the_method() (as Trait) fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -405,7 +581,20 @@ fn foo(a: A) { a.$0 } "#, - expect![[""]], + expect![[r#" + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut + "#]], ); } @@ -419,8 +608,20 @@ fn foo() { } "#, expect![[r#" - fd 0 i32 - fd 1 f64 + fd 0 i32 + fd 1 f64 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -436,8 +637,20 @@ fn foo() { } "#, expect![[r#" - fd 0 i32 - fd 1 f64 + fd 0 i32 + fd 1 f64 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -460,6 +673,18 @@ impl T { "#, expect![[r#" me blah() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -475,6 +700,18 @@ const X: u32 = { "#, expect![[r#" fd the_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -491,6 +728,16 @@ fn foo(a: A) { "#, expect![[r#" fd the_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -508,6 +755,16 @@ fn foo(a: A) { "#, expect![[r#" fd the_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -524,6 +781,16 @@ fn foo(a: A) { "#, expect![[r#" fd the_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -550,6 +817,16 @@ fn foo(a: A) { "#, expect![[r#" fd the_field u32 + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -569,6 +846,18 @@ fn foo() { "#, expect![[r#" me the_method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -584,6 +873,18 @@ fn main() { make_s!().f$0; } "#, expect![[r#" me foo() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } @@ -612,6 +913,18 @@ mod foo { "#, expect![[r#" me private() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); } @@ -639,6 +952,16 @@ impl S { "#, expect![[r#" me foo() fn(&self) -> &[u8] + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -654,6 +977,7 @@ impl Foo { fn foo(&self) { $0 } }"#, lc self &Foo sp Self st Foo + bt u32 fd self.field i32 me self.foo() fn(&self) "#]], @@ -667,6 +991,7 @@ impl Foo { fn foo(&mut self) { $0 } }"#, lc self &mut Foo sp Self st Foo + bt u32 fd self.0 i32 me self.foo() fn(&mut self) "#]], @@ -694,6 +1019,16 @@ fn f() { "#, expect![[r#" me method() fn(&self) + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) "#]], ); } @@ -716,6 +1051,18 @@ fn main() { "#, expect![[r#" me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index d7c8c54315..486cbff685 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs @@ -219,1018 +219,3 @@ fn compute_fuzzy_completion_order_key( None => usize::MAX, } } - -#[cfg(test)] -mod tests { - use expect_test::{expect, Expect}; - - use crate::{ - item::CompletionKind, - tests::{check_edit, check_edit_with_config, filtered_completion_list, TEST_CONFIG}, - }; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); - expect.assert_eq(&actual); - } - - #[test] - fn function_fuzzy_completion() { - check_edit( - "stdin", - r#" -//- /lib.rs crate:dep -pub mod io { - pub fn stdin() {} -}; - -//- /main.rs crate:main deps:dep -fn main() { - stdi$0 -} -"#, - r#" -use dep::io::stdin; - -fn main() { - stdin()$0 -} -"#, - ); - } - - #[test] - fn macro_fuzzy_completion() { - check_edit( - "macro_with_curlies!", - r#" -//- /lib.rs crate:dep -/// Please call me as macro_with_curlies! {} -#[macro_export] -macro_rules! macro_with_curlies { - () => {} -} - -//- /main.rs crate:main deps:dep -fn main() { - curli$0 -} -"#, - r#" -use dep::macro_with_curlies; - -fn main() { - macro_with_curlies! {$0} -} -"#, - ); - } - - #[test] - fn struct_fuzzy_completion() { - check_edit( - "ThirdStruct", - r#" -//- /lib.rs crate:dep -pub struct FirstStruct; -pub mod some_module { - pub struct SecondStruct; - pub struct ThirdStruct; -} - -//- /main.rs crate:main deps:dep -use dep::{FirstStruct, some_module::SecondStruct}; - -fn main() { - this$0 -} -"#, - r#" -use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}}; - -fn main() { - ThirdStruct -} -"#, - ); - } - - #[test] - fn short_paths_are_ignored() { - cov_mark::check!(ignore_short_input_for_path); - - check( - r#" -//- /lib.rs crate:dep -pub struct FirstStruct; -pub mod some_module { - pub struct SecondStruct; - pub struct ThirdStruct; -} - -//- /main.rs crate:main deps:dep -use dep::{FirstStruct, some_module::SecondStruct}; - -fn main() { - t$0 -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn fuzzy_completions_come_in_specific_order() { - cov_mark::check!(certain_fuzzy_order_test); - check( - r#" -//- /lib.rs crate:dep -pub struct FirstStruct; -pub mod some_module { - // already imported, omitted - pub struct SecondStruct; - // does not contain all letters from the query, omitted - pub struct UnrelatedOne; - // contains all letters from the query, but not in sequence, displayed last - pub struct ThiiiiiirdStruct; - // contains all letters from the query, but not in the beginning, displayed second - pub struct AfterThirdStruct; - // contains all letters from the query in the begginning, displayed first - pub struct ThirdStruct; -} - -//- /main.rs crate:main deps:dep -use dep::{FirstStruct, some_module::SecondStruct}; - -fn main() { - hir$0 -} -"#, - expect![[r#" - st ThirdStruct (use dep::some_module::ThirdStruct) - st AfterThirdStruct (use dep::some_module::AfterThirdStruct) - st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct) - "#]], - ); - } - - #[test] - fn trait_function_fuzzy_completion() { - let fixture = r#" - //- /lib.rs crate:dep - pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } - } - - //- /main.rs crate:main deps:dep - fn main() { - dep::test_mod::TestStruct::wei$0 - } - "#; - - check( - fixture, - expect![[r#" - fn weird_function() (use dep::test_mod::TestTrait) fn() - "#]], - ); - - check_edit( - "weird_function", - fixture, - r#" -use dep::test_mod::TestTrait; - -fn main() { - dep::test_mod::TestStruct::weird_function()$0 -} -"#, - ); - } - - #[test] - fn trait_const_fuzzy_completion() { - let fixture = r#" - //- /lib.rs crate:dep - pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } - } - - //- /main.rs crate:main deps:dep - fn main() { - dep::test_mod::TestStruct::spe$0 - } - "#; - - check( - fixture, - expect![[r#" - ct SPECIAL_CONST (use dep::test_mod::TestTrait) - "#]], - ); - - check_edit( - "SPECIAL_CONST", - fixture, - r#" -use dep::test_mod::TestTrait; - -fn main() { - dep::test_mod::TestStruct::SPECIAL_CONST -} -"#, - ); - } - - #[test] - fn trait_method_fuzzy_completion() { - let fixture = r#" - //- /lib.rs crate:dep - pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } - } - - //- /main.rs crate:main deps:dep - fn main() { - let test_struct = dep::test_mod::TestStruct {}; - test_struct.ran$0 - } - "#; - - check( - fixture, - expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&self) - "#]], - ); - - check_edit( - "random_method", - fixture, - r#" -use dep::test_mod::TestTrait; - -fn main() { - let test_struct = dep::test_mod::TestStruct {}; - test_struct.random_method()$0 -} -"#, - ); - } - - #[test] - fn no_trait_type_fuzzy_completion() { - check( - r#" -//- /lib.rs crate:dep -pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } -} - -//- /main.rs crate:main deps:dep -fn main() { - dep::test_mod::TestStruct::hum$0 -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn does_not_propose_names_in_scope() { - check( - r#" -//- /lib.rs crate:dep -pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } -} - -//- /main.rs crate:main deps:dep -use dep::test_mod::TestStruct; -fn main() { - TestSt$0 -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn does_not_propose_traits_in_scope() { - check( - r#" -//- /lib.rs crate:dep -pub mod test_mod { - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } -} - -//- /main.rs crate:main deps:dep -use dep::test_mod::{TestStruct, TestTrait}; -fn main() { - dep::test_mod::TestStruct::hum$0 -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn blanket_trait_impl_import() { - check_edit( - "another_function", - r#" -//- /lib.rs crate:dep -pub mod test_mod { - pub struct TestStruct {} - pub trait TestTrait { - fn another_function(); - } - impl TestTrait for T { - fn another_function() {} - } -} - -//- /main.rs crate:main deps:dep -fn main() { - dep::test_mod::TestStruct::ano$0 -} -"#, - r#" -use dep::test_mod::TestTrait; - -fn main() { - dep::test_mod::TestStruct::another_function()$0 -} -"#, - ); - } - - #[test] - fn zero_input_deprecated_assoc_item_completion() { - check( - r#" -//- /lib.rs crate:dep -pub mod test_mod { - #[deprecated] - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } -} - -//- /main.rs crate:main deps:dep -fn main() { - let test_struct = dep::test_mod::TestStruct {}; - test_struct.$0 -} - "#, - expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED - "#]], - ); - - check( - r#" -//- /lib.rs crate:dep -pub mod test_mod { - #[deprecated] - pub trait TestTrait { - const SPECIAL_CONST: u8; - type HumbleType; - fn weird_function(); - fn random_method(&self); - } - pub struct TestStruct {} - impl TestTrait for TestStruct { - const SPECIAL_CONST: u8 = 42; - type HumbleType = (); - fn weird_function() {} - fn random_method(&self) {} - } -} - -//- /main.rs crate:main deps:dep -fn main() { - dep::test_mod::TestStruct::$0 -} -"#, - expect![[r#" - fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED - ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED - "#]], - ); - } - - #[test] - fn no_completions_in_use_statements() { - check( - r#" -//- /lib.rs crate:dep -pub mod io { - pub fn stdin() {} -}; - -//- /main.rs crate:main deps:dep -use stdi$0 - -fn main() {} -"#, - expect![[]], - ); - } - - #[test] - fn prefix_config_usage() { - let fixture = r#" -mod foo { - pub mod bar { - pub struct Item; - } -} - -use crate::foo::bar; - -fn main() { - Ite$0 -}"#; - let mut config = TEST_CONFIG; - - config.insert_use.prefix_kind = hir::PrefixKind::ByCrate; - check_edit_with_config( - config.clone(), - "Item", - fixture, - r#" -mod foo { - pub mod bar { - pub struct Item; - } -} - -use crate::foo::bar::{self, Item}; - -fn main() { - Item -}"#, - ); - - config.insert_use.prefix_kind = hir::PrefixKind::BySelf; - check_edit_with_config( - config.clone(), - "Item", - fixture, - r#" -mod foo { - pub mod bar { - pub struct Item; - } -} - -use crate::foo::bar; - -use self::foo::bar::Item; - -fn main() { - Item -}"#, - ); - - config.insert_use.prefix_kind = hir::PrefixKind::Plain; - check_edit_with_config( - config, - "Item", - fixture, - r#" -mod foo { - pub mod bar { - pub struct Item; - } -} - -use foo::bar::Item; - -use crate::foo::bar; - -fn main() { - Item -}"#, - ); - } - - #[test] - fn unresolved_qualifier() { - let fixture = r#" -mod foo { - pub mod bar { - pub mod baz { - pub struct Item; - } - } -} - -fn main() { - bar::baz::Ite$0 -}"#; - - check( - fixture, - expect![[r#" - st Item (use foo::bar::baz::Item) - "#]], - ); - - check_edit( - "Item", - fixture, - r#" - use foo::bar; - - mod foo { - pub mod bar { - pub mod baz { - pub struct Item; - } - } - } - - fn main() { - bar::baz::Item - }"#, - ); - } - - #[test] - fn unresolved_assoc_item_container() { - let fixture = r#" -mod foo { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } -} - -fn main() { - Item::TEST_A$0 -}"#; - - check( - fixture, - expect![[r#" - ct TEST_ASSOC (use foo::Item) - "#]], - ); - - check_edit( - "TEST_ASSOC", - fixture, - r#" -use foo::Item; - -mod foo { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } -} - -fn main() { - Item::TEST_ASSOC -}"#, - ); - } - - #[test] - fn unresolved_assoc_item_container_with_path() { - let fixture = r#" -mod foo { - pub mod bar { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } - } -} - -fn main() { - bar::Item::TEST_A$0 -}"#; - - check( - fixture, - expect![[r#" - ct TEST_ASSOC (use foo::bar::Item) - "#]], - ); - - check_edit( - "TEST_ASSOC", - fixture, - r#" -use foo::bar; - -mod foo { - pub mod bar { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } - } -} - -fn main() { - bar::Item::TEST_ASSOC -}"#, - ); - } - - #[test] - fn fuzzy_unresolved_path() { - check( - r#" -mod foo { - pub mod bar { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } - } -} - -fn main() { - bar::ASS$0 -}"#, - expect![[]], - ) - } - - #[test] - fn unqualified_assoc_items_are_omitted() { - check( - r#" -mod something { - pub trait BaseTrait { - fn test_function() -> i32; - } - - pub struct Item1; - pub struct Item2; - - impl BaseTrait for Item1 { - fn test_function() -> i32 { - 1 - } - } - - impl BaseTrait for Item2 { - fn test_function() -> i32 { - 2 - } - } -} - -fn main() { - test_f$0 -}"#, - expect![[]], - ) - } - - #[test] - fn case_matters() { - check( - r#" -mod foo { - pub const TEST_CONST: usize = 3; - pub fn test_function() -> i32 { - 4 - } -} - -fn main() { - TE$0 -}"#, - expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - "#]], - ); - - check( - r#" -mod foo { - pub const TEST_CONST: usize = 3; - pub fn test_function() -> i32 { - 4 - } -} - -fn main() { - te$0 -}"#, - expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - fn test_function() (use foo::test_function) fn() -> i32 - "#]], - ); - - check( - r#" -mod foo { - pub const TEST_CONST: usize = 3; - pub fn test_function() -> i32 { - 4 - } -} - -fn main() { - Te$0 -}"#, - expect![[]], - ); - } - - #[test] - fn no_fuzzy_during_fields_of_record_lit_syntax() { - check( - r#" -mod m { - pub fn some_fn() -> i32 { - 42 - } -} -struct Foo { - some_field: i32, -} -fn main() { - let _ = Foo { so$0 }; -} -"#, - expect![[]], - ); - } - - #[test] - fn fuzzy_after_fields_of_record_lit_syntax() { - check( - r#" -mod m { - pub fn some_fn() -> i32 { - 42 - } -} -struct Foo { - some_field: i32, -} -fn main() { - let _ = Foo { some_field: so$0 }; -} -"#, - expect![[r#" - fn some_fn() (use m::some_fn) fn() -> i32 - "#]], - ); - } - - #[test] - fn no_flyimports_in_traits_and_impl_declarations() { - check( - r#" -mod m { - pub fn some_fn() -> i32 { - 42 - } -} -trait Foo { - som$0 -} -"#, - expect![[r#""#]], - ); - - check( - r#" -mod m { - pub fn some_fn() -> i32 { - 42 - } -} -struct Foo; -impl Foo { - som$0 -} -"#, - expect![[r#""#]], - ); - - check( - r#" -mod m { - pub fn some_fn() -> i32 { - 42 - } -} -struct Foo; -trait Bar {} -impl Bar for Foo { - som$0 -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn no_inherent_candidates_proposed() { - check( - r#" -mod baz { - pub trait DefDatabase { - fn method1(&self); - } - pub trait HirDatabase: DefDatabase { - fn method2(&self); - } -} - -mod bar { - fn test(db: &dyn crate::baz::HirDatabase) { - db.metho$0 - } -} - "#, - expect![[r#""#]], - ); - } - - #[test] - fn respects_doc_hidden() { - check( - r#" -//- /lib.rs crate:lib deps:dep -fn f() { - ().fro$0 -} - -//- /dep.rs crate:dep -#[doc(hidden)] -pub trait Private { - fn frob(&self) {} -} - -impl Private for T {} - "#, - expect![[r#""#]], - ); - check( - r#" -//- /lib.rs crate:lib deps:dep -fn f() { - ().fro$0 -} - -//- /dep.rs crate:dep -pub trait Private { - #[doc(hidden)] - fn frob(&self) {} -} - -impl Private for T {} - "#, - expect![[r#""#]], - ); - } - - #[test] - fn regression_9760() { - check( - r#" -struct Struct; -fn main() {} - -mod mud { - fn func() { - let struct_instance = Stru$0 - } -} -"#, - expect![[r#" - st Struct (use crate::Struct) - "#]], - ); - } - - #[test] - fn flyimport_pattern() { - check( - r#" -mod module { - pub struct Struct; -} -fn function() { - let Str$0 -} -"#, - expect![[r#" - st Struct (use module::Struct) - "#]], - ); - } - - #[test] - fn flyimport_rename() { - check( - r#" -mod module { - pub struct Struct; -} -use self as Str$0; - "#, - expect![[r#""#]], - ); - } -} diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 31aabd98d3..4fd622f399 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs @@ -181,115 +181,15 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet mod tests { use expect_test::{expect, Expect}; - use crate::{ - tests::{check_edit, filtered_completion_list}, - CompletionKind, - }; + use crate::tests::{check_edit, completion_list}; fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword); + let actual = completion_list(ra_fixture); expect.assert_eq(&actual) } #[test] - fn test_keywords_in_function() { - check( - r"fn quux() { $0 }", - expect![[r#" - kw unsafe - kw fn - kw const - kw type - kw impl - kw extern - kw use - kw trait - kw static - kw mod - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw let - kw return - kw self - kw super - kw crate - "#]], - ); - } - - #[test] - fn test_keywords_inside_block() { - check( - r"fn quux() { if true { $0 } }", - expect![[r#" - kw unsafe - kw fn - kw const - kw type - kw impl - kw extern - kw use - kw trait - kw static - kw mod - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw let - kw return - kw self - kw super - kw crate - "#]], - ); - } - - #[test] - fn test_keywords_after_if() { - check( - r#"fn quux() { if true { () } $0 }"#, - expect![[r#" - kw unsafe - kw fn - kw const - kw type - kw impl - kw extern - kw use - kw trait - kw static - kw mod - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw let - kw else - kw else if - kw return - kw self - kw super - kw crate - "#]], - ); + fn test_else_edit_after_if() { check_edit( "else", r#"fn quux() { if true { () } $0 }"#, @@ -299,68 +199,6 @@ mod tests { ); } - #[test] - fn test_keywords_in_match_arm() { - check( - r#" -fn quux() -> i32 { - match () { () => $0 } -} -"#, - expect![[r#" - kw unsafe - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw return - kw self - kw super - kw crate - "#]], - ); - } - - #[test] - fn test_keywords_in_loop() { - check( - r"fn my() { loop { $0 } }", - expect![[r#" - kw unsafe - kw fn - kw const - kw type - kw impl - kw extern - kw use - kw trait - kw static - kw mod - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw let - kw continue - kw break - kw return - kw self - kw super - kw crate - "#]], - ); - } - #[test] fn test_keywords_after_unsafe_in_block_expr() { check( @@ -369,38 +207,12 @@ fn quux() -> i32 { kw fn kw trait kw impl + sn pd + sn ppd "#]], ); } - #[test] - fn no_keyword_completion_in_comments() { - cov_mark::check!(no_keyword_completion_in_comments); - check( - r#" -fn test() { - let x = 2; // A comment$0 -} -"#, - expect![[""]], - ); - check( - r#" -/* -Some multi-line comment$0 -*/ -"#, - expect![[""]], - ); - check( - r#" -/// Some doc comment -/// let test$0 = 1 -"#, - expect![[""]], - ); - } - #[test] fn test_completion_await_impls_future() { check( @@ -413,6 +225,18 @@ fn foo(a: A) { a.$0 } "#, expect![[r#" kw await expr.await + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ); @@ -427,83 +251,22 @@ fn foo() { "#, expect![[r#" kw await expr.await + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut "#]], ) } - #[test] - fn after_let() { - check( - r#"fn main() { let _ = $0 }"#, - expect![[r#" - kw unsafe - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw return - kw self - kw super - kw crate - "#]], - ) - } - - #[test] - fn skip_struct_initializer() { - cov_mark::check!(no_keyword_completion_in_record_lit); - check( - r#" -struct Foo { - pub f: i32, -} -fn foo() { - Foo { - $0 - } -} -"#, - expect![[r#""#]], - ); - } - - #[test] - fn struct_initializer_field_expr() { - check( - r#" -struct Foo { - pub f: i32, -} -fn foo() { - Foo { - f: $0 - } -} -"#, - expect![[r#" - kw unsafe - kw match - kw while - kw while let - kw loop - kw if - kw if let - kw for - kw true - kw false - kw return - kw self - kw super - kw crate - "#]], - ); - } - #[test] fn let_semi() { cov_mark::check!(let_semi); diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs index 1c864c0e70..c26fa42d1b 100644 --- a/crates/ide_completion/src/completions/mod_.rs +++ b/crates/ide_completion/src/completions/mod_.rs @@ -141,9 +141,10 @@ fn module_chain_to_containing_module_file( #[cfg(test)] mod tests { - use crate::tests::completion_list; 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); diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs index 4ace346768..87b5d6c472 100644 --- a/crates/ide_completion/src/completions/postfix.rs +++ b/crates/ide_completion/src/completions/postfix.rs @@ -270,12 +270,12 @@ mod tests { use expect_test::{expect, Expect}; use crate::{ - tests::{check_edit, check_edit_with_config, filtered_completion_list, TEST_CONFIG}, - CompletionConfig, CompletionKind, Snippet, + tests::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG}, + CompletionConfig, Snippet, }; fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Postfix); + let actual = completion_list(ra_fixture); expect.assert_eq(&actual) } diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index f61baf184b..e9d39edc43 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -250,13 +250,10 @@ fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enu mod tests { use expect_test::{expect, Expect}; - use crate::{ - tests::{check_edit, filtered_completion_list}, - CompletionKind, - }; + use crate::tests::{check_edit, completion_list_no_kw}; fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); + let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual); } diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs index 31accd035f..37fa001e0c 100644 --- a/crates/ide_completion/src/completions/trait_impl.rs +++ b/crates/ide_completion/src/completions/trait_impl.rs @@ -290,13 +290,10 @@ fn replacement_range(ctx: &CompletionContext, item: &SyntaxNode) -> TextRange { mod tests { use expect_test::{expect, Expect}; - use crate::{ - tests::{check_edit, filtered_completion_list}, - CompletionKind, - }; + use crate::tests::{check_edit, completion_list_no_kw}; fn check(ra_fixture: &str, expect: Expect) { - let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); + let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) } @@ -313,7 +310,12 @@ impl Test for T { } } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); check( @@ -356,7 +358,23 @@ impl Test for T { } } ", - expect![[""]], + expect![[r#" + sn if if expr {} + sn while while expr {} + sn not !expr + sn ref &expr + sn refm &mut expr + sn match match expr {} + sn box Box::new(expr) + sn ok Ok(expr) + sn err Err(expr) + sn some Some(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn call function(expr) + sn let let + sn letm let mut + "#]], ); check( @@ -368,7 +386,10 @@ impl Test for T { fn test(t$0) } ", - expect![[""]], + expect![[r#" + sp Self + st T + "#]], ); check( @@ -380,7 +401,10 @@ impl Test for T { fn test(f: fn $0) } ", - expect![[""]], + expect![[r#" + sp Self + st T + "#]], ); } @@ -395,7 +419,7 @@ impl Test for T { const TEST: fn $0 } ", - expect![[""]], + expect![[r#""#]], ); check( @@ -407,7 +431,12 @@ impl Test for T { const TEST: T$0 } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); check( @@ -419,7 +448,12 @@ impl Test for T { const TEST: u32 = f$0 } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); check( @@ -433,7 +467,12 @@ impl Test for T { }; } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); check( @@ -476,7 +515,12 @@ impl Test for T { type Test = T$0; } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); check( @@ -488,7 +532,12 @@ impl Test for T { type Test = fn $0; } ", - expect![[""]], + expect![[r#" + sp Self + tt Test + st T + bt u32 + "#]], ); } diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index afacf7fe03..825fae587b 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -117,24 +117,15 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC mod tests { use expect_test::{expect, Expect}; - use crate::{ - tests::{check_edit, filtered_completion_list_with_config, TEST_CONFIG}, - CompletionConfig, CompletionKind, - }; + use crate::tests::{check_edit, completion_list_no_kw}; fn check(ra_fixture: &str, expect: Expect) { - check_with_config(TEST_CONFIG, ra_fixture, expect); - } - - fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { - let actual = - filtered_completion_list_with_config(config, ra_fixture, CompletionKind::Reference); + let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) } #[test] fn completes_if_prefix_is_keyword() { - cov_mark::check!(completes_if_prefix_is_keyword); check_edit( "wherewolf", r#" @@ -188,6 +179,7 @@ pub mod prelude { "#, expect![[r#" md std + bt u32 st Option "#]], ); @@ -217,6 +209,7 @@ mod macros { fn f() fn() ma concat!(…) #[macro_export] macro_rules! concat md std + bt u32 "##]], ); } @@ -245,6 +238,7 @@ pub mod prelude { expect![[r#" md std md core + bt u32 st String "#]], ); @@ -273,6 +267,7 @@ pub mod prelude { expect![[r#" fn f() fn() md std + bt u32 "#]], ); } diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 4e3abff3b3..0cb484d507 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -134,7 +134,6 @@ impl<'a> CompletionContext<'a> { // check kind of macro-expanded token, but use range of original token let kind = self.token.kind(); if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() { - cov_mark::hit!(completes_if_prefix_is_keyword); self.original_token.text_range() } else if kind == CHAR { // assume we are completing a lifetime but the user has only typed the ' diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs index 4028fc2242..fee61e0bfc 100644 --- a/crates/ide_completion/src/tests.rs +++ b/crates/ide_completion/src/tests.rs @@ -20,6 +20,7 @@ mod record; mod type_pos; mod use_tree; mod visibility; +mod flyimport; use std::mem; @@ -77,10 +78,18 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { }; pub(crate) fn completion_list(ra_fixture: &str) -> String { - completion_list_with_config(TEST_CONFIG, ra_fixture) + completion_list_with_config(TEST_CONFIG, ra_fixture, true) } -fn completion_list_with_config(config: CompletionConfig, ra_fixture: &str) -> String { +pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String { + completion_list_with_config(TEST_CONFIG, ra_fixture, false) +} + +fn completion_list_with_config( + config: CompletionConfig, + ra_fixture: &str, + include_keywords: bool, +) -> String { // filter out all but one builtintype completion for smaller test outputs let items = get_all_items(config, ra_fixture); let mut bt_seen = false; @@ -89,6 +98,8 @@ fn completion_list_with_config(config: CompletionConfig, ra_fixture: &str) -> St .filter(|it| { it.completion_kind != CompletionKind::BuiltinType || !mem::replace(&mut bt_seen, true) }) + .filter(|it| include_keywords || it.completion_kind != CompletionKind::Keyword) + .filter(|it| include_keywords || it.completion_kind != CompletionKind::Snippet) .collect(); render_completion_list(items) } @@ -120,20 +131,6 @@ pub(crate) fn do_completion_with_config( .collect() } -pub(crate) fn filtered_completion_list(code: &str, kind: CompletionKind) -> String { - filtered_completion_list_with_config(TEST_CONFIG, code, kind) -} - -pub(crate) fn filtered_completion_list_with_config( - config: CompletionConfig, - code: &str, - kind: CompletionKind, -) -> String { - let kind_completions: Vec = - get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect(); - render_completion_list(kind_completions) -} - fn render_completion_list(completions: Vec) -> String { fn monospace_width(s: &str) -> usize { s.chars().count() @@ -254,3 +251,37 @@ fn foo() { "#, ); } + +#[test] +fn no_completions_in_comments() { + cov_mark::check!(no_keyword_completion_in_comments); + assert_eq!( + completion_list( + r#" +fn test() { +let x = 2; // A comment$0 +} +"#, + ), + String::new(), + ); + assert_eq!( + completion_list( + r#" +/* +Some multi-line comment$0 +*/ +"#, + ), + String::new(), + ); + assert_eq!( + completion_list( + r#" +/// Some doc comment +/// let test$0 = 1 +"#, + ), + String::new(), + ); +} diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs index 9a42dd7b27..a634808734 100644 --- a/crates/ide_completion/src/tests/expression.rs +++ b/crates/ide_completion/src/tests/expression.rs @@ -110,7 +110,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) { } #[test] -fn completes_all_the_things() { +fn completes_all_the_things_in_fn_body() { cov_mark::check!(unqualified_skip_lifetime_completion); check( r#" @@ -206,6 +206,223 @@ impl Unit { ); } +#[test] +fn complete_in_block() { + check_empty( + r#" + fn foo() { + if true { + $0 + } + } +"#, + expect![[r#" + kw unsafe + kw fn + kw const + kw type + kw impl + kw extern + kw use + kw trait + kw static + kw mod + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw let + kw return + sn pd + sn ppd + kw self + kw super + kw crate + fn foo() fn() + bt u32 + "#]], + ) +} + +#[test] +fn complete_after_if_expr() { + check_empty( + r#" + fn foo() { + if true {} + $0 + } +"#, + expect![[r#" + kw unsafe + kw fn + kw const + kw type + kw impl + kw extern + kw use + kw trait + kw static + kw mod + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw let + kw else + kw else if + kw return + sn pd + sn ppd + kw self + kw super + kw crate + fn foo() fn() + bt u32 + "#]], + ) +} + +#[test] +fn complete_in_match_arm() { + check_empty( + r#" + fn foo() { + match () { + () => $0 + } + } +"#, + expect![[r#" + kw unsafe + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw return + kw self + kw super + kw crate + fn foo() fn() + bt u32 + "#]], + ) +} + +#[test] +fn completes_in_loop_ctx() { + check_empty( + r"fn my() { loop { $0 } }", + expect![[r#" + kw unsafe + kw fn + kw const + kw type + kw impl + kw extern + kw use + kw trait + kw static + kw mod + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw let + kw continue + kw break + kw return + sn pd + sn ppd + kw self + kw super + kw crate + fn my() fn() + bt u32 + "#]], + ); +} + +#[test] +fn completes_in_let_initializer() { + check_empty( + r#"fn main() { let _ = $0 }"#, + expect![[r#" + kw unsafe + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw return + kw self + kw super + kw crate + fn main() fn() + bt u32 + "#]], + ) +} + +#[test] +fn struct_initializer_field_expr() { + check_empty( + r#" +struct Foo { + pub f: i32, +} +fn foo() { + Foo { + f: $0 + } +} +"#, + expect![[r#" + kw unsafe + kw match + kw while + kw while let + kw loop + kw if + kw if let + kw for + kw true + kw false + kw return + kw self + kw super + kw crate + st Foo + fn foo() fn() + bt u32 + "#]], + ); +} + #[test] fn shadowing_shows_single_completion() { cov_mark::check!(shadowing_shows_single_completion); diff --git a/crates/ide_completion/src/tests/flyimport.rs b/crates/ide_completion/src/tests/flyimport.rs new file mode 100644 index 0000000000..201443e10c --- /dev/null +++ b/crates/ide_completion/src/tests/flyimport.rs @@ -0,0 +1,1014 @@ +use expect_test::{expect, Expect}; + +use crate::tests::{check_edit, check_edit_with_config, TEST_CONFIG}; + +fn check(ra_fixture: &str, expect: Expect) { + let config = TEST_CONFIG; + let (db, position) = crate::tests::position(ra_fixture); + let ctx = crate::context::CompletionContext::new(&db, position, &config).unwrap(); + + let mut acc = crate::completions::Completions::default(); + crate::completions::flyimport::import_on_the_fly(&mut acc, &ctx); + + expect.assert_eq(&super::render_completion_list(Vec::from(acc))); +} + +#[test] +fn function_fuzzy_completion() { + check_edit( + "stdin", + r#" +//- /lib.rs crate:dep +pub mod io { + pub fn stdin() {} +}; + +//- /main.rs crate:main deps:dep +fn main() { + stdi$0 +} +"#, + r#" +use dep::io::stdin; + +fn main() { + stdin()$0 +} +"#, + ); +} + +#[test] +fn macro_fuzzy_completion() { + check_edit( + "macro_with_curlies!", + r#" +//- /lib.rs crate:dep +/// Please call me as macro_with_curlies! {} +#[macro_export] +macro_rules! macro_with_curlies { + () => {} +} + +//- /main.rs crate:main deps:dep +fn main() { + curli$0 +} +"#, + r#" +use dep::macro_with_curlies; + +fn main() { + macro_with_curlies! {$0} +} +"#, + ); +} + +#[test] +fn struct_fuzzy_completion() { + check_edit( + "ThirdStruct", + r#" +//- /lib.rs crate:dep +pub struct FirstStruct; +pub mod some_module { + pub struct SecondStruct; + pub struct ThirdStruct; +} + +//- /main.rs crate:main deps:dep +use dep::{FirstStruct, some_module::SecondStruct}; + +fn main() { + this$0 +} +"#, + r#" +use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}}; + +fn main() { + ThirdStruct +} +"#, + ); +} + +#[test] +fn short_paths_are_ignored() { + cov_mark::check!(ignore_short_input_for_path); + + check( + r#" +//- /lib.rs crate:dep +pub struct FirstStruct; +pub mod some_module { + pub struct SecondStruct; + pub struct ThirdStruct; +} + +//- /main.rs crate:main deps:dep +use dep::{FirstStruct, some_module::SecondStruct}; + +fn main() { + t$0 +} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn fuzzy_completions_come_in_specific_order() { + cov_mark::check!(certain_fuzzy_order_test); + check( + r#" +//- /lib.rs crate:dep +pub struct FirstStruct; +pub mod some_module { + // already imported, omitted + pub struct SecondStruct; + // does not contain all letters from the query, omitted + pub struct UnrelatedOne; + // contains all letters from the query, but not in sequence, displayed last + pub struct ThiiiiiirdStruct; + // contains all letters from the query, but not in the beginning, displayed second + pub struct AfterThirdStruct; + // contains all letters from the query in the begginning, displayed first + pub struct ThirdStruct; +} + +//- /main.rs crate:main deps:dep +use dep::{FirstStruct, some_module::SecondStruct}; + +fn main() { + hir$0 +} +"#, + expect![[r#" + st ThirdStruct (use dep::some_module::ThirdStruct) + st AfterThirdStruct (use dep::some_module::AfterThirdStruct) + st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct) + "#]], + ); +} + +#[test] +fn trait_function_fuzzy_completion() { + let fixture = r#" + //- /lib.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } + } + + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::wei$0 + } + "#; + + check( + fixture, + expect![[r#" + fn weird_function() (use dep::test_mod::TestTrait) fn() + "#]], + ); + + check_edit( + "weird_function", + fixture, + r#" +use dep::test_mod::TestTrait; + +fn main() { + dep::test_mod::TestStruct::weird_function()$0 +} +"#, + ); +} + +#[test] +fn trait_const_fuzzy_completion() { + let fixture = r#" + //- /lib.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } + } + + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::spe$0 + } + "#; + + check( + fixture, + expect![[r#" + ct SPECIAL_CONST (use dep::test_mod::TestTrait) + "#]], + ); + + check_edit( + "SPECIAL_CONST", + fixture, + r#" +use dep::test_mod::TestTrait; + +fn main() { + dep::test_mod::TestStruct::SPECIAL_CONST +} +"#, + ); +} + +#[test] +fn trait_method_fuzzy_completion() { + let fixture = r#" + //- /lib.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } + } + + //- /main.rs crate:main deps:dep + fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.ran$0 + } + "#; + + check( + fixture, + expect![[r#" + me random_method() (use dep::test_mod::TestTrait) fn(&self) + "#]], + ); + + check_edit( + "random_method", + fixture, + r#" +use dep::test_mod::TestTrait; + +fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.random_method()$0 +} +"#, + ); +} + +#[test] +fn no_trait_type_fuzzy_completion() { + check( + r#" +//- /lib.rs crate:dep +pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } +} + +//- /main.rs crate:main deps:dep +fn main() { + dep::test_mod::TestStruct::hum$0 +} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn does_not_propose_names_in_scope() { + check( + r#" +//- /lib.rs crate:dep +pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } +} + +//- /main.rs crate:main deps:dep +use dep::test_mod::TestStruct; +fn main() { + TestSt$0 +} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn does_not_propose_traits_in_scope() { + check( + r#" +//- /lib.rs crate:dep +pub mod test_mod { + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } +} + +//- /main.rs crate:main deps:dep +use dep::test_mod::{TestStruct, TestTrait}; +fn main() { + dep::test_mod::TestStruct::hum$0 +} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn blanket_trait_impl_import() { + check_edit( + "another_function", + r#" +//- /lib.rs crate:dep +pub mod test_mod { + pub struct TestStruct {} + pub trait TestTrait { + fn another_function(); + } + impl TestTrait for T { + fn another_function() {} + } +} + +//- /main.rs crate:main deps:dep +fn main() { + dep::test_mod::TestStruct::ano$0 +} +"#, + r#" +use dep::test_mod::TestTrait; + +fn main() { + dep::test_mod::TestStruct::another_function()$0 +} +"#, + ); +} + +#[test] +fn zero_input_deprecated_assoc_item_completion() { + check( + r#" +//- /lib.rs crate:dep +pub mod test_mod { + #[deprecated] + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } +} + +//- /main.rs crate:main deps:dep +fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.$0 +} + "#, + expect![[r#" + me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED + "#]], + ); + + check( + r#" +//- /lib.rs crate:dep +pub mod test_mod { + #[deprecated] + pub trait TestTrait { + const SPECIAL_CONST: u8; + type HumbleType; + fn weird_function(); + fn random_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const SPECIAL_CONST: u8 = 42; + type HumbleType = (); + fn weird_function() {} + fn random_method(&self) {} + } +} + +//- /main.rs crate:main deps:dep +fn main() { + dep::test_mod::TestStruct::$0 +} +"#, + expect![[r#" + fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED + ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED + "#]], + ); +} + +#[test] +fn no_completions_in_use_statements() { + check( + r#" +//- /lib.rs crate:dep +pub mod io { + pub fn stdin() {} +}; + +//- /main.rs crate:main deps:dep +use stdi$0 + +fn main() {} +"#, + expect![[]], + ); +} + +#[test] +fn prefix_config_usage() { + let fixture = r#" +mod foo { + pub mod bar { + pub struct Item; + } +} + +use crate::foo::bar; + +fn main() { + Ite$0 +}"#; + let mut config = TEST_CONFIG; + + config.insert_use.prefix_kind = hir::PrefixKind::ByCrate; + check_edit_with_config( + config.clone(), + "Item", + fixture, + r#" +mod foo { + pub mod bar { + pub struct Item; + } +} + +use crate::foo::bar::{self, Item}; + +fn main() { + Item +}"#, + ); + + config.insert_use.prefix_kind = hir::PrefixKind::BySelf; + check_edit_with_config( + config.clone(), + "Item", + fixture, + r#" +mod foo { + pub mod bar { + pub struct Item; + } +} + +use crate::foo::bar; + +use self::foo::bar::Item; + +fn main() { + Item +}"#, + ); + + config.insert_use.prefix_kind = hir::PrefixKind::Plain; + check_edit_with_config( + config, + "Item", + fixture, + r#" +mod foo { + pub mod bar { + pub struct Item; + } +} + +use foo::bar::Item; + +use crate::foo::bar; + +fn main() { + Item +}"#, + ); +} + +#[test] +fn unresolved_qualifier() { + let fixture = r#" +mod foo { + pub mod bar { + pub mod baz { + pub struct Item; + } + } +} + +fn main() { + bar::baz::Ite$0 +}"#; + + check( + fixture, + expect![[r#" + st Item (use foo::bar::baz::Item) + "#]], + ); + + check_edit( + "Item", + fixture, + r#" + use foo::bar; + + mod foo { + pub mod bar { + pub mod baz { + pub struct Item; + } + } + } + + fn main() { + bar::baz::Item + }"#, + ); +} + +#[test] +fn unresolved_assoc_item_container() { + let fixture = r#" +mod foo { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } +} + +fn main() { + Item::TEST_A$0 +}"#; + + check( + fixture, + expect![[r#" + ct TEST_ASSOC (use foo::Item) + "#]], + ); + + check_edit( + "TEST_ASSOC", + fixture, + r#" +use foo::Item; + +mod foo { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } +} + +fn main() { + Item::TEST_ASSOC +}"#, + ); +} + +#[test] +fn unresolved_assoc_item_container_with_path() { + let fixture = r#" +mod foo { + pub mod bar { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } + } +} + +fn main() { + bar::Item::TEST_A$0 +}"#; + + check( + fixture, + expect![[r#" + ct TEST_ASSOC (use foo::bar::Item) + "#]], + ); + + check_edit( + "TEST_ASSOC", + fixture, + r#" +use foo::bar; + +mod foo { + pub mod bar { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } + } +} + +fn main() { + bar::Item::TEST_ASSOC +}"#, + ); +} + +#[test] +fn fuzzy_unresolved_path() { + check( + r#" +mod foo { + pub mod bar { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } + } +} + +fn main() { + bar::ASS$0 +}"#, + expect![[]], + ) +} + +#[test] +fn unqualified_assoc_items_are_omitted() { + check( + r#" +mod something { + pub trait BaseTrait { + fn test_function() -> i32; + } + + pub struct Item1; + pub struct Item2; + + impl BaseTrait for Item1 { + fn test_function() -> i32 { + 1 + } + } + + impl BaseTrait for Item2 { + fn test_function() -> i32 { + 2 + } + } +} + +fn main() { + test_f$0 +}"#, + expect![[]], + ) +} + +#[test] +fn case_matters() { + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + TE$0 +}"#, + expect![[r#" + ct TEST_CONST (use foo::TEST_CONST) + "#]], + ); + + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + te$0 +}"#, + expect![[r#" + ct TEST_CONST (use foo::TEST_CONST) + fn test_function() (use foo::test_function) fn() -> i32 + "#]], + ); + + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + Te$0 +}"#, + expect![[]], + ); +} + +#[test] +fn no_fuzzy_during_fields_of_record_lit_syntax() { + check( + r#" +mod m { + pub fn some_fn() -> i32 { + 42 + } +} +struct Foo { + some_field: i32, +} +fn main() { + let _ = Foo { so$0 }; +} +"#, + expect![[]], + ); +} + +#[test] +fn fuzzy_after_fields_of_record_lit_syntax() { + check( + r#" +mod m { + pub fn some_fn() -> i32 { + 42 + } +} +struct Foo { + some_field: i32, +} +fn main() { + let _ = Foo { some_field: so$0 }; +} +"#, + expect![[r#" + fn some_fn() (use m::some_fn) fn() -> i32 + "#]], + ); +} + +#[test] +fn no_flyimports_in_traits_and_impl_declarations() { + check( + r#" +mod m { + pub fn some_fn() -> i32 { + 42 + } +} +trait Foo { + som$0 +} +"#, + expect![[r#""#]], + ); + + check( + r#" +mod m { + pub fn some_fn() -> i32 { + 42 + } +} +struct Foo; +impl Foo { + som$0 +} +"#, + expect![[r#""#]], + ); + + check( + r#" +mod m { + pub fn some_fn() -> i32 { + 42 + } +} +struct Foo; +trait Bar {} +impl Bar for Foo { + som$0 +} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn no_inherent_candidates_proposed() { + check( + r#" +mod baz { + pub trait DefDatabase { + fn method1(&self); + } + pub trait HirDatabase: DefDatabase { + fn method2(&self); + } +} + +mod bar { + fn test(db: &dyn crate::baz::HirDatabase) { + db.metho$0 + } +} + "#, + expect![[r#""#]], + ); +} + +#[test] +fn respects_doc_hidden() { + check( + r#" +//- /lib.rs crate:lib deps:dep +fn f() { + ().fro$0 +} + +//- /dep.rs crate:dep +#[doc(hidden)] +pub trait Private { + fn frob(&self) {} +} + +impl Private for T {} + "#, + expect![[r#""#]], + ); + check( + r#" +//- /lib.rs crate:lib deps:dep +fn f() { + ().fro$0 +} + +//- /dep.rs crate:dep +pub trait Private { + #[doc(hidden)] + fn frob(&self) {} +} + +impl Private for T {} + "#, + expect![[r#""#]], + ); +} + +#[test] +fn regression_9760() { + check( + r#" +struct Struct; +fn main() {} + +mod mud { + fn func() { + let struct_instance = Stru$0 + } +} +"#, + expect![[r#" + st Struct (use crate::Struct) + "#]], + ); +} + +#[test] +fn flyimport_pattern() { + check( + r#" +mod module { + pub struct Struct; +} +fn function() { + let Str$0 +} +"#, + expect![[r#" + st Struct (use module::Struct) + "#]], + ); +} + +#[test] +fn flyimport_rename() { + check( + r#" +mod module { + pub struct Struct; +} +use self as Str$0; + "#, + expect![[r#""#]], + ); +} diff --git a/crates/ide_completion/src/tests/record.rs b/crates/ide_completion/src/tests/record.rs index 30b1f2c1c9..e09e99aad5 100644 --- a/crates/ide_completion/src/tests/record.rs +++ b/crates/ide_completion/src/tests/record.rs @@ -9,6 +9,7 @@ fn check(ra_fixture: &str, expect: Expect) { #[test] fn without_default_impl() { + cov_mark::check!(no_keyword_completion_in_record_lit); check( r#" struct Struct { foo: u32, bar: usize } diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index 9be9f3afea..5debb9fb3d 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -313,6 +313,7 @@ fn check_dbg(path: &Path, text: &str) { "handlers/remove_dbg.rs", // We have .dbg postfix "ide_completion/src/completions/postfix.rs", + "ide_completion/src/completions/keyword.rs", "ide_completion/src/tests/proc_macros.rs", // The documentation in string literals may contain anything for its own purposes "ide_completion/src/lib.rs",