diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs | 895 |
1 files changed, 895 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs new file mode 100644 index 000000000..033dc99c2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -0,0 +1,895 @@ +//! Tests that don't fit into a specific category. + +use expect_test::{expect, Expect}; + +use crate::tests::{check_edit, completion_list_no_kw}; + +fn check(ra_fixture: &str, expect: Expect) { + let actual = completion_list_no_kw(ra_fixture); + expect.assert_eq(&actual) +} + +#[test] +fn completes_if_prefix_is_keyword() { + check_edit( + "wherewolf", + r#" +fn main() { + let wherewolf = 92; + drop(where$0) +} +"#, + r#" +fn main() { + let wherewolf = 92; + drop(wherewolf) +} +"#, + ) +} + +/// Regression test for issue #6091. +#[test] +fn correctly_completes_module_items_prefixed_with_underscore() { + check_edit( + "_alpha", + r#" +fn main() { + _$0 +} +fn _alpha() {} +"#, + r#" +fn main() { + _alpha()$0 +} +fn _alpha() {} +"#, + ) +} + +#[test] +fn completes_prelude() { + check( + r#" +//- /main.rs crate:main deps:std +fn foo() { let x: $0 } + +//- /std/lib.rs crate:std +pub mod prelude { + pub mod rust_2018 { + pub struct Option; + } +} +"#, + expect![[r#" + md std + st Option + bt u32 + "#]], + ); +} + +#[test] +fn completes_prelude_macros() { + check( + r#" +//- /main.rs crate:main deps:std +fn f() {$0} + +//- /std/lib.rs crate:std +pub mod prelude { + pub mod rust_2018 { + pub use crate::concat; + } +} + +mod macros { + #[rustc_builtin_macro] + #[macro_export] + macro_rules! concat { } +} +"#, + expect![[r#" + fn f() fn() + ma concat!(…) macro_rules! concat + md std + bt u32 + "#]], + ); +} + +#[test] +fn completes_std_prelude_if_core_is_defined() { + check( + r#" +//- /main.rs crate:main deps:core,std +fn foo() { let x: $0 } + +//- /core/lib.rs crate:core +pub mod prelude { + pub mod rust_2018 { + pub struct Option; + } +} + +//- /std/lib.rs crate:std deps:core +pub mod prelude { + pub mod rust_2018 { + pub struct String; + } +} +"#, + expect![[r#" + md core + md std + st String + bt u32 + "#]], + ); +} + +#[test] +fn respects_doc_hidden() { + check( + r#" +//- /lib.rs crate:lib deps:std +fn f() { + format_$0 +} + +//- /std.rs crate:std +#[doc(hidden)] +#[macro_export] +macro_rules! format_args_nl { + () => {} +} + +pub mod prelude { + pub mod rust_2018 {} +} + "#, + expect![[r#" + fn f() fn() + md std + bt u32 + "#]], + ); +} + +#[test] +fn respects_doc_hidden_in_assoc_item_list() { + check( + r#" +//- /lib.rs crate:lib deps:std +struct S; +impl S { + format_$0 +} + +//- /std.rs crate:std +#[doc(hidden)] +#[macro_export] +macro_rules! format_args_nl { + () => {} +} + +pub mod prelude { + pub mod rust_2018 {} +} + "#, + expect![[r#" + md std + "#]], + ); +} + +#[test] +fn associated_item_visibility() { + check( + r#" +//- /lib.rs crate:lib new_source_root:library +pub struct S; + +impl S { + pub fn public_method() { } + fn private_method() { } + pub type PublicType = u32; + type PrivateType = u32; + pub const PUBLIC_CONST: u32 = 1; + const PRIVATE_CONST: u32 = 1; +} + +//- /main.rs crate:main deps:lib new_source_root:local +fn foo() { let _ = lib::S::$0 } +"#, + expect![[r#" + ct PUBLIC_CONST pub const PUBLIC_CONST: u32 + fn public_method() fn() + ta PublicType pub type PublicType = u32 + "#]], + ); +} + +#[test] +fn completes_union_associated_method() { + check( + r#" +union U {}; +impl U { fn m() { } } + +fn foo() { let _ = U::$0 } +"#, + expect![[r#" + fn m() fn() + "#]], + ); +} + +#[test] +fn completes_trait_associated_method_1() { + check( + r#" +trait Trait { fn m(); } + +fn foo() { let _ = Trait::$0 } +"#, + expect![[r#" + fn m() (as Trait) fn() + "#]], + ); +} + +#[test] +fn completes_trait_associated_method_2() { + check( + r#" +trait Trait { fn m(); } + +struct S; +impl Trait for S {} + +fn foo() { let _ = S::$0 } +"#, + expect![[r#" + fn m() (as Trait) fn() + "#]], + ); +} + +#[test] +fn completes_trait_associated_method_3() { + check( + r#" +trait Trait { fn m(); } + +struct S; +impl Trait for S {} + +fn foo() { let _ = <S as Trait>::$0 } +"#, + expect![[r#" + fn m() (as Trait) fn() + "#]], + ); +} + +#[test] +fn completes_ty_param_assoc_ty() { + check( + r#" +trait Super { + type Ty; + const CONST: u8; + fn func() {} + fn method(&self) {} +} + +trait Sub: Super { + type SubTy; + const C2: (); + fn subfunc() {} + fn submethod(&self) {} +} + +fn foo<T: Sub>() { T::$0 } +"#, + expect![[r#" + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty + me method(…) (as Super) fn(&self) + me submethod(…) (as Sub) fn(&self) + "#]], + ); +} + +#[test] +fn completes_self_param_assoc_ty() { + check( + r#" +trait Super { + type Ty; + const CONST: u8 = 0; + fn func() {} + fn method(&self) {} +} + +trait Sub: Super { + type SubTy; + const C2: () = (); + fn subfunc() {} + fn submethod(&self) {} +} + +struct Wrap<T>(T); +impl<T> Super for Wrap<T> {} +impl<T> Sub for Wrap<T> { + fn subfunc() { + // Should be able to assume `Self: Sub + Super` + Self::$0 + } +} +"#, + expect![[r#" + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty + me method(…) (as Super) fn(&self) + me submethod(…) (as Sub) fn(&self) + "#]], + ); +} + +#[test] +fn completes_type_alias() { + check( + r#" +struct S; +impl S { fn foo() {} } +type T = S; +impl T { fn bar() {} } + +fn main() { T::$0; } +"#, + expect![[r#" + fn bar() fn() + fn foo() fn() + "#]], + ); +} + +#[test] +fn completes_qualified_macros() { + check( + r#" +#[macro_export] +macro_rules! foo { () => {} } + +fn main() { let _ = crate::$0 } +"#, + expect![[r#" + fn main() fn() + ma foo!(…) macro_rules! foo + "#]], + ); +} + +#[test] +fn does_not_complete_non_fn_macros() { + check( + r#" +mod m { + #[rustc_builtin_macro] + pub macro Clone {} +} + +fn f() {m::$0} +"#, + expect![[r#""#]], + ); + check( + r#" +mod m { + #[rustc_builtin_macro] + pub macro bench {} +} + +fn f() {m::$0} +"#, + expect![[r#""#]], + ); +} + +#[test] +fn completes_reexported_items_under_correct_name() { + check( + r#" +fn foo() { self::m::$0 } + +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 { + pub fn wrong_fn() {} + pub const WRONG_CONST: u32 = 1; + pub struct WrongType {}; +} +"#, + expect![[r#" + ct RIGHT_CONST + fn right_fn() fn() + st RightType + "#]], + ); + + check_edit( + "RightType", + r#" +fn foo() { self::m::$0 } + +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 { + pub fn wrong_fn() {} + pub const WRONG_CONST: u32 = 1; + pub struct WrongType {}; +} +"#, + r#" +fn foo() { self::m::RightType } + +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 { + pub fn wrong_fn() {} + pub const WRONG_CONST: u32 = 1; + pub struct WrongType {}; +} +"#, + ); +} + +#[test] +fn completes_in_simple_macro_call() { + check( + r#" +macro_rules! m { ($e:expr) => { $e } } +fn main() { m!(self::f$0); } +fn foo() {} +"#, + expect![[r#" + fn foo() fn() + fn main() fn() + "#]], + ); +} + +#[test] +fn function_mod_share_name() { + check( + r#" +fn foo() { self::m::$0 } + +mod m { + pub mod z {} + pub fn z() {} +} +"#, + expect![[r#" + fn z() fn() + md z + "#]], + ); +} + +#[test] +fn completes_hashmap_new() { + check( + r#" +struct RandomState; +struct HashMap<K, V, S = RandomState> {} + +impl<K, V> HashMap<K, V, RandomState> { + pub fn new() -> HashMap<K, V, RandomState> { } +} +fn foo() { + HashMap::$0 +} +"#, + expect![[r#" + fn new() fn() -> HashMap<K, V, RandomState> + "#]], + ); +} + +#[test] +fn completes_variant_through_self() { + cov_mark::check!(completes_variant_through_self); + check( + r#" +enum Foo { + Bar, + Baz, +} + +impl Foo { + fn foo(self) { + Self::$0 + } +} +"#, + expect![[r#" + ev Bar Bar + ev Baz Baz + me foo(…) fn(self) + "#]], + ); +} + +#[test] +fn completes_non_exhaustive_variant_within_the_defining_crate() { + check( + r#" +enum Foo { + #[non_exhaustive] + Bar, + Baz, +} + +fn foo(self) { + Foo::$0 +} +"#, + expect![[r#" + ev Bar Bar + ev Baz Baz + "#]], + ); + + check( + r#" +//- /main.rs crate:main deps:e +fn foo(self) { + e::Foo::$0 +} + +//- /e.rs crate:e +enum Foo { + #[non_exhaustive] + Bar, + Baz, +} +"#, + expect![[r#" + ev Baz Baz + "#]], + ); +} + +#[test] +fn completes_primitive_assoc_const() { + cov_mark::check!(completes_primitive_assoc_const); + check( + r#" +//- /lib.rs crate:lib deps:core +fn f() { + u8::$0 +} + +//- /core.rs crate:core +#[lang = "u8"] +impl u8 { + pub const MAX: Self = 255; + + pub fn func(self) {} +} +"#, + expect![[r#" + ct MAX pub const MAX: Self + me func(…) fn(self) + "#]], + ); +} + +#[test] +fn completes_variant_through_alias() { + cov_mark::check!(completes_variant_through_alias); + check( + r#" +enum Foo { + Bar +} +type Foo2 = Foo; +fn main() { + Foo2::$0 +} +"#, + expect![[r#" + ev Bar Bar + "#]], + ); +} + +#[test] +fn respects_doc_hidden2() { + check( + r#" +//- /lib.rs crate:lib deps:dep +fn f() { + dep::$0 +} + +//- /dep.rs crate:dep +#[doc(hidden)] +#[macro_export] +macro_rules! m { + () => {} +} + +#[doc(hidden)] +pub fn f() {} + +#[doc(hidden)] +pub struct S; + +#[doc(hidden)] +pub mod m {} + "#, + expect![[r#""#]], + ) +} + +#[test] +fn type_anchor_empty() { + check( + r#" +trait Foo { + fn foo() -> Self; +} +struct Bar; +impl Foo for Bar { + fn foo() -> { + Bar + } +} +fn bar() -> Bar { + <_>::$0 +} +"#, + expect![[r#" + fn foo() (as Foo) fn() -> Self + "#]], + ); +} + +#[test] +fn type_anchor_type() { + check( + r#" +trait Foo { + fn foo() -> Self; +} +struct Bar; +impl Bar { + fn bar() {} +} +impl Foo for Bar { + fn foo() -> { + Bar + } +} +fn bar() -> Bar { + <Bar>::$0 +} +"#, + expect![[r#" + fn bar() fn() + fn foo() (as Foo) fn() -> Self + "#]], + ); +} + +#[test] +fn type_anchor_type_trait() { + check( + r#" +trait Foo { + fn foo() -> Self; +} +struct Bar; +impl Bar { + fn bar() {} +} +impl Foo for Bar { + fn foo() -> { + Bar + } +} +fn bar() -> Bar { + <Bar as Foo>::$0 +} +"#, + expect![[r#" + fn foo() (as Foo) fn() -> Self + "#]], + ); +} + +#[test] +fn completes_fn_in_pub_trait_generated_by_macro() { + check( + r#" +mod other_mod { + macro_rules! make_method { + ($name:ident) => { + fn $name(&self) {} + }; + } + + pub trait MyTrait { + make_method! { by_macro } + fn not_by_macro(&self) {} + } + + pub struct Foo {} + + impl MyTrait for Foo {} +} + +fn main() { + use other_mod::{Foo, MyTrait}; + let f = Foo {}; + f.$0 +} +"#, + expect![[r#" + me by_macro() (as MyTrait) fn(&self) + me not_by_macro() (as MyTrait) fn(&self) + "#]], + ) +} + +#[test] +fn completes_fn_in_pub_trait_generated_by_recursive_macro() { + check( + r#" +mod other_mod { + macro_rules! make_method { + ($name:ident) => { + fn $name(&self) {} + }; + } + + macro_rules! make_trait { + () => { + pub trait MyTrait { + make_method! { by_macro } + fn not_by_macro(&self) {} + } + } + } + + make_trait!(); + + pub struct Foo {} + + impl MyTrait for Foo {} +} + +fn main() { + use other_mod::{Foo, MyTrait}; + let f = Foo {}; + f.$0 +} +"#, + expect![[r#" + me by_macro() (as MyTrait) fn(&self) + me not_by_macro() (as MyTrait) fn(&self) + "#]], + ) +} + +#[test] +fn completes_const_in_pub_trait_generated_by_macro() { + check( + r#" +mod other_mod { + macro_rules! make_const { + ($name:ident) => { + const $name: u8 = 1; + }; + } + + pub trait MyTrait { + make_const! { by_macro } + } + + pub struct Foo {} + + impl MyTrait for Foo {} +} + +fn main() { + use other_mod::{Foo, MyTrait}; + let f = Foo {}; + Foo::$0 +} +"#, + expect![[r#" + ct by_macro (as MyTrait) pub const by_macro: u8 + "#]], + ) +} + +#[test] +fn completes_locals_from_macros() { + check( + r#" + +macro_rules! x { + ($x:ident, $expr:expr) => { + let $x = 0; + $expr + }; +} +fn main() { + x! { + foobar, { + f$0 + } + }; +} +"#, + expect![[r#" + fn main() fn() + lc foobar i32 + ma x!(…) macro_rules! x + bt u32 + "#]], + ) +} + +#[test] +fn regression_12644() { + check( + r#" +macro_rules! __rust_force_expr { + ($e:expr) => { + $e + }; +} +macro_rules! vec { + ($elem:expr) => { + __rust_force_expr!($elem) + }; +} + +struct Struct; +impl Struct { + fn foo(self) {} +} + +fn f() { + vec![Struct].$0; +} +"#, + expect![[r#" + me foo() fn(self) + "#]], + ); +} |