Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/qualified_path.rs')
-rw-r--r--crates/ide-completion/src/completions/qualified_path.rs670
1 files changed, 0 insertions, 670 deletions
diff --git a/crates/ide-completion/src/completions/qualified_path.rs b/crates/ide-completion/src/completions/qualified_path.rs
deleted file mode 100644
index d12f8490bd..0000000000
--- a/crates/ide-completion/src/completions/qualified_path.rs
+++ /dev/null
@@ -1,670 +0,0 @@
-//! Completion of paths, i.e. `some::prefix::$0`.
-
-use hir::{ScopeDef, Trait};
-use ide_db::FxHashSet;
-use syntax::ast;
-
-use crate::{
- context::{PathCompletionCtx, PathKind},
- CompletionContext, Completions,
-};
-
-pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
- if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
- return;
- }
- if ctx.pattern_ctx.is_some() {
- return;
- }
- let (qualifier, kind) = match ctx.path_context {
- // let ... else, syntax would come in really handy here right now
- Some(PathCompletionCtx { qualifier: Some(ref qualifier), kind, .. }) => (qualifier, kind),
- _ => return,
- };
- let traits_in_scope = |ctx: &CompletionContext| {
- let mut traits_in_scope = ctx.scope.visible_traits();
- if let Some(drop) = ctx.famous_defs().core_ops_Drop() {
- traits_in_scope.remove(&drop.into());
- }
- traits_in_scope
- };
-
- // special case `<_>::$0` as this doesn't resolve to anything.
- if qualifier.path.qualifier().is_none() {
- if matches!(
- qualifier.path.segment().and_then(|it| it.kind()),
- Some(ast::PathSegmentKind::Type {
- type_ref: Some(ast::Type::InferType(_)),
- trait_ref: None,
- })
- ) {
- cov_mark::hit!(completion_type_anchor_empty);
- traits_in_scope(ctx)
- .into_iter()
- .flat_map(|it| Trait::from(it).items(ctx.sema.db))
- .for_each(|item| add_assoc_item(acc, ctx, item));
- return;
- }
- }
-
- let resolution = match &qualifier.resolution {
- Some(res) => res,
- None => return,
- };
-
- match kind {
- Some(
- PathKind::Pat
- | PathKind::Attr { .. }
- | PathKind::Vis { .. }
- | PathKind::Use
- | PathKind::Item
- | PathKind::Derive,
- ) => {
- return;
- }
- _ => {
- // Add associated types on type parameters and `Self`.
- ctx.scope.assoc_type_shorthand_candidates(resolution, |_, alias| {
- acc.add_type_alias(ctx, alias);
- None::<()>
- });
- }
- }
-
- match resolution {
- hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
- let module_scope = module.scope(ctx.db, Some(ctx.module));
- for (name, def) in module_scope {
- let add_resolution = match def {
- // Don't suggest attribute macros and derives.
- ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
- // no values in type places
- ScopeDef::ModuleDef(
- hir::ModuleDef::Function(_)
- | hir::ModuleDef::Variant(_)
- | hir::ModuleDef::Static(_),
- )
- | ScopeDef::Local(_) => !ctx.expects_type(),
- // unless its a constant in a generic arg list position
- ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
- !ctx.expects_type() || ctx.expects_generic_arg()
- }
- _ => true,
- };
-
- if add_resolution {
- acc.add_resolution(ctx, name, def);
- }
- }
- }
- hir::PathResolution::Def(
- def @ (hir::ModuleDef::Adt(_)
- | hir::ModuleDef::TypeAlias(_)
- | hir::ModuleDef::BuiltinType(_)),
- ) => {
- if let &hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
- add_enum_variants(acc, ctx, e);
- }
- let ty = match def {
- hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
- hir::ModuleDef::TypeAlias(a) => {
- let ty = a.ty(ctx.db);
- if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
- cov_mark::hit!(completes_variant_through_alias);
- add_enum_variants(acc, ctx, e);
- }
- ty
- }
- hir::ModuleDef::BuiltinType(builtin) => {
- cov_mark::hit!(completes_primitive_assoc_const);
- builtin.ty(ctx.db)
- }
- _ => unreachable!(),
- };
-
- // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
- // (where AssocType is defined on a trait, not an inherent impl)
-
- let traits_in_scope = traits_in_scope(ctx);
- ty.iterate_path_candidates(
- ctx.db,
- &ctx.scope,
- &traits_in_scope,
- Some(ctx.module),
- None,
- |item| {
- add_assoc_item(acc, ctx, item);
- None::<()>
- },
- );
-
- // Iterate assoc types separately
- ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
- if let hir::AssocItem::TypeAlias(ty) = item {
- acc.add_type_alias(ctx, ty)
- }
- None::<()>
- });
- }
- hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
- // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
- for item in t.items(ctx.db) {
- add_assoc_item(acc, ctx, item);
- }
- }
- hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
- let ty = match resolution {
- hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
- hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
- _ => return,
- };
-
- if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
- add_enum_variants(acc, ctx, e);
- }
- let traits_in_scope = traits_in_scope(ctx);
- let mut seen = FxHashSet::default();
- ty.iterate_path_candidates(
- ctx.db,
- &ctx.scope,
- &traits_in_scope,
- Some(ctx.module),
- None,
- |item| {
- // We might iterate candidates of a trait multiple times here, so deduplicate
- // them.
- if seen.insert(item) {
- add_assoc_item(acc, ctx, item);
- }
- None::<()>
- },
- );
- }
- _ => {}
- }
-}
-
-fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
- match item {
- hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
- hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
- acc.add_const(ctx, ct)
- }
- hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
- _ => (),
- }
-}
-
-fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
- if ctx.expects_type() {
- return;
- }
- e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
-}
-
-#[cfg(test)]
-mod tests {
- 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 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 {
- fn wrong_fn() {}
- const WRONG_CONST: u32 = 1;
- 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 {
- fn wrong_fn() {}
- const WRONG_CONST: u32 = 1;
- 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 {
- fn wrong_fn() {}
- const WRONG_CONST: u32 = 1;
- 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() {
- 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_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_hidden() {
- cov_mark::check!(qualified_path_doc_hidden);
- 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() {
- cov_mark::check!(completion_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
- "#]],
- )
- }
-}